通過 GDB 除錯理解 GOT PLT

2021-09-11 17:11:12 字數 2312 閱讀 2606

關於 linux 中 elf 檔案格式可參考詳細文件《elf_format》,本文僅記錄筆者理解got/plt的過程。

got(global offset table):全域性偏移表用於記錄在 elf 檔案中所用到的共享庫中符號的絕對位址。在程式剛開始執行時,got 表項是空的,當符號第一次被呼叫時會動態解析符號的絕對位址然後轉去執行,並將被解析符號的絕對位址記錄在 got 中,第二次呼叫同一符號時,由於 got 中已經記錄了其絕對位址,直接轉去執行即可(不用重新解析)。

plt(procedure linkage table):過程鏈結表的作用是將位置無關的符號轉移到絕對位址。當乙個外部符號被呼叫時,plt 去引用 got 中的其符號對應的絕對位址,然後轉入並執行。

got 位於.got.pltsection 中,而 plt 位於.pltsection中。下面給出一示例程式:

#include #include int main(int argc, char* ar**)

printf("you input: ");

printf(ar**[1]);

printf("down\n");

return 0;

}

編譯該程式:

gcc -o format format.c
然後我們通過readelf命令來檢視format程式的 sectioin 資訊,並檢查 got:

從上圖可看到,該 elf 檔案共包含29個 section,有關 got 的重定向:

.rel.dyn記錄了載入時需要重定位的變數,.rel.plt記錄的是需要重定位的函式。

接下來,我們使用gdb來對程式進行除錯,觀察程式在呼叫printf()函式時,got 的變化情況。

因為程式邏輯需要輸入引數,設定好引數後,在主函式處下斷點,然後執行,單步除錯來到printf()函式呼叫的地方:

這裡可以看到在0x080484ab處指令為:

call 0x8048330
然後檢視一下0x8048330處的**:

可以看到流程會跳轉到ds[0x804a00c]處,而0x804a00cprintf()重定位偏移(檢視上面 got 資訊圖),接著看一下後面的流程都做了什麼:

根據上面的流程分析,進行單步除錯,當動態解析(_dl_runtime_resolve)完成後,流程會直接跳轉到printf()函式主體:

上面我們說過,當第一次呼叫符號時會動態解析其絕對位址並寫到 got 中,下次呼叫的時候就不用再次解析了,我們來看看這個時候原先0x804a00c處的指向情況:

其所指向的位址正好為第一次解析後得到的printf()函式的入口位址。

程式中,printf()函式的呼叫過程可以總結為:

總結來說就是,got 儲存了程式中所要呼叫的函式的位址,執行一開時其表項為空,會在執行時實時的更新表項。乙個符號呼叫在第一次時會解析出絕對位址更新到 got 中,第二次呼叫時就直接找到 got 表項所儲存的函式位址直接呼叫了。

(清楚上述動態解析的過程,有助於理解got覆寫利用)

通過GDB除錯理解指標

源 include intmain 編譯上面的 之後進行除錯。在初始化之前,a pon ppon的值各為 可以使用info locals命令進行檢視區域性變數 0x0執行結束退出main之前,a pon ppon的值各為 a 0xapon 0x7ffeefbff94c ppon 0x7ffeefbf...

gdb 除錯 vs除錯

一 先要生成二進位制檔案 g g 1.cpp o 1.out g引數不要省,不然 gdb l 引數用不了 二 引數 設定斷點 設定 函式斷點break func 在某行設定斷點break 7 檢視斷點資訊 info break 刪除斷點 d 刪除所有斷點 d 3 刪除第三個 執行 r 下一步 n 逐...

GDB除錯命令以及GDB除錯段錯誤

一 gdb的除錯命令。c語言是 cc g tst.c o tst c 是g g o 生成的檔案 file.cpp c 除錯程式命令 gdb file 啟動,羅列 行數ist 1,break 行數 info break,run r 除錯執行,step s 單步除錯,檢視變數 print p 變數名,檢...