[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 次)