2012-04-20 109 views
4

我正在開發一個應用程序,它在某些時候必須使用不同的堆棧,並由我開發的庫管理。所以,我調用這個庫的初始化函數,並將堆棧指針($ sp)設置爲我想要的內存地址。當手動更改堆棧指針時,GDB會丟失

當運行通過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正確執行,並有在0×12沒有功能,這是因爲GDB使用堆棧指針來解決跟蹤函數的幀的。

有什麼辦法可以避免這種行爲,並且能夠調試這個應用程序?

回答

1

我認爲你需要的是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 or reg_id)訪問CPU寄存器,但很明顯,讀取本地變量可能是一個問題!

一旦開卷精心打造,應該透明地集成到GDB,和所有常見的CLI機制應當是可用的。

1

發生這種情況是因爲GDB使用棧指針地址 來跟蹤函數的框架。

是,顯然it does

get_frame_id在gdb_reader_funcs是返回對應於當前幀中的gdb_frame_id 。 [...]這樣做的一種 方式是通過具有CODE_ADDRESS指向 函數的第一指令和STACK_ADDRESS指向堆棧指針的值 進入功能時。

我想解決這個問題的一種方法是將你的代碼在 兩個不同的函數(事件,如果你只是在它們之間跳轉)分開。