[Linux] 用 c++filt 求得 mangle 前的 C/C++ 函式名稱

[Linux] 用 c++filt 求得 mangle 前的 C/C++ 函式名稱

在用 gdb debug C/C++ 程式時,常常會看到一些 mangle 過的函式名稱,

理論上 gdb 應該會自動還原名稱,但還是常常會看到沒有 demangle 的函式…

 

舉例來說,用 disas 反組譯時,看到程式呼叫一個_ZN7Scanner10ScanPacketEPhji 的函式:

(gdb) disas 0x00002b757251dfc1
Dump of assembler code for function ScanPcap:
0x00002b757251dfa0 <ScanPcap+0>:    sub    $0x8,%rsp
0x00002b757251dfa4 <ScanPcap+4>:    mov    %r9,(%rsp)
0x00002b757251dfa8 <ScanPcap+8>:    mov    %r8,%r9
0x00002b757251dfab <ScanPcap+11>:   mov    %rcx,%r8
0x00002b757251dfae <ScanPcap+14>:   mov    %edx,%ecx
0x00002b757251dfb0 <ScanPcap+16>:   mov    %esi,%edx
0x00002b757251dfb2 <ScanPcap+18>:   mov    %rdi,%rsi
0x00002b757251dfb5 <ScanPcap+21>:   mov    0x2063cc(%rip),%rdi        # 0x2b7572724388
0x00002b757251dfbc <ScanPcap+28>:   callq  0x2b757251dbb0 <_ZN7Scanner10ScanPacketEPhji@plt>
0x00002b757251dfc1 <ScanPcap+33>:   add    $0x8,%rsp
0x00002b757251dfc5 <ScanPcap+37>:   retq

 

這個是什麼函式呢?藉由 c++filt 這個工具的幫助,我們可以還原原始的名稱~

只要輸入 c++filt <mangled symbol name> 就行了 (注意不要把 @plt 也加上去),

可以看到原始的函式名稱是 Scanner::ScanPacket(),另外也可以看到函式參數的型態:

testuser@localhost ~ $ c++filt _ZN7Scanner10ScanPacketEPhji
Scanner::ScanPacket(unsigned char*, unsigned int, int)

 

c++filt 不只對我們自己寫的函式有用,C++ STL 中的函式也一樣有效:

testuser@localhost ~ $ c++filt _ZNSt3mapImSt6vectorI4InfoSaIS1_EESt4lessImESaISt4pairIKmS3_EEEixERS7_
std::map<unsigned long, std::vector<Info, std::allocator<Info> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, std::vector<Info, std::allocator<Info> > > > >::operator[](unsigned long const&)

 

不過 c++filt 最好是在編譯出 C/C++ 程式的同樣平台上執行,確保 mangle 的方式是一樣的,

像我在 Mac 上雖然也可以執行 c++filt,但輸入 Linux 上的 unmangled 函式名稱幾乎都無效喔~

 

(本頁面已被瀏覽過 954 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料