|
世間多不公, 以血引雷霆 |
承
上篇, glibc 的 backtrace 怎麼辦到在 signal handler 還可以正常抓出上一層的呼叫者, 先說答案, 我不知道, 看到這邊你可能會失望, 裡頭有 gcc 魔法, 我不是想往裡頭鑽, 所以這篇是介紹 glibc 的 backtrace 用什麼手法辦到這件事情。
__backtrace 有好幾個平台的實作, x86_64 應該是用 list 1 這個。
在 glibc 2.39 debug/backtrace.c __backtrace (void **array, int size) 可以看到類似的作法。
看了一下 list 2, 是 t1 的反組譯, __backtrace 有看到 _Unwind_Backtrace, 所以應該是用 list 1 這段。
list 3 是 gcc 輸出的組合語言, 可以看到 .cfi 開頭的指令, 這並非是 x86 指令, 到底是什麼呢?
chatgpt 真的威, 連 .cfi_def_cfa 都可以解釋, 最重要的是用「中文」解釋。讓英文不好的我和英文好的開發者差距拉近了一點。以下是 gpt 的回答, 看完應該可以猜到 glibc 的 backtrace 是怎麼做的。
所以程式用了 -fno-asynchronous-unwind-tables, 就不會有 .cfi 這些指令, 然後你就會發現 backtrace 再也無法正確印出整個呼叫順序了。如 list 6, 只能抓到 print_backtrace, 我自己尋訪 stack frame 的作法依然可以正常。gcc 勝之不武, 偷偷用了自己的加料手法完成這件事情, 這樣也許也可以不因為 cpu 平台而有一個統一的作法吧。
ref:
What do the CFI directives mean? (and some more questions)
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。