在GDB编译代码命令中,哪种语言结构的行为与它们在原始源中的存在完全相同?

时间:2015-07-29 20:54:10

标签: gdb

GDB最近引入了compile命令以在运行时注入代码,请参阅this answer了解需求和最小示例。

但是我注意到有些东西不起作用,好像我在当前位置的原始源代码中写了它们一样:

  • compile code return;不会结束当前函数,只会结束注入的代码。

    假设:代码在新的堆栈框架中运行,但是局部变量仍然可见。

  • 注册修改失败,例如:

    compile code asm volatile ("mov $0x123, %rbp");
    p $rbp
    

    输出:不是0x123

    假设:在功能运行中保存并恢复寄存器。

除此之外,documentation清楚地解释了注入的代码符号和类型在外部不可见。

那些"不起作用的那些结构的一般理论/完整列表是什么?#/ p>

该功能的GNU Cauldron演示文稿包含功能使用和内部的概述:videopresentation

该功能在7.9.1 GDB源代码的compile/子目录中实现。

1 个答案:

答案 0 :(得分:2)

compile命令通过发出一个新函数,用gcc编译它,然后从gdb调用函数(gdb lingo中的“下级函数调用”)来工作。

代码生成器确实具有一些特殊功能,可以访问局部变量。特别是它将DWARF位置表达式转换为C.对寄存器的引用被转换为对特殊struct中的字段的引用。 gdb安排在执行劣质调用时将相关寄存器复制到此结构的实例中。调用完成后,它会将寄存器复制回来 - 这允许写入局部变量。

我认为,这种描述应该更清楚地说明什么是有效的,什么是不可行的。我希望return和其他控制流操作(breakcontinuegoto)不起作用。

写入寄存器应该工作,但仅适用于某些位置表达式所需的寄存器。这可能是固定的;虽然我现在相信,出于性能原因,只传入必要的寄存器。

我不知道如果您的编译代码调用longjmpthrow(当实现C ++时)会发生什么。可能是疯了。

值得一提的是,此代码的设计是为了使未来的补丁可以添加已编译的断点条件,可能与dyninst一起使用。