【问题标题】:GDB gets lost when stack pointer is manually changed手动更改堆栈指针时 GDB 丢失
【发布时间】:2012-05-02 09:35:06
【问题描述】:

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

有什么方法可以避免这种行为并能够调试这个应用程序?

【问题讨论】:

    标签: debugging gdb stack cpu-registers


    【解决方案1】:

    我认为你需要的是 GDB/Python 的 frame unwinding。我自己从来没有使用过,但是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 or reg_id) 访问 CPU 寄存器,但显然,读取局部变量可能是个问题!

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

    【讨论】:

      【解决方案2】:

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

      是的,显然是it does

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-20
        • 2020-05-08
        • 2015-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-21
        相关资源
        最近更新 更多