3

为了模拟应用程序的完全重启(GNU C 版本 4.1.2 (arm-linux-gnueabi)),包括静态变量初始化,我尝试根据请求将 jmp/longjmp 设置为 gcc pre_init 挂钩函数。longjmp 实际上到达了.preinit_array函数,但是在退出时它会与 SIGSEGV 一起崩溃。

知道为什么这会出错吗?这通常应该可行吗?在 gdbserver 的控制下,是否有其他方法可以将 Linux 应用程序回滚到其初始状态?

添加来源:

static jmp_buf reset_simulation_jumpbuf __attribute__ ((section (".noinit")));
int preinit(int argc, char **argv, char **envp)
{
  // at this point no static variables shall be initialized
  setjmp(reset_simulation_jumpbuf);
}
// gcc standard linker scripts are calling this function before initialization
__attribute__((section(".preinit_array"))) typeof(preinit) *__preinit = preinit;

int main(void)
{
  // at this point all static variables are initialized
  do_something();
  if (reset)
    longjmp(reset_simulation_jumpbuf,1);
}
4

1 回答 1

0

很难完全确定,但我最好的猜测是你的跳转点是在静态变量初始化之前,但它可能是在 C 堆栈设置之后,可能是段寄存器和我不太熟悉的其他 ARM 内部。

在这一点上,有几个潜在的问题可能会导致您出现问题。预初始化代码可能与具有不同权限的先前代码位于不同的段中,从而导致 SIGSEGV。堆栈可能处于与正在运行的代码不兼容的状态(上面留下了太多的用户数据,没有足够的空间容纳一些 init 结构),并且分配的东西跨越了段边界。您的处理器初始化代码可能在代码中的这一点之后保护了一些寄存器,但假设它现在仍然不受保护,并且您的 longjmp 没有取消保护它。这些只是我脑海中的一些。

简而言之,尝试使用初始化代码玩游戏的方法太多了。并不是您的代码不起作用,它只是在做一些系统无法处理的非常不寻常的事情。我建议想出一种不同的方法来强制您的软件重置,如果它具有该功能,也许可以通过在您的处理器中进行软件重置。

于 2013-12-07T01:30:42.073 回答