GDB最近引入了compile
命令以在运行时注入代码,请参阅this answer了解需求和最小示例。
但是我注意到有些东西不起作用,好像我在当前位置的原始源代码中写了它们一样:
compile code return;
不会结束当前函数,只会结束注入的代码。
假设:代码在新的堆栈框架中运行,但是局部变量仍然可见。
注册修改失败,例如:
compile code asm volatile ("mov $0x123, %rbp");
p $rbp
输出:不是0x123
。
假设:在功能运行中保存并恢复寄存器。
除此之外,documentation清楚地解释了注入的代码符号和类型在外部不可见。
那些"不起作用的那些结构的一般理论/完整列表是什么?#/ p>
该功能的GNU Cauldron演示文稿包含功能使用和内部的概述:video,presentation
该功能在7.9.1 GDB源代码的compile/
子目录中实现。
答案 0 :(得分:2)
compile
命令通过发出一个新函数,用gcc编译它,然后从gdb调用函数(gdb lingo中的“下级函数调用”)来工作。
代码生成器确实具有一些特殊功能,可以访问局部变量。特别是它将DWARF位置表达式转换为C.对寄存器的引用被转换为对特殊struct
中的字段的引用。 gdb安排在执行劣质调用时将相关寄存器复制到此结构的实例中。调用完成后,它会将寄存器复制回来 - 这允许写入局部变量。
我认为,这种描述应该更清楚地说明什么是有效的,什么是不可行的。我希望return
和其他控制流操作(break
,continue
,goto
)不起作用。
写入寄存器应该工作,但仅适用于某些位置表达式所需的寄存器。这可能是固定的;虽然我现在相信,出于性能原因,只传入必要的寄存器。
我不知道如果您的编译代码调用longjmp
或throw
(当实现C ++时)会发生什么。可能是疯了。
值得一提的是,此代码的设计是为了使未来的补丁可以添加已编译的断点条件,可能与dyninst一起使用。