【问题标题】:Is it possible to do a longjmp to a gcc pre_init function right before static variable initialisation?是否可以在静态变量初始化之前对 gcc pre_init 函数执行 longjmp?
【发布时间】:2013-12-12 22:18:04
【问题描述】:

为了模拟应用程序的完全重启(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);
}

【问题讨论】:

  • 我宁愿建议你exec这个程序。可以这么说,这与从“从头开始”重新启动程序相同。发生故障的可能性较小,并且它仍然是相同的过程,因此希望可以与 gdbserver 一起正常工作。
  • 你怎么把setjmp放在那里?
  • 我添加了一个代码 sn-p 来展示我的方法。

标签: c linux gcc embedded setjmp


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    相关资源
    最近更新 更多