Debugging 当手动更改堆栈指针时,GDB将丢失

Debugging 当手动更改堆栈指针时,GDB将丢失,debugging,gdb,stack,cpu-registers,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 a

我正在开发一个应用程序,在某个时候,它必须使用不同的堆栈,由我开发的库管理。因此,我调用这个库的初始化函数,堆栈指针($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的。我自己从未使用过它,但帧展开是重建进程调用堆栈的(内部)过程

正如您提到的,您更改了
$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
从gdb.unwinders导入退绕机
类FrameId(对象):
定义初始化(自、sp、pc):
self.sp=sp
self.pc=pc
My类退绕机(退绕机):
定义初始值(..):
超级(MyUnwinder,self)。\uuuuu init\uuuuuuuu()
定义调用(挂起帧):
如果没有:
一无所获
#创建UnwindInfo。通常,框架由堆栈标识
#指针和程序计数器。
sp=挂起的\u帧。读取\u寄存器()
pc=挂起的\u帧。读取\u寄存器()
展开\信息=挂起\帧。创建\展开\信息(帧ID(sp、pc))
#查找调用者帧中寄存器的值,然后
#将它们保存在结果中:
展开信息。添加保存的寄存器(,)
....
#返回结果:
返回展开信息
根据文档,您可以使用
PendingFrame.read\u register(reg\u name或reg\u id)
访问CPU寄存器,但显然,读取局部变量可能会有问题

一旦您构建好了unwinder,它应该透明地集成到GDB中,并且所有常用的CLI机制都应该可用

这是因为GDB使用堆栈指针指向地址 跟踪函数的框架

是的,显然:

在gdb_reader_函数中,get_frame_id是返回一个gdb_frame_id 对应于当前帧。[…]一 实现这一点的方法是让CODE_地址指向 函数的第一条指令和堆栈地址指向 输入函数时堆栈指针的值

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