手动更改堆栈指针时,GDB会丢失

时间:2012-04-20 19:24:30

标签: debugging gdb stack cpu-registers

我正在开发一个应用程序,在某些时候,必须使用不同的堆栈,这将由我开发的库管理。所以,我调用这个库的初始化函数,并将堆栈指针($ 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使用堆栈指针来寻址以跟踪函数的帧。

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

2 个答案:

答案 0 :(得分:1)

我认为您需要的是GDB / Python frame unwinding 。我自己从未使用它,但帧展开是重建过程callstack的(内部)过程。

正如您所提到的,您更改了$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 or reg_id)访问CPU寄存器,但显然,读取局部变量可能是个问题!

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

答案 1 :(得分:1)

  

这是因为GDB使用堆栈指针来寻址   跟踪功能的框架。

是的,显然是it does

  gdb_reader_funcs中的

get_frame_id是返回gdb_frame_id   对应于当前帧。 [...]一个   这样做的方法是让CODE_ADDRESS指向   函数的第一条指令和STACK_ADDRESS指向   进入函数时堆栈指针的值。

我想解决这个问题的一种方法就是将你的代码分开 两个不同的函数(如果你只是在它们之间跳转,则为事件)。