c++での名前マングリングされたシンボル名を人が読むのはけっこうつらい。
社内勉強会で c++filt
で簡単にデマングルできるよ、との情報があったので試してみる。
c++filtのインストール
おそらくデフォルトでは入っていないため、debian系では以下のようにダウンロードします。
sudo apt-get install c++filt
検証対象のソース
# include <iostream>
# include <boost/optional.hpp>
int main(int argc, char const* argv[])
{
boost::optional<int> opt;
return 0;
}
おもむろに g++ test.cpp
でビルドする (=> a.out ができる)
まずはそのままシンボルテーブルを見てみる(マングリングされている状態)
以下は readelf -s -W a.out
の実行結果
Symbol table '.dynsym' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
7: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (4)
9: 0000000000400630 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400238 0 SECTION LOCAL DEFAULT 1
2: 0000000000400254 0 SECTION LOCAL DEFAULT 2
3: 0000000000400274 0 SECTION LOCAL DEFAULT 3
4: 0000000000400298 0 SECTION LOCAL DEFAULT 4
5: 00000000004002c0 0 SECTION LOCAL DEFAULT 5
6: 00000000004003b0 0 SECTION LOCAL DEFAULT 6
7: 00000000004004a6 0 SECTION LOCAL DEFAULT 7
8: 00000000004004c0 0 SECTION LOCAL DEFAULT 8
9: 0000000000400510 0 SECTION LOCAL DEFAULT 9
10: 0000000000400528 0 SECTION LOCAL DEFAULT 10
11: 00000000004005b8 0 SECTION LOCAL DEFAULT 11
12: 00000000004005e0 0 SECTION LOCAL DEFAULT 12
13: 0000000000400650 0 SECTION LOCAL DEFAULT 13
14: 00000000004009a4 0 SECTION LOCAL DEFAULT 14
15: 00000000004009b0 0 SECTION LOCAL DEFAULT 15
16: 00000000004009c0 0 SECTION LOCAL DEFAULT 16
17: 0000000000400a60 0 SECTION LOCAL DEFAULT 17
18: 0000000000600df8 0 SECTION LOCAL DEFAULT 18
19: 0000000000600e08 0 SECTION LOCAL DEFAULT 19
20: 0000000000600e10 0 SECTION LOCAL DEFAULT 20
21: 0000000000600e18 0 SECTION LOCAL DEFAULT 21
22: 0000000000600ff8 0 SECTION LOCAL DEFAULT 22
23: 0000000000601000 0 SECTION LOCAL DEFAULT 23
24: 0000000000601048 0 SECTION LOCAL DEFAULT 24
25: 0000000000601058 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
28: 0000000000600e10 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__
29: 0000000000400680 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
30: 00000000004006b0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
31: 00000000004006f0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
32: 0000000000601058 1 OBJECT LOCAL DEFAULT 25 completed.6972
33: 0000000000600e08 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fini_array_entry
34: 0000000000400710 0 FUNC LOCAL DEFAULT 13 frame_dummy
35: 0000000000600df8 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_entry
36: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.cpp
37: 0000000000601059 1 OBJECT LOCAL DEFAULT 25 _ZStL8__ioinit
38: 0000000000400796 61 FUNC LOCAL DEFAULT 13 _Z41__static_initialization_and_destruction_0ii
39: 00000000004009b8 8 OBJECT LOCAL DEFAULT 15 _ZN5boostL4noneE
40: 00000000004007d3 21 FUNC LOCAL DEFAULT 13 _GLOBAL__sub_I_main
41: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
42: 0000000000400cf8 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
43: 0000000000600e10 0 OBJECT LOCAL DEFAULT 20 __JCR_END__
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS
45: 0000000000601000 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_
46: 0000000000600e08 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
47: 0000000000600df8 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
48: 0000000000600e18 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
49: 0000000000601048 0 NOTYPE WEAK DEFAULT 24 data_start
50: 00000000004009a0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
51: 0000000000400650 0 FUNC GLOBAL DEFAULT 13 _start
52: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
53: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
54: 00000000004009a4 0 FUNC GLOBAL DEFAULT 14 _fini
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
57: 00000000004007e8 26 FUNC WEAK DEFAULT 13 _ZN5boost8optionalIiEC2Ev
58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
59: 000000000040091a 14 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail15aligned_storageIiE7addressEv
60: 0000000000400802 26 FUNC WEAK DEFAULT 13 _ZN5boost8optionalIiED2Ev
61: 0000000000400630 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
62: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
63: 00000000004009b0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
64: 00000000004008ac 53 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiE12get_ptr_implEv
65: 0000000000400826 33 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiEC2Ev
66: 0000000000400848 26 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiED1Ev
67: 00000000004007e8 26 FUNC WEAK DEFAULT 13 _ZN5boost8optionalIiEC1Ev
68: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
69: 0000000000601048 0 NOTYPE GLOBAL DEFAULT 24 __data_start
70: 000000000040088a 33 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiE12destroy_implEN4mpl_5bool_ILb0EEE
71: 000000000040081c 10 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail12optional_tagC1Ev
72: 0000000000601058 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__
73: 0000000000601050 0 OBJECT GLOBAL HIDDEN 24 __dso_handle
74: 0000000000400930 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
75: 00000000004008e2 38 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiE10get_objectEv
76: 0000000000400908 18 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiE8cast_ptrEPiN4mpl_5bool_ILb0EEE
77: 0000000000601058 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
78: 0000000000400802 26 FUNC WEAK DEFAULT 13 _ZN5boost8optionalIiED1Ev
79: 0000000000400848 26 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiED2Ev
80: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2.4
81: 0000000000400862 40 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiE7destroyEv
82: 0000000000400826 33 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail13optional_baseIiEC1Ev
83: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 25 _end
84: 0000000000601058 0 NOTYPE GLOBAL DEFAULT 24 _edata
85: 000000000040081c 10 FUNC WEAK DEFAULT 13 _ZN5boost15optional_detail12optional_tagC2Ev
86: 000000000040073d 89 FUNC GLOBAL DEFAULT 13 main
87: 00000000004005b8 0 FUNC GLOBAL DEFAULT 11 _init
_ZN5boost15optional_detail12optional_tagC2Ev
とか訳の分からない文字列になってますね・・・。
c++filt
を通す
以下は readelf -s -W a.out | c++filt
の実行結果
※wide指定をしないと80文字で切れでデマングルできないため、必ず -W
または --wide
をつけること
Symbol table '.dynsym' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@GLIBCXX_3.4 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
7: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (4)
9: 0000000000400630 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400238 0 SECTION LOCAL DEFAULT 1
2: 0000000000400254 0 SECTION LOCAL DEFAULT 2
3: 0000000000400274 0 SECTION LOCAL DEFAULT 3
4: 0000000000400298 0 SECTION LOCAL DEFAULT 4
5: 00000000004002c0 0 SECTION LOCAL DEFAULT 5
6: 00000000004003b0 0 SECTION LOCAL DEFAULT 6
7: 00000000004004a6 0 SECTION LOCAL DEFAULT 7
8: 00000000004004c0 0 SECTION LOCAL DEFAULT 8
9: 0000000000400510 0 SECTION LOCAL DEFAULT 9
10: 0000000000400528 0 SECTION LOCAL DEFAULT 10
11: 00000000004005b8 0 SECTION LOCAL DEFAULT 11
12: 00000000004005e0 0 SECTION LOCAL DEFAULT 12
13: 0000000000400650 0 SECTION LOCAL DEFAULT 13
14: 00000000004009a4 0 SECTION LOCAL DEFAULT 14
15: 00000000004009b0 0 SECTION LOCAL DEFAULT 15
16: 00000000004009c0 0 SECTION LOCAL DEFAULT 16
17: 0000000000400a60 0 SECTION LOCAL DEFAULT 17
18: 0000000000600df8 0 SECTION LOCAL DEFAULT 18
19: 0000000000600e08 0 SECTION LOCAL DEFAULT 19
20: 0000000000600e10 0 SECTION LOCAL DEFAULT 20
21: 0000000000600e18 0 SECTION LOCAL DEFAULT 21
22: 0000000000600ff8 0 SECTION LOCAL DEFAULT 22
23: 0000000000601000 0 SECTION LOCAL DEFAULT 23
24: 0000000000601048 0 SECTION LOCAL DEFAULT 24
25: 0000000000601058 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
28: 0000000000600e10 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__
29: 0000000000400680 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
30: 00000000004006b0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
31: 00000000004006f0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
32: 0000000000601058 1 OBJECT LOCAL DEFAULT 25 completed.6972
33: 0000000000600e08 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fini_array_entry
34: 0000000000400710 0 FUNC LOCAL DEFAULT 13 frame_dummy
35: 0000000000600df8 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_entry
36: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.cpp
37: 0000000000601059 1 OBJECT LOCAL DEFAULT 25 std::__ioinit
38: 0000000000400796 61 FUNC LOCAL DEFAULT 13 __static_initialization_and_destruction_0(int, int)
39: 00000000004009b8 8 OBJECT LOCAL DEFAULT 15 boost::none
40: 00000000004007d3 21 FUNC LOCAL DEFAULT 13 _GLOBAL__sub_I_main
41: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
42: 0000000000400cf8 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
43: 0000000000600e10 0 OBJECT LOCAL DEFAULT 20 __JCR_END__
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS
45: 0000000000601000 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_
46: 0000000000600e08 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
47: 0000000000600df8 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
48: 0000000000600e18 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
49: 0000000000601048 0 NOTYPE WEAK DEFAULT 24 data_start
50: 00000000004009a0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
51: 0000000000400650 0 FUNC GLOBAL DEFAULT 13 _start
52: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
53: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
54: 00000000004009a4 0 FUNC GLOBAL DEFAULT 14 _fini
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@@GLIBCXX_3.4
56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
57: 00000000004007e8 26 FUNC WEAK DEFAULT 13 boost::optional<int>::optional()
58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
59: 000000000040091a 14 FUNC WEAK DEFAULT 13 boost::optional_detail::aligned_storage<int>::address()
60: 0000000000400802 26 FUNC WEAK DEFAULT 13 boost::optional<int>::~optional()
61: 0000000000400630 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@@GLIBCXX_3.4
62: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
63: 00000000004009b0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
64: 00000000004008ac 53 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::get_ptr_impl()
65: 0000000000400826 33 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::optional_base()
66: 0000000000400848 26 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::~optional_base()
67: 00000000004007e8 26 FUNC WEAK DEFAULT 13 boost::optional<int>::optional()
68: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
69: 0000000000601048 0 NOTYPE GLOBAL DEFAULT 24 __data_start
70: 000000000040088a 33 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::destroy_impl(mpl_::bool_<false>)
71: 000000000040081c 10 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_tag::optional_tag()
72: 0000000000601058 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__
73: 0000000000601050 0 OBJECT GLOBAL HIDDEN 24 __dso_handle
74: 0000000000400930 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
75: 00000000004008e2 38 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::get_object()
76: 0000000000400908 18 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::cast_ptr(int*, mpl_::bool_<false>)
77: 0000000000601058 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
78: 0000000000400802 26 FUNC WEAK DEFAULT 13 boost::optional<int>::~optional()
79: 0000000000400848 26 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::~optional_base()
80: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2.4
81: 0000000000400862 40 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::destroy()
82: 0000000000400826 33 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_base<int>::optional_base()
83: 0000000000601060 0 NOTYPE GLOBAL DEFAULT 25 _end
84: 0000000000601058 0 NOTYPE GLOBAL DEFAULT 24 _edata
85: 000000000040081c 10 FUNC WEAK DEFAULT 13 boost::optional_detail::optional_tag::optional_tag()
86: 000000000040073d 89 FUNC GLOBAL DEFAULT 13 main
87: 00000000004005b8 0 FUNC GLOBAL DEFAULT 11 _init
読める。
結論
c++filtすごい。
細かいところ
C++ の名前修飾に関しては標準化されておらず、どういうシンボル名になるのかはコンパイラ依存のようです。
ヘタすると同じコンパイラでもバージョンやプラットフォームごとにルールが違ったりするとのこと。
※今回使用したコンパイラは g++ 4.8.2
になります。
$ c++filt --help
Usage: c++filt [options] [mangled names]
Options are:
[-_|--strip-underscore] Ignore first leading underscore
[-n|--no-strip-underscore] Do not ignore a leading underscore (default)
[-p|--no-params] Do not display function arguments
[-i|--no-verbose] Do not show implementation details (if any)
[-t|--types] Also attempt to demangle type encodings
[-s|--format {none,auto,gnu,lucid,arm,hp,edg,gnu-v3,java,gnat}]
[@<file>] Read extra options from <file>
[-h|--help] Display this information
[-v|--version] Show the version information
Demangled names are displayed to stdout.
If a name cannot be demangled it is just echoed to stdout.
If no names are provided on the command line, stdin is read.
Report bugs to <http://www.sourceware.org/bugzilla/>.
c++filt が自動判別してくれるか不明ですが、いちおう --format
オプションで明示的に種別を選べるようです。
その他
nm の場合は c++filt を通してもいいけど、nm自体が--demangle
オプションを持っているとのこと。