binary hacks 繁體中文版 item 38, 39, 40, 41 是用 gcc 3.4.4 講解, 用目前的 gcc 5.4.0 (20161231) 編譯的執行檔會直接 segmentfault, 無法在目前的系統上執行有點可惜, 我希望這段程式碼可以使用 gcc 5.4.0 編譯測試, 來試試看吧!
你可能有興趣:
c++ exception handling (1) - 原理篇
挑戰自己, 先來編譯 gcc 5.4.0, glibc 2.23。
env:
x64 debian 64 bit
系統上的 glibc 是使用 dwarf 的方式處理 exception handle 編譯出來的, 要以 static link 編譯 a.cpp 就出了問題, 得自己編譯以 sjlj 處理 exception handle 的 glibc。
dwarf 呼叫的是 _Unwind_RaiseException, sjlj 的版本呼叫的則是 _Unwind_SjLj_RaiseException, symbol 不一樣。
編譯 glibc 時會遇到 ldconfig, sln 無法使用 static 編譯的問題, 我用 touch 建立這 2 個檔案, 還有 libgcc.so 找不到的問題, 我修改了路徑以及加入 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.4.0/libgcc.a, 成功編譯出呼叫 sjlj 系列函式的 glibc。
static link a.cpp 需要重新編譯 glibc, 所以才編譯了 glibc-2.23, 為什麼需要使用 static link 呢? 因為使用 gdb 時, libgcc.so 的行號對應似乎有問題, 所以才想要使用 static link, 不過由於有 2 套 glibc, 我不知道怎麼讓 gcc 使用我自己編的那個, 就有了很蠢 d.sh 那個方法,
-lunwind 也可以拿掉。
而和 gcc 3.4.4 搭配的 glibc 是 2.3.5, 2.23 無法使用 gcc 3.4.4 編譯, 在目前的系統上因為有些工具太新而不能編譯, 例如: sed, awk, make, binutility ...
一開始沒有修改 lsda, 執行下去馬上就 segmentfault, 所以該啟動反組譯工程了。
有了自行編譯的 glibc 之後, 就可以使用 gdb debug 這個 static link 的檔案, 方便理解整個來龍去脈, 遺憾的就是 lsda 裡頭的格式我還是不了解, 但我還是可以把 lsda 的格式填對, 怎麼做呢?
list 1 是 .gcc_except_table, 就是那個 lsda, 可是 L7 不是一個值, 而是一個需要計算才知道的值, 我要怎麼填呢?
靠 objdump -D a, list 2 L1329 開始的 ff, 03, 0x0d, 0x01, 4, 0, 1, 1, 0, 1, 0 不就是答案了嗎?
把這串神秘的數字換掉 binary hack 的範例程式, 就可以使用 g++ 5.4.0 來編譯這個程式, 並且成功的執行 exception handle, 爽阿!
完整 source code 請參考
https://github.com/descent/eh_impl, 支援 gcc 3.4.4 以及 gcc 5.4.0。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。