是否可以在静态变量初始化之前对gcc pre_init函数执行longjmp?

时间:2013-11-27 10:19:26

标签: c linux gcc embedded longjmp

为了模拟包括静态变量初始化的应用程序(GNU C版本4.1.2(arm-linux-gnueabi))的完全重启,我尝试将setjmp / 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);
}

1 个答案:

答案 0 :(得分:0)

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

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

简而言之,通过尝试使用init代码玩游戏,有很多方法可以让自己陷入困境。并不是说你的代码不能正常工作,它只是做了一些非常不寻常的事情,系统无法应对。我建议采用不同的方法强制软件重置,如果它具有该功能,可能会导致处理器中的软件重置。