调试 – 手动更改堆栈指针时GDB丢失

我正在开发一个应用程序,在某些时候,必须使用不同的堆栈,这将由我开发的库管理.所以,我调用这个库的初始化函数,并将堆栈指针($sp)设置为我想要的内存地址.

通过GDB运行此代码时,在完成其他堆栈的初始化并执行返回调用函数后,GDB向我发出以下警告:

warning: GDB can't find the start of the function at 0x12.

    GDB is unable to find the start of the function at 0x12
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
    This problem is most likely caused by an invalid program counter or
stack pointer.
    However, if you think GDB should simply search farther back
from 0x12 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.

此外,在打印$sp时,会显示旧值.

由于这部分代码在没有GDB的情况下正确执行,并且在0x12处没有函数,这是因为GDB使用堆栈指针来寻址以跟踪函数的帧.

有没有办法避免这种行为,并能够调试此应用程序?

最佳答案 我认为你需要的是GDB / Python的
frame unwinding.我自己从未使用它,但帧展开是重建进程调用栈的(内部)过程.

正如您所提到的,您更改了$SP值,因此GDB无法识别标准调用约定.自定义框架展开器应该让你教GDB你使用的堆栈布局.

以下是他们在文档中提供的示例:

 from gdb.unwinders import Unwinder

 class FrameId(object):
     def __init__(self, sp, pc):
         self.sp = sp
         self.pc = pc


 class MyUnwinder(Unwinder):
     def __init__(....):
         super(MyUnwinder, self).__init___(<expects unwinder name argument>)

     def __call__(pending_frame):
         if not <we recognize frame>:
             return None
         # Create UnwindInfo.  Usually the frame is identified by the stack
         # pointer and the program counter.
         sp = pending_frame.read_register(<SP number>)
         pc = pending_frame.read_register(<PC number>)
         unwind_info = pending_frame.create_unwind_info(FrameId(sp, pc))

         # Find the values of the registers in the caller's frame and
         # save them in the result:
         unwind_info.add_saved_register(<register>, <value>)
         ....

         # Return the result:
         return unwind_info

根据文档,您可以使用PendingFrame.read_register(reg_name或reg_id)访问CPU寄存器,但显然,读取局部变量可能是个问题!

打开后,它应该透明地集成到GDB中,并且所有常用的CLI机制都应该可用.

点赞