I have been using Anthony Shoumikhin's elfhook utility to redirect certain function calls in a shared library.
As a proof of concept, I've created a shared library which calls various functions from the posix socket api.
void TestAPI::work()
{
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
char buf[1024];
recv(fd, buf, sizeof(buf), 0);
listen(fd, 1);
}
I've then hooked these functions:
elf_hook(filename, base_address, "socket", hook_socket);
elf_hook(filename, base_address, "listen", hook_listen);
elf_hook(filename, base_address, "recv", hook_recv);
where a hooked function calls the original api function, but also logs what is happening, for example:
int hook_socket(int domain, int type, int protocol)
{
int fd = socket(domain, type, protocol);
printf("fd=%d domain=%d type=%d protocol=%d\n", fd, domain, type, protocol);
return fd;
}
This all works fine, until I attempt to hook a function which isn't called in my TestAPI shared library
elf_hook(filename, base_address, "bind", hook_bind);
elf_hook(filename, base_address, "connect", hook_connect);
As soon as I do this, I get a segmentation fault:
#0 elf_machine_fixup_plt (map=<optimized out>, t=<optimized out>, reloc=<optimized out>, value=139753823227104, reloc_addr=0x7f1afa15e188) at ../sysdeps/x86_64/dl-machine.h:235
#1 _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at ../elf/dl-runtime.c:148
#2 0x00007f1afa176753 in _dl_runtime_resolve_avx () at ../sysdeps/x86_64/dl-trampoline.h:112
#3 0x0000000000561b20 in ?? ()
#4 0x00007f1afa16f8e0 in ?? () at dl-fini.c:105 from /lib64/ld-linux-x86-64.so.2
#5 0x00007f1afa16f5fb in call_init (env=0x7ffff0e3aae0, argv=0x4a7390 <_start>, argc=-253515440, l=<optimized out>) at dl-init.c:30
#6 _dl_init (main_map=0x0, argc=-253515440, argv=0x4a7390 <_start>, env=0x7ffff0e3aae0) at dl-init.c:120
#7 0x000000000000001c in ?? ()
#8 0x0000000000000001 in ?? ()
#9 0x00007ffff0e3c21f in ?? ()
#10 0x0000000000000000 in ?? ()
I've tested this by hooking a function, running my application, seeing it segfault, calling that function in my shared library, running again, and seeing work correctly.
My knowledge of libdl and elf is not up to scratch to know what is happening here or how to prevent it / catch the fact that I've tried to hook a function which doesn't get called.
How can I prevent this from happening?
Edit:
Per request, here is the output of readelf:
$ readelf -s -S --dyn-syms -r ./libtest_api.so
There are 36 section headers, starting at offset 0x14a208:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.gnu.build-i NOTE 00000000000001c8 000001c8
0000000000000024 0000000000000000 A 0 0 4
[ 2] .gnu.hash GNU_HASH 00000000000001f0 000001f0
0000000000000044 0000000000000000 A 3 0 8
[ 3] .dynsym DYNSYM 0000000000000238 00000238
0000000000000240 0000000000000018 A 4 2 8
[ 4] .dynstr STRTAB 0000000000000478 00000478
00000000000001b4 0000000000000000 A 0 0 1
[ 5] .gnu.version VERSYM 000000000000062c 0000062c
0000000000000030 0000000000000002 A 3 0 2
[ 6] .gnu.version_r VERNEED 0000000000000660 00000660
0000000000000070 0000000000000000 A 4 3 8
[ 7] .rela.dyn RELA 00000000000006d0 000006d0
00000000000000f0 0000000000000018 A 3 0 8
[ 8] .rela.plt RELA 00000000000007c0 000007c0
00000000000000d8 0000000000000018 AI 3 22 8
[ 9] .init PROGBITS 0000000000000898 00000898
000000000000001a 0000000000000000 AX 0 0 4
[10] .plt PROGBITS 00000000000008c0 000008c0
00000000000000a0 0000000000000010 AX 0 0 16
[11] .plt.got PROGBITS 0000000000000960 00000960
0000000000000010 0000000000000000 AX 0 0 8
[12] .text PROGBITS 0000000000000970 00000970
0000000000000253 0000000000000000 AX 0 0 16
[13] .fini PROGBITS 0000000000000bc4 00000bc4
0000000000000009 0000000000000000 AX 0 0 4
[14] .rodata PROGBITS 0000000000000bd0 00000bd0
0000000000000105 0000000000000000 A 0 0 8
[15] .eh_frame_hdr PROGBITS 0000000000000cd8 00000cd8
0000000000000034 0000000000000000 A 0 0 4
[16] .eh_frame PROGBITS 0000000000000d10 00000d10
00000000000000cc 0000000000000000 A 0 0 8
[17] .init_array INIT_ARRAY 0000000000201dc0 00001dc0
0000000000000010 0000000000000000 WA 0 0 8
[18] .fini_array FINI_ARRAY 0000000000201dd0 00001dd0
0000000000000008 0000000000000000 WA 0 0 8
[19] .jcr PROGBITS 0000000000201dd8 00001dd8
0000000000000008 0000000000000000 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000201de0 00001de0
00000000000001f0 0000000000000010 WA 4 0 8
[21] .got PROGBITS 0000000000201fd0 00001fd0
0000000000000030 0000000000000008 WA 0 0 8
[22] .got.plt PROGBITS 0000000000202000 00002000
0000000000000060 0000000000000008 WA 0 0 8
[23] .data PROGBITS 0000000000202060 00002060
0000000000000008 0000000000000000 WA 0 0 8
[24] .bss NOBITS 0000000000202068 00002068
0000000000000008 0000000000000000 WA 0 0 1
[25] .comment PROGBITS 0000000000000000 00002068
0000000000000034 0000000000000001 MS 0 0 1
[26] .debug_aranges PROGBITS 0000000000000000 0000209c
0000000000000040 0000000000000000 0 0 1
[27] .debug_info PROGBITS 0000000000000000 000020dc
0000000000007a3b 0000000000000000 0 0 1
[28] .debug_abbrev PROGBITS 0000000000000000 00009b17
00000000000009e1 0000000000000000 0 0 1
[29] .debug_line PROGBITS 0000000000000000 0000a4f8
00000000000052dd 0000000000000000 0 0 1
[30] .debug_str PROGBITS 0000000000000000 0000f7d5
000000000011cb84 0000000000000001 MS 0 0 1
[31] .debug_ranges PROGBITS 0000000000000000 0012c359
0000000000000030 0000000000000000 0 0 1
[32] .debug_macro PROGBITS 0000000000000000 0012c389
000000000001c8a8 0000000000000000 0 0 1
[33] .shstrtab STRTAB 0000000000000000 0014a0b4
0000000000000151 0000000000000000 0 0 1
[34] .symtab SYMTAB 0000000000000000 00148c38
0000000000000ba0 0000000000000018 35 102 8
[35] .strtab STRTAB 0000000000000000 001497d8
00000000000008dc 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Relocation section '.rela.dyn' at offset 0x6d0 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000201dc0 000000000008 R_X86_64_RELATIVE a40
000000201dc8 000000000008 R_X86_64_RELATIVE ba2
000000201dd0 000000000008 R_X86_64_RELATIVE a00
000000202060 000000000008 R_X86_64_RELATIVE 202060
000000201fd0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000201fd8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 _Jv_RegisterClasses + 0
000000201fe0 000800000006 R_X86_64_GLOB_DAT 0000000000000000 _ZNSt8ios_base4InitD1E#GLIBCXX_3.4 + 0
000000201fe8 000900000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000201ff0 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
000000201ff8 000c00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize#GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x7c0 contains 9 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000202018 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts#GLIBC_2.2.5 + 0
000000202020 000500000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNSt8ios_base4InitC1E#GLIBCXX_3.4 + 0
000000202028 001600000007 R_X86_64_JUMP_SLO 0000000000000bb8 _ZN5boost6none_tC1ENS0 + 0
000000202030 000600000007 R_X86_64_JUMP_SLO 0000000000000000 recv#GLIBC_2.2.5 + 0
000000202038 000700000007 R_X86_64_JUMP_SLO 0000000000000000 __cxa_atexit#GLIBC_2.2.5 + 0
000000202040 000b00000007 R_X86_64_JUMP_SLO 0000000000000000 listen#GLIBC_2.2.5 + 0
000000202048 000d00000007 R_X86_64_JUMP_SLO 0000000000000000 socket#GLIBC_2.2.5 + 0
000000202050 000e00000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail#GLIBC_2.4 + 0
000000202058 000f00000007 R_X86_64_JUMP_SLO 0000000000000000 send#GLIBC_2.2.5 + 0
Symbol table '.dynsym' contains 24 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000898 0 SECTION LOCAL DEFAULT 9
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts#GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev#GLIBCXX_3.4 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv#GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev#GLIBCXX_3.4 (3)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen#GLIBC_2.2.5 (2)
12: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.2.5 (2)
13: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket#GLIBC_2.2.5 (2)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail#GLIBC_2.4 (5)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send#GLIBC_2.2.5 (4)
16: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
17: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
18: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
19: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
20: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
21: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
22: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
23: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
Symbol table '.symtab' contains 124 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000001c8 0 SECTION LOCAL DEFAULT 1
2: 00000000000001f0 0 SECTION LOCAL DEFAULT 2
3: 0000000000000238 0 SECTION LOCAL DEFAULT 3
4: 0000000000000478 0 SECTION LOCAL DEFAULT 4
5: 000000000000062c 0 SECTION LOCAL DEFAULT 5
6: 0000000000000660 0 SECTION LOCAL DEFAULT 6
7: 00000000000006d0 0 SECTION LOCAL DEFAULT 7
8: 00000000000007c0 0 SECTION LOCAL DEFAULT 8
9: 0000000000000898 0 SECTION LOCAL DEFAULT 9
10: 00000000000008c0 0 SECTION LOCAL DEFAULT 10
11: 0000000000000960 0 SECTION LOCAL DEFAULT 11
12: 0000000000000970 0 SECTION LOCAL DEFAULT 12
13: 0000000000000bc4 0 SECTION LOCAL DEFAULT 13
14: 0000000000000bd0 0 SECTION LOCAL DEFAULT 14
15: 0000000000000cd8 0 SECTION LOCAL DEFAULT 15
16: 0000000000000d10 0 SECTION LOCAL DEFAULT 16
17: 0000000000201dc0 0 SECTION LOCAL DEFAULT 17
18: 0000000000201dd0 0 SECTION LOCAL DEFAULT 18
19: 0000000000201dd8 0 SECTION LOCAL DEFAULT 19
20: 0000000000201de0 0 SECTION LOCAL DEFAULT 20
21: 0000000000201fd0 0 SECTION LOCAL DEFAULT 21
22: 0000000000202000 0 SECTION LOCAL DEFAULT 22
23: 0000000000202060 0 SECTION LOCAL DEFAULT 23
24: 0000000000202068 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
34: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_LIST__
35: 0000000000000970 0 FUNC LOCAL DEFAULT 12 deregister_tm_clones
36: 00000000000009b0 0 FUNC LOCAL DEFAULT 12 register_tm_clones
37: 0000000000000a00 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
38: 0000000000202068 1 OBJECT LOCAL DEFAULT 24 completed.7585
39: 0000000000201dd0 0 OBJECT LOCAL DEFAULT 18 __do_global_dtors_aux_fin
40: 0000000000000a40 0 FUNC LOCAL DEFAULT 12 frame_dummy
41: 0000000000201dc0 0 OBJECT LOCAL DEFAULT 17 __frame_dummy_init_array_
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS lib_elfhook.cpp
43: 0000000000000bd0 1 OBJECT LOCAL DEFAULT 14 _ZStL19piecewise_construc
44: 0000000000202069 1 OBJECT LOCAL DEFAULT 24 _ZStL8__ioinit
45: 0000000000000bd1 1 OBJECT LOCAL DEFAULT 14 _ZStL13allocator_arg
46: 0000000000000bd2 1 OBJECT LOCAL DEFAULT 14 _ZStL6ignore
47: 0000000000000bd3 1 OBJECT LOCAL DEFAULT 14 _ZStL10defer_lock
48: 0000000000000bd4 1 OBJECT LOCAL DEFAULT 14 _ZStL11try_to_lock
49: 0000000000000bd5 1 OBJECT LOCAL DEFAULT 14 _ZStL10adopt_lock
50: 0000000000000bd8 4 OBJECT LOCAL DEFAULT 14 _ZN9__gnu_cxxL21__default
51: 0000000000000bdc 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
52: 0000000000000be0 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
53: 0000000000000be4 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
54: 0000000000000be8 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
55: 0000000000000bf0 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
56: 0000000000000bf8 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
57: 0000000000000c00 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
58: 0000000000000c08 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
59: 0000000000000c10 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
60: 0000000000000c14 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MINE
61: 0000000000000c18 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MAXE
62: 0000000000000c1c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL15Level_ARRAY
63: 0000000000000c20 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL13DEFAULT_LEV
64: 000000000020206a 1 OBJECT LOCAL DEFAULT 24 _ZN5boostL4noneE
65: 0000000000000c24 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL13days_per
66: 0000000000000c28 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
67: 0000000000000c2c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL16days_per
68: 0000000000000c30 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
69: 0000000000000c34 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
70: 0000000000000c38 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12min_per_
71: 0000000000000c40 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12sec_per_
72: 0000000000000c48 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ms_per_h
73: 0000000000000c50 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11us_per_h
74: 0000000000000c58 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ns_per_h
75: 0000000000000c60 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11sec_per_
76: 0000000000000c68 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_m
77: 0000000000000c70 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_m
78: 0000000000000c78 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_m
79: 0000000000000c80 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_s
80: 0000000000000c84 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_s
81: 0000000000000c88 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_s
82: 0000000000000c90 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
83: 0000000000000c98 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ms
84: 0000000000000c9c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_ms
85: 0000000000000ca0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
86: 0000000000000ca8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_us
87: 0000000000000cb0 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_us
88: 0000000000000cb8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
89: 0000000000000cc0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_ns
90: 0000000000000cc8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ns
91: 0000000000000b1c 134 FUNC LOCAL DEFAULT 12 _Z41__static_initializati
92: 0000000000000ba2 21 FUNC LOCAL DEFAULT 12 _GLOBAL__sub_I_lib_elfhoo
93: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
94: 0000000000000dd8 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
95: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_END__
96: 0000000000000000 0 FILE LOCAL DEFAULT ABS
97: 0000000000000cd8 0 NOTYPE LOCAL DEFAULT 15 __GNU_EH_FRAME_HDR
98: 0000000000202000 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_
99: 0000000000202068 0 OBJECT LOCAL DEFAULT 23 __TMC_END__
100: 0000000000202060 0 OBJECT LOCAL DEFAULT 23 __dso_handle
101: 0000000000201de0 0 OBJECT LOCAL DEFAULT 20 _DYNAMIC
102: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
103: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
104: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
105: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts##GLIBC_2.2.5
106: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
107: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev##
108: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
109: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv##GLIBC_2.2.5
110: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
111: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev##
112: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
113: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
114: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen##GLIBC_2.2.5
115: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.2
116: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
117: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket##GLIBC_2.2.5
118: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
119: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail##GLIBC_2
120: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send##GLIBC_2.2.5
121: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
122: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
123: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
So what basically his code does is when you create shared library libtest.so that calls libc.so within it the following items are created within your library
a dynamic symbol table ( that includes data of all functions you are calling from libc.so )
a relocation table ( a list of entries within your code that called the functions within libc.so, every entry in a relocation table says that function X that belongs to libc.so was called in libtest.so in lines a,b,c...
His code parses your shared library, pulls the dynsymtable and the relocation table out of it and swaps symbols to your request by calling elf_hook() (see elf_hook.c lines 434 - 442).
You called three functions out of the libc.so API, which is a HUGE API, hence the dynsym in your table should contain symbols for socket() listen() and recv()
We can see dyn-symbols 13 11 and 6 are accordingly socket#GLIBC, listen#GLIBC and recv#GLIBC.
What the relocation table does is basically say where within the ACTUAL code of yours are those functions called, and when those symbols would have a resolved address which addresses would need to be replaced in order for your code to call the actual functions, as we also can see at .rela.plt you've posted as an output of the readelf command we see that on 3 different entries you've called theses symbols. These are what we need to replace.
So what his code does is find the index of the symbol you're looking to replace, go through ALL relocations, and see if they are relevant to the index-symbol. If so that means that in the place this relocation entry is relevant, it needs to replace it with the code you want.
Back with our previous example, lets say you want to replace socket() with y() in your libtest.so. His code finds the symbol index of socket(), finds where in code have you called socket() and replaces that with the address of y() instead.
Trying to hook symbols which don't exist
What can go wrong is the fact that when trying to hook symbols that weren't called is that simply there are no relocation entries for that symbol AND that symbol doesn't exist, you can see that e.g there is no entry in the dynsym table ( readelf output ) of bind().
What SHOULD happen is that he wouldn't find the according symbol and wont hook anything.
I honestly haven't gone through his entire code but my guess is that something went wrong there and he didn't handle the case of trying to hook a symbol that doesn't exist right...
Note:
Another thing that I've noticed that seems to be terrible wrong is the filling relocations of rel.dyn.
He has chosen to load the libs in his example with RTLD_LAZY, which basically means that every call to a DLL function would end up in jumping to some table of offsets, which point to your dynamic linker, and when the dynamic linker is called it replaces the offset which it was called from with the actual offset of the function... this is run-time relocation...
As far as I know rel.dyn is usually meant for load-time relocation, when the operating system loads an executable it copies it's code and looks at all the relocation entries and replaces them in code....
During run-time the offsets a rel.dyn table entries are pointing at would be within an executable section of the executable image, which means they SHOULD have only READ / EXECUTE permissions, not WRITE hence attempting to write into them SHOULD cause some segfault....
To sum things up, this probably happens because his utility didn't handle trying to hook an API function that does not exist within symbol table ( not called within your code ) right... hopefully I've helped you understand a little bit more of what happened...
Also, try reading this, it helped me to learn a lot about the ELF subject back in the day :)
http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf
Related
I'm trying to install the code from this git-repo for a university project and I'm stuck because ld does not seem to be able to link lua properly. I followed the install instructions and compile the code with:
catkin_make -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_CXX_STANDARD=14
which fails with several messages like:
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_toboolean(lua_State*, int)'
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_tonumberx(lua_State*, int, int*)'
...
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_pushstring(lua_State*, char const*)'
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_isstring(lua_State*, int)'
collect2: error: ld returned 1 exit status
The code was tested and works on Ubuntu 18.04 but I'm trying to get it to work on Manjaro. The manual states that liblua5.2-dev is needed and I installed lua52 from the AUR which seems to provide the right libraries.
The output of ldd is:
ldd /home/felixk/catkin_ws/devel/lib/libflatland_lib.so | grep lua
liblua5.2.so.5.2 => /usr/lib/liblua5.2.so.5.2 (0x00007f23fd51c000)
Then I checked if /usr/lib/liblua5.2.so.5.2 exists and it does. I tried to use readelf to check whether liblua5.2.so.5.2 contains the undefined references:
readelf -s /usr/lib/liblua5.2.so.5.2
Symbol table '.dynsym' contains 245 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free#GLIBC_2.2.5 (3)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort#GLIBC_2.2.5 (3)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND ldexp#GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
9: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.7 (5)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
13: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fread#GLIBC_2.2.5 (3)
14: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND stdin#GLIBC_2.2.5 (3)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
16: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
17: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atan#GLIBC_2.2.5 (4)
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND pow#GLIBC_2.29 (6)
19: 0000000000000000 0 FUNC GLOBAL DEFAULT UND clock#GLIBC_2.2.5 (3)
20: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
21: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
22: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.4 (7)
23: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
24: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
25: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
26: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
27: 0000000000000000 0 FUNC GLOBAL DEFAULT UND modf#GLIBC_2.2.5 (4)
28: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
29: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
30: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
31: 0000000000000000 0 FUNC GLOBAL DEFAULT UND close#GLIBC_2.2.5 (3)
32: 0000000000000000 0 FUNC GLOBAL DEFAULT UND log#GLIBC_2.29 (6)
33: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fmod#GLIBC_2.2.5 (4)
34: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
35: 0000000000000000 0 FUNC GLOBAL DEFAULT UND cos#GLIBC_2.2.5 (4)
36: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
37: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
38: 0000000000000000 0 FUNC GLOBAL DEFAULT UND acos#GLIBC_2.2.5 (4)
39: 0000000000000000 0 FUNC GLOBAL DEFAULT UND srand#GLIBC_2.2.5 (3)
40: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
41: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fgets#GLIBC_2.2.5 (3)
42: 0000000000000000 0 FUNC GLOBAL DEFAULT UND frexp#GLIBC_2.2.5 (4)
43: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
44: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
45: 0000000000000000 0 FUNC GLOBAL DEFAULT UND log10#GLIBC_2.2.5 (4)
46: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
47: 0000000000000000 0 FUNC GLOBAL DEFAULT UND feof#GLIBC_2.2.5 (3)
48: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
49: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
50: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND memcpy#GLIBC_2.14 (9)
52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
53: 0000000000000000 0 FUNC GLOBAL DEFAULT UND cosh#GLIBC_2.2.5 (4)
54: 0000000000000000 0 FUNC GLOBAL DEFAULT UND time#GLIBC_2.2.5 (3)
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sinh#GLIBC_2.2.5 (4)
57: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tan#GLIBC_2.2.5 (4)
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
61: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
62: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atan2#GLIBC_2.2.5 (4)
63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
64: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
65: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
70: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.11 (11)
71: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
72: 0000000000000000 0 FUNC GLOBAL DEFAULT UND popen#GLIBC_2.2.5 (3)
73: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fopen#GLIBC_2.2.5 (3)
74: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
75: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sin#GLIBC_2.2.5 (4)
76: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tanh#GLIBC_2.2.5 (4)
77: 0000000000000000 0 FUNC GLOBAL DEFAULT UND asin#GLIBC_2.2.5 (4)
78: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit#GLIBC_2.2.5 (3)
79: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
80: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
81: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
82: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sqrt#GLIBC_2.2.5 (4)
83: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
84: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
85: 0000000000000000 0 FUNC WEAK DEFAULT UND [...]#GLIBC_2.2.5 (3)
86: 0000000000000000 0 FUNC GLOBAL DEFAULT UND getc#GLIBC_2.2.5 (3)
87: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
88: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exp#GLIBC_2.29 (6)
89: 0000000000000000 0 FUNC GLOBAL DEFAULT UND rand#GLIBC_2.2.5 (3)
90: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
91: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
92: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
93: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
94: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
95: 0000000000007680 135 FUNC GLOBAL DEFAULT 9 lua_arith
96: 0000000000008640 32 FUNC GLOBAL DEFAULT 9 lua_getctx
97: 00000000000085d0 97 FUNC GLOBAL DEFAULT 9 lua_setuservalue
98: 0000000000008bd0 24 FUNC GLOBAL DEFAULT 9 lua_getallocf
99: 00000000000086f0 273 FUNC GLOBAL DEFAULT 9 lua_pcallk
100: 0000000000007a80 47 FUNC GLOBAL DEFAULT 9 lua_touserdata
101: 000000000000aff0 1192 FUNC GLOBAL DEFAULT 9 lua_getinfo
102: 000000000001b420 169 FUNC GLOBAL DEFAULT 9 luaL_openlib
103: 0000000000007460 60 FUNC GLOBAL DEFAULT 9 lua_insert
104: 0000000000007580 83 FUNC GLOBAL DEFAULT 9 lua_isnumber
105: 00000000000149d0 231 FUNC GLOBAL DEFAULT 9 lua_newthread
106: 0000000000024d90 117 FUNC GLOBAL DEFAULT 9 luaL_openlibs
107: 000000000001b360 183 FUNC GLOBAL DEFAULT 9 luaL_setfuncs
108: 000000000001ae50 275 FUNC GLOBAL DEFAULT 9 luaL_tolstring
109: 00000000000074a0 30 FUNC GLOBAL DEFAULT 9 lua_replace
110: 000000000001a840 38 FUNC GLOBAL DEFAULT 9 luaL_buffinitsize
111: 0000000000008df0 72 FUNC GLOBAL DEFAULT 9 lua_upvalueid
112: 0000000000007ef0 108 FUNC GLOBAL DEFAULT 9 lua_getglobal
113: 00000000000209c0 42 FUNC GLOBAL DEFAULT 9 luaopen_os
114: 000000000001a870 214 FUNC GLOBAL DEFAULT 9 luaL_ref
115: 000000000000ae00 5 FUNC GLOBAL DEFAULT 9 lua_gethook
116: 0000000000007370 24 FUNC GLOBAL DEFAULT 9 lua_version
117: 0000000000008260 39 FUNC GLOBAL DEFAULT 9 lua_settable
118: 0000000000019b40 159 FUNC GLOBAL DEFAULT 9 luaL_where
119: 000000000001a1f0 63 FUNC GLOBAL DEFAULT 9 luaL_checktype
120: 000000000001a230 58 FUNC GLOBAL DEFAULT 9 luaL_checkany
121: 0000000000019e90 132 FUNC GLOBAL DEFAULT 9 luaL_fileresult
122: 000000000001a5b0 57 FUNC GLOBAL DEFAULT 9 luaL_optunsigned
123: 0000000000008e40 92 FUNC GLOBAL DEFAULT 9 lua_upvaluejoin
124: 000000000001a050 33 FUNC GLOBAL DEFAULT 9 luaL_setmetatable
125: 000000000001a9b0 656 FUNC GLOBAL DEFAULT 9 luaL_loadfilex
126: 0000000000008c00 76 FUNC GLOBAL DEFAULT 9 lua_newuserdata
127: 0000000000007600 26 FUNC GLOBAL DEFAULT 9 lua_isuserdata
128: 000000000001a2c0 106 FUNC GLOBAL DEFAULT 9 luaL_optlstring
129: 000000000001a6f0 44 FUNC GLOBAL DEFAULT 9 luaL_addstring
130: 0000000000007390 34 FUNC GLOBAL DEFAULT 9 lua_absindex
131: 0000000000007c40 98 FUNC GLOBAL DEFAULT 9 lua_pushstring
132: 00000000000078a0 133 FUNC GLOBAL DEFAULT 9 lua_tounsignedx
133: 0000000000008660 135 FUNC GLOBAL DEFAULT 9 lua_callk
134: 0000000000007560 26 FUNC GLOBAL DEFAULT 9 lua_iscfunction
135: 000000000001ad60 85 FUNC GLOBAL DEFAULT 9 luaL_callmeta
136: 000000000001c470 127 FUNC GLOBAL DEFAULT 9 luaopen_base
137: 00000000000250e0 129 OBJECT GLOBAL DEFAULT 11 lua_ident
138: 0000000000008810 219 FUNC GLOBAL DEFAULT 9 lua_load
139: 000000000001acd0 139 FUNC GLOBAL DEFAULT 9 luaL_getmetafield
140: 0000000000007fe0 44 FUNC GLOBAL DEFAULT 9 lua_rawget
141: 00000000000074c0 37 FUNC GLOBAL DEFAULT 9 lua_copy
142: 0000000000008290 94 FUNC GLOBAL DEFAULT 9 lua_setfield
143: 00000000000072e0 102 FUNC GLOBAL DEFAULT 9 lua_xmove
144: 000000000001f430 216 FUNC GLOBAL DEFAULT 9 luaopen_io
145: 0000000000008d10 221 FUNC GLOBAL DEFAULT 9 lua_setupvalue
146: 0000000000019cd0 315 FUNC GLOBAL DEFAULT 9 luaL_argerror
147: 00000000000080c0 102 FUNC GLOBAL DEFAULT 9 lua_createtable
148: 0000000000007350 22 FUNC GLOBAL DEFAULT 9 lua_atpanic
149: 0000000000008010 50 FUNC GLOBAL DEFAULT 9 lua_rawgeti
150: 000000000000c7a0 155 FUNC GLOBAL DEFAULT 9 lua_yieldk
151: 0000000000008b10 145 FUNC GLOBAL DEFAULT 9 lua_concat
152: 000000000001a330 157 FUNC GLOBAL DEFAULT 9 luaL_checkoption
153: 0000000000008050 108 FUNC GLOBAL DEFAULT 9 lua_rawgetp
154: 0000000000008930 391 FUNC GLOBAL DEFAULT 9 lua_gc
155: 00000000000073e0 64 FUNC GLOBAL DEFAULT 9 lua_settop
156: 000000000001b040 127 FUNC GLOBAL DEFAULT 9 luaL_getsubtable
157: 0000000000007dd0 175 FUNC GLOBAL DEFAULT 9 lua_pushcclosure
158: 000000000001ac40 72 FUNC GLOBAL DEFAULT 9 luaL_loadbufferx
159: 0000000000008bf0 12 FUNC GLOBAL DEFAULT 9 lua_setallocf
160: 0000000000007b30 20 FUNC GLOBAL DEFAULT 9 lua_pushnil
161: 0000000000007a50 39 FUNC GLOBAL DEFAULT 9 lua_tocfunction
162: 000000000001a490 109 FUNC GLOBAL DEFAULT 9 luaL_checkinteger
163: 0000000000019f20 175 FUNC GLOBAL DEFAULT 9 luaL_execresult
164: 000000000000ae10 5 FUNC GLOBAL DEFAULT 9 lua_gethookmask
165: 00000000000082f0 126 FUNC GLOBAL DEFAULT 9 lua_rawset
166: 0000000000008920 5 FUNC GLOBAL DEFAULT 9 lua_status
167: 0000000000008ad0 50 FUNC GLOBAL DEFAULT 9 lua_next
168: 000000000001a180 105 FUNC GLOBAL DEFAULT 9 luaL_checkstack
169: 00000000000081e0 119 FUNC GLOBAL DEFAULT 9 lua_setglobal
170: 000000000001a440 67 FUNC GLOBAL DEFAULT 9 luaL_optnumber
171: 0000000000007420 55 FUNC GLOBAL DEFAULT 9 lua_remove
172: 000000000000af50 154 FUNC GLOBAL DEFAULT 9 lua_setlocal
173: 0000000000019fd0 122 FUNC GLOBAL DEFAULT 9 luaL_newmetatable
174: 0000000000014b10 16 FUNC GLOBAL DEFAULT 9 lua_close
175: 000000000000ae20 4 FUNC GLOBAL DEFAULT 9 lua_gethookcount
176: 00000000000077a0 119 FUNC GLOBAL DEFAULT 9 lua_tonumberx
177: 0000000000007cb0 64 FUNC GLOBAL DEFAULT 9 lua_pushvfstring
178: 0000000000007710 143 FUNC GLOBAL DEFAULT 9 lua_compare
179: 0000000000007e80 29 FUNC GLOBAL DEFAULT 9 lua_pushboolean
180: 0000000000007f60 38 FUNC GLOBAL DEFAULT 9 lua_gettable
181: 000000000001ffa0 118 FUNC GLOBAL DEFAULT 9 luaopen_math
182: 0000000000007ba0 53 FUNC GLOBAL DEFAULT 9 lua_pushunsigned
183: 000000000001b0c0 174 FUNC GLOBAL DEFAULT 9 luaL_requiref
184: 000000000000c650 328 FUNC GLOBAL DEFAULT 9 lua_resume
185: 0000000000008370 110 FUNC GLOBAL DEFAULT 9 lua_rawseti
186: 00000000000088f0 41 FUNC GLOBAL DEFAULT 9 lua_dump
187: 000000000001adc0 130 FUNC GLOBAL DEFAULT 9 luaL_len
188: 0000000000022f50 167 FUNC GLOBAL DEFAULT 9 luaopen_string
189: 0000000000007ec0 40 FUNC GLOBAL DEFAULT 9 lua_pushthread
190: 000000000001b170 224 FUNC GLOBAL DEFAULT 9 luaL_gsub
191: 0000000000008c50 181 FUNC GLOBAL DEFAULT 9 lua_getupvalue
192: 00000000000083e0 174 FUNC GLOBAL DEFAULT 9 lua_rawsetp
193: 0000000000007be0 88 FUNC GLOBAL DEFAULT 9 lua_pushlstring
194: 000000000001a720 71 FUNC GLOBAL DEFAULT 9 luaL_pushresult
195: 000000000000adc0 54 FUNC GLOBAL DEFAULT 9 lua_sethook
196: 00000000000075e0 27 FUNC GLOBAL DEFAULT 9 lua_isstring
197: 0000000000019820 800 FUNC GLOBAL DEFAULT 9 luaL_traceback
198: 000000000001a5f0 193 FUNC GLOBAL DEFAULT 9 luaL_prepbuffsize
199: 000000000001a120 85 FUNC GLOBAL DEFAULT 9 luaL_checkudata
200: 0000000000008ac0 9 FUNC GLOBAL DEFAULT 9 lua_error
201: 000000000001a950 83 FUNC GLOBAL DEFAULT 9 luaL_unref
202: 000000000001e150 42 FUNC GLOBAL DEFAULT 9 luaopen_debug
203: 000000000001b280 217 FUNC GLOBAL DEFAULT 9 luaL_checkversion_
204: 000000000001caa0 42 FUNC GLOBAL DEFAULT 9 luaopen_bit32
205: 0000000000007b50 25 FUNC GLOBAL DEFAULT 9 lua_pushnumber
206: 000000000001a780 146 FUNC GLOBAL DEFAULT 9 luaL_addvalue
207: 000000000001a500 107 FUNC GLOBAL DEFAULT 9 luaL_checkunsigned
208: 000000000001a6c0 46 FUNC GLOBAL DEFAULT 9 luaL_addlstring
209: 0000000000007ab0 21 FUNC GLOBAL DEFAULT 9 lua_tothread
210: 000000000001cf50 42 FUNC GLOBAL DEFAULT 9 luaopen_coroutine
211: 0000000000007620 87 FUNC GLOBAL DEFAULT 9 lua_rawequal
212: 00000000000074f0 33 FUNC GLOBAL DEFAULT 9 lua_pushvalue
213: 0000000000008130 105 FUNC GLOBAL DEFAULT 9 lua_getmetatable
214: 0000000000014720 683 FUNC GLOBAL DEFAULT 9 lua_newstate
215: 0000000000007b70 34 FUNC GLOBAL DEFAULT 9 lua_pushinteger
216: 0000000000023b40 79 FUNC GLOBAL DEFAULT 9 luaopen_table
217: 0000000000007f90 79 FUNC GLOBAL DEFAULT 9 lua_getfield
218: 000000000001a570 57 FUNC GLOBAL DEFAULT 9 luaL_optinteger
219: 0000000000019be0 234 FUNC GLOBAL DEFAULT 9 luaL_error
220: 0000000000007930 47 FUNC GLOBAL DEFAULT 9 lua_toboolean
221: 0000000000007ea0 23 FUNC GLOBAL DEFAULT 9 lua_pushlightuserdata
222: 00000000000079e0 111 FUNC GLOBAL DEFAULT 9 lua_rawlen
223: 0000000000007230 162 FUNC GLOBAL DEFAULT 9 lua_checkstack
224: 0000000000007cf0 218 FUNC GLOBAL DEFAULT 9 lua_pushfstring
225: 0000000000008490 317 FUNC GLOBAL DEFAULT 9 lua_setmetatable
226: 0000000000007ad0 96 FUNC GLOBAL DEFAULT 9 lua_topointer
227: 0000000000007540 18 FUNC GLOBAL DEFAULT 9 lua_typename
228: 0000000000007960 128 FUNC GLOBAL DEFAULT 9 lua_tolstring
229: 000000000001a820 28 FUNC GLOBAL DEFAULT 9 luaL_buffinit
230: 000000000001a770 10 FUNC GLOBAL DEFAULT 9 luaL_pushresultsize
231: 000000000001af70 207 FUNC GLOBAL DEFAULT 9 luaL_pushmodule
232: 000000000001b250 47 FUNC GLOBAL DEFAULT 9 luaL_newstate
233: 000000000001a080 148 FUNC GLOBAL DEFAULT 9 luaL_testudata
234: 0000000000007520 30 FUNC GLOBAL DEFAULT 9 lua_type
235: 000000000000ae80 199 FUNC GLOBAL DEFAULT 9 lua_getlocal
236: 000000000001a270 77 FUNC GLOBAL DEFAULT 9 luaL_checklstring
237: 0000000000008bb0 31 FUNC GLOBAL DEFAULT 9 lua_len
238: 000000000000ae30 79 FUNC GLOBAL DEFAULT 9 lua_getstack
239: 000000000001ac90 50 FUNC GLOBAL DEFAULT 9 luaL_loadstring
240: 00000000000081a0 64 FUNC GLOBAL DEFAULT 9 lua_getuservalue
241: 00000000000073c0 23 FUNC GLOBAL DEFAULT 9 lua_gettop
242: 0000000000007820 117 FUNC GLOBAL DEFAULT 9 lua_tointegerx
243: 0000000000024b50 568 FUNC GLOBAL DEFAULT 9 luaopen_package
244: 000000000001a3d0 111 FUNC GLOBAL DEFAULT 9 luaL_checknumber
It seems like all the undefined references exist in /usr/lib/liblua5.2.so.5.2 and I don't know how to go on from here.
Other answers on SO suggest to put the #includes of lua into a extern "C" like so:
extern "C"{
#include <lua5.2/lualib.h>
#include <lua5.2/lauxlib.h>
#include <lua5.2/lua.h>
}
But I would rather not change the given code and wouldn't even know how to find out in which files lua is #included .
Optimally I would only like to change the make command catkin_make -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_CXX_STANDARD=14 to help ld to properly link but I don't know if thats possible. I'm not really familiar with make, cmake or in this case catkin_make and couldn't find out if it is possible to add linker options in the make command.
Lua can be compiled both as C ans C++ languages. This is an advertised feature of it. For that reason, Lua authors decided not to include the classic extern "C" in the headers.
Your liblua5.2.so.5.2 library was compiled in C language and the symbols are not mangled. You compiled your application in C++ mode with just including Lua headers without extern "C", so your Lua included symbols are mangled.
Solution: wrap your include with extern "C":
extern "C"
{
#include "lua.h"
}
The other solution would be to recompile Lua 5.2 as C++ language (with -x c++ compiler option for GCC and Clang, or /TP compiler option for MSVC).
I got it working thanks to prapin's answer :)
I installed lua 5.2 from source following the lua manual.
Instead of prapins suggestion to use the -x c++ compiler option I changed the following in the makefile in lua-5.2.0/src:
changed CC= gcc to CC= g++
added -shared -fPIC to MYCFLAGS= because I needed the .so file.
I hope this helps anybody with this problem who does not want to wrap the includes in extern "C"
i'm a beginner coder here.
so I have a file with main that looks like this
#include <iostream>
#include "Helper.hpp"
using namespace std;
int main(int argc, char* argv[])
{
cout<<argc<<endl;
return 0;
}
and I linked it with 2 other .cpp
I'm just wondering why the executable comes out to be so big (330kb)
when the main doesn't even call any functions.
are all the methods and variables in my other 2 .cpp wrapped up in the executable even though
I haven't actually called any functions? I only have 1 extern int declared. no static functions
this is the makefile call I used to compile
CXX=g++
CXXFLAGS =-Wall -pedantic -g -O0 -std=c++11
test: Helper.cpp Helper.hpp HCTree.cpp HCTree.hpp
$(CXX) $(CXXFLAGS) -o test test.cpp Helper.cpp HCTree.cpp
and I call "make test"
Reason is that your binary will include parts of the standard libraries and the symbol maps, even if you compile the extreme trivial case as follows:
main.cpp
using namespace std;
int main(int argc, char* argv[])
{
return 0;
}
~# g++ -Wall -pedantic -g -O0 -std=c++11 -o test main.cpp
~# ls -ltr
-rwxrwxr-x 1 jordan jordan 10264 Mar 1 08:14 test
after compiling it, my binary is around 10k. If you are compiling it for linux, you can see what is in the binary by calling readelf -a or by examining the symbols in the file with nm.
~# readelf -a test
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: AArch64
Version: 0x1
Entry point address: 0x610
Start of program headers: 64 (bytes into file)
Start of section headers: 8152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000000238 00000238
000000000000001b 0000000000000000 A 0 0 1
[ 2] .note.gnu.build-i NOTE 0000000000000254 00000254
0000000000000024 0000000000000000 A 0 0 4
[ 3] .note.ABI-tag NOTE 0000000000000278 00000278
0000000000000020 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000000298 00000298
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000000002b8 000002b8
00000000000000d8 0000000000000018 A 6 3 8
[ 6] .dynstr STRTAB 0000000000000390 00000390
0000000000000082 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000000412 00000412
0000000000000012 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000000428 00000428
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000000448 00000448
00000000000000f0 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000000538 00000538
0000000000000060 0000000000000018 AI 5 21 8
[11] .init PROGBITS 0000000000000598 00000598
0000000000000014 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 00000000000005b0 000005b0
0000000000000060 0000000000000010 AX 0 0 16
[13] .text PROGBITS 0000000000000610 00000610
00000000000001ac 0000000000000000 AX 0 0 8
[14] .fini PROGBITS 00000000000007bc 000007bc
0000000000000010 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 00000000000007cc 000007cc
0000000000000004 0000000000000004 AM 0 0 4
[16] .eh_frame_hdr PROGBITS 00000000000007d0 000007d0
0000000000000044 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000000818 00000818
00000000000000dc 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000010d88 00000d88
0000000000000008 0000000000000008 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000010d90 00000d90
0000000000000008 0000000000000008 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000010d98 00000d98
00000000000001f0 0000000000000010 WA 6 0 8
[21] .got PROGBITS 0000000000010f88 00000f88
0000000000000078 0000000000000008 WA 0 0 8
[22] .data PROGBITS 0000000000011000 00001000
0000000000000010 0000000000000000 WA 0 0 8
[23] .bss NOBITS 0000000000011010 00001010
0000000000000008 0000000000000000 WA 0 0 1
[24] .comment PROGBITS 0000000000000000 00001010
000000000000002a 0000000000000001 MS 0 0 1
[25] .debug_aranges PROGBITS 0000000000000000 0000103a
0000000000000030 0000000000000000 0 0 1
[26] .debug_info PROGBITS 0000000000000000 0000106a
0000000000000098 0000000000000000 0 0 1
[27] .debug_abbrev PROGBITS 0000000000000000 00001102
0000000000000078 0000000000000000 0 0 1
[28] .debug_line PROGBITS 0000000000000000 0000117a
0000000000000050 0000000000000000 0 0 1
[29] .debug_str PROGBITS 0000000000000000 000011ca
00000000000000bf 0000000000000001 MS 0 0 1
[30] .symtab SYMTAB 0000000000000000 00001290
0000000000000900 0000000000000018 31 73 8
[31] .strtab STRTAB 0000000000000000 00001b90
000000000000030d 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 00001e9d
000000000000013a 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R 0x8
INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x000000000000001b 0x000000000000001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000008f4 0x00000000000008f4 R E 0x10000
LOAD 0x0000000000000d88 0x0000000000010d88 0x0000000000010d88
0x0000000000000288 0x0000000000000290 RW 0x10000
DYNAMIC 0x0000000000000d98 0x0000000000010d98 0x0000000000010d98
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x00000000000007d0 0x00000000000007d0 0x00000000000007d0
0x0000000000000044 0x0000000000000044 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000000d88 0x0000000000010d88 0x0000000000010d88
0x0000000000000278 0x0000000000000278 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
Dynamic section at offset 0xd98 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x598
0x000000000000000d (FINI) 0x7bc
0x0000000000000019 (INIT_ARRAY) 0x10d88
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x10d90
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x298
0x0000000000000005 (STRTAB) 0x390
0x0000000000000006 (SYMTAB) 0x2b8
0x000000000000000a (STRSZ) 130 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x10f88
0x0000000000000002 (PLTRELSZ) 96 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x538
0x0000000000000007 (RELA) 0x448
0x0000000000000008 (RELASZ) 240 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0x428
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x412
0x000000006ffffff9 (RELACOUNT) 6
0x0000000000000000 (NULL) 0x0
Relocation section '.rela.dyn' at offset 0x448 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000010d88 000000000403 R_AARCH64_RELATIV 718
000000010d90 000000000403 R_AARCH64_RELATIV 6d0
000000010fc8 000000000403 R_AARCH64_RELATIV 7b8
000000010fe8 000000000403 R_AARCH64_RELATIV 738
000000010ff0 000000000403 R_AARCH64_RELATIV 71c
000000011008 000000000403 R_AARCH64_RELATIV 11008
000000010fd0 000300000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_deregisterTMClone + 0
000000010fd8 000400000401 R_AARCH64_GLOB_DA 0000000000000000 __cxa_finalize#GLIBC_2.17 + 0
000000010fe0 000600000401 R_AARCH64_GLOB_DA 0000000000000000 __gmon_start__ + 0
000000010ff8 000800000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCloneTa + 0
Relocation section '.rela.plt' at offset 0x538 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000010fa0 000400000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize#GLIBC_2.17 + 0
000000010fa8 000500000402 R_AARCH64_JUMP_SL 0000000000000000 __libc_start_main#GLIBC_2.17 + 0
000000010fb0 000600000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0
000000010fb8 000700000402 R_AARCH64_JUMP_SL 0000000000000000 abort#GLIBC_2.17 + 0
The decoding of unwind sections for machine type AArch64 is not currently supported.
Symbol table '.dynsym' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000598 0 SECTION LOCAL DEFAULT 11
2: 0000000000011000 0 SECTION LOCAL DEFAULT 22
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
4: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.17 (2)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort#GLIBC_2.17 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
Symbol table '.symtab' contains 96 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000238 0 SECTION LOCAL DEFAULT 1
2: 0000000000000254 0 SECTION LOCAL DEFAULT 2
3: 0000000000000278 0 SECTION LOCAL DEFAULT 3
4: 0000000000000298 0 SECTION LOCAL DEFAULT 4
5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5
6: 0000000000000390 0 SECTION LOCAL DEFAULT 6
7: 0000000000000412 0 SECTION LOCAL DEFAULT 7
8: 0000000000000428 0 SECTION LOCAL DEFAULT 8
9: 0000000000000448 0 SECTION LOCAL DEFAULT 9
10: 0000000000000538 0 SECTION LOCAL DEFAULT 10
11: 0000000000000598 0 SECTION LOCAL DEFAULT 11
12: 00000000000005b0 0 SECTION LOCAL DEFAULT 12
13: 0000000000000610 0 SECTION LOCAL DEFAULT 13
14: 00000000000007bc 0 SECTION LOCAL DEFAULT 14
15: 00000000000007cc 0 SECTION LOCAL DEFAULT 15
16: 00000000000007d0 0 SECTION LOCAL DEFAULT 16
17: 0000000000000818 0 SECTION LOCAL DEFAULT 17
18: 0000000000010d88 0 SECTION LOCAL DEFAULT 18
19: 0000000000010d90 0 SECTION LOCAL DEFAULT 19
20: 0000000000010d98 0 SECTION LOCAL DEFAULT 20
21: 0000000000010f88 0 SECTION LOCAL DEFAULT 21
22: 0000000000011000 0 SECTION LOCAL DEFAULT 22
23: 0000000000011010 0 SECTION LOCAL DEFAULT 23
24: 0000000000000000 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
31: 0000000000000278 0 NOTYPE LOCAL DEFAULT 3 $d
32: 0000000000000610 0 NOTYPE LOCAL DEFAULT 13 $x
33: 00000000000007cc 0 NOTYPE LOCAL DEFAULT 15 $d
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
35: 0000000000000648 0 NOTYPE LOCAL DEFAULT 13 $x
36: 0000000000000648 20 FUNC LOCAL DEFAULT 13 call_weak_fn
37: 0000000000000598 0 NOTYPE LOCAL DEFAULT 11 $x
38: 00000000000007bc 0 NOTYPE LOCAL DEFAULT 14 $x
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
40: 00000000000005a4 0 NOTYPE LOCAL DEFAULT 11 $x
41: 00000000000007c4 0 NOTYPE LOCAL DEFAULT 14 $x
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
43: 0000000000000660 0 NOTYPE LOCAL DEFAULT 13 $x
44: 0000000000000660 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
45: 0000000000000690 0 FUNC LOCAL DEFAULT 13 register_tm_clones
46: 0000000000011008 0 NOTYPE LOCAL DEFAULT 22 $d
47: 00000000000006d0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
48: 0000000000011010 1 OBJECT LOCAL DEFAULT 23 completed.9126
49: 0000000000010d90 0 NOTYPE LOCAL DEFAULT 19 $d
50: 0000000000010d90 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin
51: 0000000000000718 0 FUNC LOCAL DEFAULT 13 frame_dummy
52: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 18 $d
53: 0000000000010d88 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_
54: 000000000000082c 0 NOTYPE LOCAL DEFAULT 17 $d
55: 0000000000011010 0 NOTYPE LOCAL DEFAULT 23 $d
56: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.cpp
57: 000000000000071c 0 NOTYPE LOCAL DEFAULT 13 $x
58: 0000000000000890 0 NOTYPE LOCAL DEFAULT 17 $d
59: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.oS
60: 0000000000000738 0 NOTYPE LOCAL DEFAULT 13 $x
61: 00000000000008a8 0 NOTYPE LOCAL DEFAULT 17 $d
62: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
63: 00000000000008f0 0 NOTYPE LOCAL DEFAULT 17 $d
64: 00000000000008f0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
65: 0000000000000000 0 FILE LOCAL DEFAULT ABS
66: 0000000000010d90 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
67: 0000000000010d98 0 OBJECT LOCAL DEFAULT ABS _DYNAMIC
68: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
69: 00000000000007d0 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR
70: 0000000000010fc0 0 OBJECT LOCAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
71: 0000000000000598 0 FUNC LOCAL DEFAULT 11 _init
72: 00000000000005b0 0 NOTYPE LOCAL DEFAULT 12 $x
73: 00000000000007b8 4 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
75: 0000000000011000 0 NOTYPE WEAK DEFAULT 22 data_start
76: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start__
77: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.1
78: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _bss_end__
79: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 22 _edata
80: 00000000000007bc 0 FUNC GLOBAL HIDDEN 14 _fini
81: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __bss_end__
82: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_
83: 0000000000011000 0 NOTYPE GLOBAL DEFAULT 22 __data_start
84: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
85: 0000000000011008 0 OBJECT GLOBAL HIDDEN 22 __dso_handle
86: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort##GLIBC_2.17
87: 00000000000007cc 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
88: 0000000000000738 124 FUNC GLOBAL DEFAULT 13 __libc_csu_init
89: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _end
90: 0000000000000610 0 FUNC GLOBAL DEFAULT 13 _start
91: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __end__
92: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start
93: 000000000000071c 24 FUNC GLOBAL DEFAULT 13 main
94: 0000000000011010 0 OBJECT GLOBAL HIDDEN 22 __TMC_END__
95: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
Version symbols section '.gnu.version' contains 9 entries:
Addr: 0x0000000000000412 Offset: 0x000412 Link: 5 (.dynsym)
000: 0 (*local*) 0 (*local*) 0 (*local*) 0 (*local*)
004: 2 (GLIBC_2.17) 2 (GLIBC_2.17) 0 (*local*) 2 (GLIBC_2.17)
008: 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entry:
Addr: 0x0000000000000428 Offset: 0x000428 Link: 6 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 1
0x0010: Name: GLIBC_2.17 Flags: none Version: 2
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 3e05092df57e4b081d4823e60f0e74fa226ac79f
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.7.0
~# nm -a test
nm -a test
0000000000000000 a
U abort##GLIBC_2.17
0000000000011010 b .bss
0000000000011018 B __bss_end__
0000000000011018 B _bss_end__
0000000000011010 B __bss_start
0000000000011010 B __bss_start__
0000000000000648 t call_weak_fn
0000000000000000 n .comment
0000000000011010 b completed.9126
0000000000000000 a crtstuff.c
0000000000000000 a crtstuff.c
w __cxa_finalize##GLIBC_2.17
0000000000011000 d .data
0000000000011000 D __data_start
0000000000011000 W data_start
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_str
0000000000000660 t deregister_tm_clones
00000000000006d0 t __do_global_dtors_aux
0000000000010d90 d __do_global_dtors_aux_fini_array_entry
0000000000011008 D __dso_handle
0000000000010d98 d .dynamic
0000000000010d98 a _DYNAMIC
0000000000000390 r .dynstr
00000000000002b8 r .dynsym
0000000000011010 D _edata
0000000000000818 r .eh_frame
00000000000007d0 r .eh_frame_hdr
0000000000000000 a elf-init.oS
0000000000011018 B __end__
0000000000011018 B _end
00000000000007bc t .fini
00000000000007bc T _fini
0000000000010d90 d .fini_array
0000000000000718 t frame_dummy
0000000000010d88 d __frame_dummy_init_array_entry
00000000000008f0 r __FRAME_END__
0000000000010fc0 a _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00000000000007d0 r __GNU_EH_FRAME_HDR
0000000000000298 r .gnu.hash
0000000000000412 r .gnu.version
0000000000000428 r .gnu.version_r
0000000000010f88 d .got
0000000000000598 t .init
0000000000000598 t _init
0000000000010d88 d .init_array
0000000000010d90 d __init_array_end
0000000000010d88 d __init_array_start
0000000000000238 r .interp
00000000000007cc R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000007b8 T __libc_csu_fini
0000000000000738 T __libc_csu_init
U __libc_start_main##GLIBC_2.17
000000000000071c T main
0000000000000000 a main.cpp
0000000000000278 r .note.ABI-tag
0000000000000254 r .note.gnu.build-id
00000000000005b0 t .plt
0000000000000690 t register_tm_clones
0000000000000448 r .rela.dyn
0000000000000538 r .rela.plt
00000000000007cc r .rodata
0000000000000610 T _start
0000000000000610 t .text
0000000000011010 D __TMC_END__
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/crti.o
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/crtn.o
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/Scrt1.o
You can lower the size by stripping the symbols as follows:
~# strip test
~# ls -ltr
-rwxrwxr-x 1 jordan jordan 6056 Mar 1 08:21 test
so the file went from 10k to 6k.
I've compiled a simple object file file and tried to link with ld, but it gave that warning. However, the file has _start symbol, Here's the readelf of the object.
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x40
Start of program headers: 0 (bytes into file)
Start of section headers: 59392 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 6
Section header string table index: 5
(...)
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
000000000000005c 0000000000000000 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00001040
0000000000001000 0000000000000000 WA 0 0 8
[ 3] .symtab SYMTAB 0000000000000000 00003400
0000000000000030 0000000000000018 4 2 8
[ 4] .strtab STRTAB 0000000000000000 00003800
0000000000000400 0000000000000000 0 0 1
[ 5] .shstrtab STRTAB 0000000000000000 00003000
0000000000000400 0000000000000000 0 0 1
(...)
Symbol table '.symtab' contains 2 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 87 FUNC GLOBAL DEFAULT 1 _start
What could be the problem here
So, I found the problem. The info of symbol section header must be the index of the _start function in the symbol table. But for some reason the linker change that later, but It worked just fine!!
This question relates specifically to the x86 architecture, g++ compiler and c++ code.
So, I have the following code:
#include <iostream>
int second;
class First {
private:
int hello;
public:
First(int number)
{
hello = number;
}
void printStuff()
{
std::cout<<this->hello<<'\n';
}
};
int main(int argc, char** argv)
{
First *first = new First(argc);
first->printStuff();
second = argc;
return 0;
}
After compiling it like so:
g++ -O0 -g class.cpp -o class
I get the output class binary.
Now, I want to know where hello is stored, so I do readelf -s ./class and the output is:
[ishaypeled#escorpio tmp14]$ readelf -s --wide ./class
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi#GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev#GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c#GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm#GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev#GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout#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: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 _ZStL19piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 _ZStL8__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 _Z41__static_initialization_and_destruction_0ii
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi##GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev##GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c##GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev##GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC1Ei
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 _ZN5First10printStuffEv
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC2Ei
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout##GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm##GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
For better readability, I also ran this command:
[ishaypeled#escorpio tmp14]$ readelf -s --wide ./class | c++filt
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)#GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()#GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)#GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)#GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()#GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout#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: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 std::piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 std::__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 __static_initialization_and_destruction_0(int, int)
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)##GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()##GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)##GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()##GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 First::printStuff()
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout##GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)##GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
My question is, where is the variable first? I don't see this object in the dump! Note that second is there as symbol 61. I expected mangling of first, but not for it to disappear altogether...
Anyone?
Your object first is just a local object that exists only at the stack. Such objects are not stored in the data section of the executable. The variable second is different because it is global. It is stored with its initial value (default value in your case as you do not explicitly instantiate it) and is defined as a symbol.
example.cpp:
class Clazz {
int x; // will live wherever the instance of Clazz is created
public:
Clazz(const std::initializer_list<int> & data) {}
Clazz() : x(13) {} // "13" is either in constructor code, or .rodata
};
// these will end in .data section
// except the list parameter {1, 2, 3}, which is const and lands in .rodata
static int localInt; // local symbol, will be in .o file only in debug info
int globalInt; // global symbol
// btw, both are initialized to 0, as they are defined in .data
static Clazz *classPtr = nullptr;
Clazz classInstance( {1, 2, 3} );
// all global symbols from .data/.rodata/.bss/.text (.code) sections
// will be visible in symbol table of executable (including the "foo" below)
// everything else defined below (except foo) is runtime allocated,
// and can't have any fixed address in symbol table, so it will not show there.
void foo(int param) { // param is either on stack or in register (ABI specific)
Clazz localVar; // localVar instance is living on the stack space
classPtr = new Clazz({});
// Instance of Clazz pointed at by classPtr lives in global heap memory
// If not released by explicit "delete classPtr;" during runtime,
// it will cause memory leak (avoid using naked pointers like this).
int localInt; // localInt lives on stack too, uninitialized = undefined value!
// On the contrary to *classPtr the localVar is released upon exiting it's scope
}
Neither stack or heap instances are in ELF file, in ELF file is only code capable to manipulate the instance, and to create the instance (either on stack or on heap, either by instancing it as global/local variable, or by new).
So unless you instantiate some type into .data/.bss sections (ie. defining it outside of function, as a global/local of that .cpp file), you can't figure out the where the variable will be kept by looking at symbol table of executable.
I think that in order to understand the output of readelf, we firstly need to understand a little bit of how a compiler works.
basically a compiler takes a C/C++ file as an output and generates an executable file each C/C++ is usually built of functions and variables.
In order to understand this a little bit further we also need to talk about things called "scopes" a scope is basically the place of recognition within the code -
Where within our code the object / functions that we have defined are recognized and accessible.
for example let's take this code
#include <stdio.h>
int myGlob = 5;
int foo()
{
int a = 5;
printf("Hey this is foo -> %d\n",a + 1);
return a + 1;
}
int goo()
{
int b = 5;
printf("Hey this is goo -> %d\n",b - 1);
return b - 1;
}
int main()
{
printf("glob(%d) foo(%d) goo(%d)",myGlob,foo() - 1, goo() +1 );
return 0;
}
we have three functions and one global var
foo -> which has the local variable a within it
goo -> which has the local variable b within it
main -> which has no local variable within it
also we have myGlob which is a global variable
variable a is only accessible within it foo, variable b which is only accessible within the goo function and myGlob which is accessible within all functions but only, so the scope of a is foo the scope of bis goo and the scope of myGlob is the entire model, pretty basic right? this is where we'll get a little bit deeper within the explanation.
each of these functions / GLOBAL objects are called symbols, when writing actual code you have many models and many header files calling and including each other. the compiler compiles one file at a time and outputs an according object file for each compiled model, in order to allow models to recognize other models, upon every model we include something called a symbol table which is basically the collection of all functions and global variables within your code that should be accessible by other models.
e.g:
we have model.h that defines the function foo
we have model.c that implements foo
we have othermodel.c that includes model.h defines and implements
the function foo that calls goo
now if we actually create something like this and run the readelf upon it we would see that model.h + model .c would combine to model.o and othermodel.c would generate othermodel.o, model.o would have within it the symbol foo and the implementation of foo (actual code and instructions) and othermodel.o would have the symbol goo and foo yet only the implementation
of foo
this is where the linker kicks in, when the linker needs to combine all object files into an executable, it reads which object file needs which symbols within it and combines all the files into one executable eventually, again I remind you that symbols may also be functions and global variables.
now that we have a little bit more understanding of what symbols are and why every symbol is used when multiple model scopes are combined we can understand why a local variable shouldn't have it's own symbol
let's go back to our previous example, within the function foo of model.o
there is some local variable b as we've spoken earlier b is only accessible by foo, why on earth would the object file of model.o need to generate a symbol for b? no one other but code within foo can access that variable, so why do the need to recognize or even know about it's existence?
now honestly that's sort of abuse of what actually happens, in real life, local variables are saved on a stack, within your instruction code, when entering some function your memory stack is manually manipulated in order to create some memory buffer to hold all your local variables and data that is regarding the function executing... that so called buffer is called a stack frame, and the beauty of that is once your function is exited, the stack is cleaned, and over functions re-use that memory and run the stack memory with their local variables and function meta data (return addresses for example) unlike local variables, global variables such as myGlob in my example or second in yours are saved in a global memory section that is accessible by all appropriate functions (in reality not always true but for now let's keep it simple), and that memory's life time is throughout the entire program, it doesn't get rewritten constantly like the stack memory and everyone can access it, therefore local variables do not have a need for a symbol or the life-time of an entire program.
if you did not know, classes / structs in C++/C are just a bunch of variables of different type sitting in sequence within memory, if your class instance is local, it's just a bunch of local variables sitting one after the other in the stack memory that the compiler allows you to access with some comfortable name that would be eventually translated to an offset, therefore as we've shown earlier in my long long explanation that you simply shouldn't \ won't have a symbol for a local variable.. if you would like to see a symbol for hello you could've done something such as
static int hello;
which perhaps doesn't give you a global scope accessibility yet gives your variable a lifetime of throughout the program..
anyways hope I've cleared you up somethings, sorry for my poor English skills :)
EDIT:
By the way, this is absolutely has nothing to do with your CPU architecture, even if you compile code for C++ PowerPC, MIPS or ARM, it would stay the same, the only thing that would differentiate is the actual instructions and perhaps the addresses of functions, yet this is more of a concept than it is relevant to CPU architecture
in this code you print just the count of arguments , argc is the number of arguments includes the command , and argv is the the string array which is the words after command seperated by space
a ELF file contains debug info, then the types of variables, structures, and great many other kinds of info can be extracted from that binary.Theoretically possible, but I don't know how to program the implementation under Windows
I have a file that contains the following:
#include <map>
class A {};
void doSomething() {
std::map<int, A> m;
}
When compiled into a shared library with g++, the library contains dynamic symbols for all the methods of std::map<int, A>. Since A is private to this file, there is no possibility that std::map will be instantiated in any other shared library with the same parameters, so I'd like to make the template instantiation hidden (for some of the reasons described in this document).
I thought I should be able to do this by adding an explicit instantiation of the template class and marking it as hidden, like so:
#include <map>
class A {};
template class __attribute__((visibility ("hidden"))) std::map<int, A>;
void doSomething() {
std::map<int, A> m;
}
However, this has no effect: the symbols are still all exported. I also tried surrounding the entire file with:
#pragma GCC visibility push(hidden)
...
#pragma GCC visibility pop
but this also has no effect on the visibility of the methods of std::map<int, A> (although it does hide doSomething). Similarly, compiling with -fvisibility=hidden has no effect on the visibility of the methods of std::map<int, A>.
The document I linked to above describes the use of export maps to restrict visibility, but that seems very tedious.
Is there a way to do what I want in g++ (other than using export maps)? If so, what is it? If not, is there a good reason why these symbols must always be exported, or is this just a omission in g++?
From GCC bug report #36022, which was marked INVALID, Benjamin Kosnik remarked:
[A]n exception class that will be thrown between DSOs must be
explicitly marked with default visibility so that the `type_info' nodes will be
unified between the DSOs.
Thus, the rationale for libstdc++ having namespace std have visibility
"default."
Also, looking through the libstdc++ source for std::map (mine is in /usr/include/c++/4.4.4/bits/stl_map.h), it appears that the way libstdc++ enforces default visibility is with the _GLIBCXX_BEGIN_NESTED_NAMESPACE macro that is used at the top of stl_map.h:
# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V)))
# define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) _GLIBCXX_BEGIN_NAMESPACE(X)
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY_ATTR(default) {
Therefore your STL implementation is explicitly overriding -fvisibility=hidden and #pragma GCC visibility push(hidden)/#pragma GCC visibility pop.
If you really wanted to force the std::map members to have hidden visibility then I think you could use something like:
// ensure that default visibility is used with any class that is used as an exception type
#include <memory>
#include <new>
#include <stdexcept>
// now include the definition of `std::map` using hidden visibility
#include <bits/c++config.h>
#undef _GLIBCXX_VISIBILITY_ATTR
#define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden")))
#include <map>
#undef _GLIBCXX_VISIBILITY_ATTR
#define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR`
Then, the following series of commands will verify that the std::map<int, A> members can be stripped from a shared object:
g++ -c -fPIC -fvisibility=hidden test.cpp
g++ -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.0 test.o
strip -x libtest.so.1.0
readelf -s libtest.so.1.0
Note that before step 3, readelf -s libtest.so.1.0 printed (for me):
Symbol table '.dynsym' contains 23 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
2: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
3: 00000000 0 FUNC GLOBAL DEFAULT UND _ZdlPv#GLIBCXX_3.4 (2)
4: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0#CXXABI_1.3 (3)
5: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume#GCC_3.0 (4)
6: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.1.3 (5)
7: 00000d02 5 FUNC WEAK DEFAULT 12 _ZNSt4pairIKi1AED1Ev
8: 00000d6c 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEEC1ISt
9: 00000d96 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
10: 000023bc 0 NOTYPE GLOBAL DEFAULT ABS _end
11: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS _edata
12: 00000d5e 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
13: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
14: 00000bac 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
15: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
16: 000007f4 0 FUNC GLOBAL DEFAULT 10 _init
17: 00000c4a 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
18: 00000df8 0 FUNC GLOBAL DEFAULT 13 _fini
19: 00000dba 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
20: 00000cde 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEED1Ev
21: 00000d90 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
22: 00000ac6 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
Symbol table '.symtab' contains 84 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000f4 0 SECTION LOCAL DEFAULT 1
2: 00000118 0 SECTION LOCAL DEFAULT 2
3: 000001c0 0 SECTION LOCAL DEFAULT 3
4: 0000022c 0 SECTION LOCAL DEFAULT 4
5: 0000039c 0 SECTION LOCAL DEFAULT 5
6: 000006b6 0 SECTION LOCAL DEFAULT 6
7: 000006e4 0 SECTION LOCAL DEFAULT 7
8: 00000754 0 SECTION LOCAL DEFAULT 8
9: 0000077c 0 SECTION LOCAL DEFAULT 9
10: 000007f4 0 SECTION LOCAL DEFAULT 10
11: 00000824 0 SECTION LOCAL DEFAULT 11
12: 00000930 0 SECTION LOCAL DEFAULT 12
13: 00000df8 0 SECTION LOCAL DEFAULT 13
14: 00000e14 0 SECTION LOCAL DEFAULT 14
15: 00000ef8 0 SECTION LOCAL DEFAULT 15
16: 00001240 0 SECTION LOCAL DEFAULT 16
17: 0000225c 0 SECTION LOCAL DEFAULT 17
18: 00002264 0 SECTION LOCAL DEFAULT 18
19: 0000226c 0 SECTION LOCAL DEFAULT 19
20: 00002270 0 SECTION LOCAL DEFAULT 20
21: 00002358 0 SECTION LOCAL DEFAULT 21
22: 00002364 0 SECTION LOCAL DEFAULT 22
23: 000023ac 0 SECTION LOCAL DEFAULT 23
24: 000023b4 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
27: 0000225c 0 OBJECT LOCAL DEFAULT 17 __CTOR_LIST__
28: 00002264 0 OBJECT LOCAL DEFAULT 18 __DTOR_LIST__
29: 0000226c 0 OBJECT LOCAL DEFAULT 19 __JCR_LIST__
30: 00000930 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
31: 000023b4 1 OBJECT LOCAL DEFAULT 24 completed.5942
32: 000023b8 4 OBJECT LOCAL DEFAULT 24 dtor_idx.5944
33: 000009b0 0 FUNC LOCAL DEFAULT 12 frame_dummy
34: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
35: 00002260 0 OBJECT LOCAL DEFAULT 17 __CTOR_END__
36: 0000123c 0 OBJECT LOCAL DEFAULT 15 __FRAME_END__
37: 0000226c 0 OBJECT LOCAL DEFAULT 19 __JCR_END__
38: 00000dc0 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux
39: 00000000 0 FILE LOCAL DEFAULT ABS test.cpp
40: 00000d64 8 FUNC LOCAL HIDDEN 12 _ZNKSt8_Rb_treeIiSt4pairI
41: 000023b0 4 OBJECT LOCAL HIDDEN 23 DW.ref.__gxx_personality_
42: 00000b40 11 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
43: 00000bc8 129 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
44: 00000bb1 11 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
45: 00000b4c 96 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
46: 00000ca0 62 FUNC LOCAL HIDDEN 12 _ZNKSt8_Rb_treeIiSt4pairI
47: 00000ab2 19 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
48: 00002364 0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_
49: 00000a56 92 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
50: 000009ec 30 FUNC LOCAL HIDDEN 12 _Z11doSomethingv
51: 00000c6e 49 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
52: 00000a32 35 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
53: 000023ac 0 OBJECT LOCAL HIDDEN 23 __dso_handle
54: 00000a0a 19 FUNC LOCAL HIDDEN 12 _ZNSt3mapIi1ASt4lessIiESa
55: 00002268 0 OBJECT LOCAL HIDDEN 18 __DTOR_END__
56: 00000bbc 11 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
57: 00000a1e 19 FUNC LOCAL HIDDEN 12 _ZNSt3mapIi1ASt4lessIiESa
58: 00000d2c 50 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
59: 00000aea 85 FUNC LOCAL HIDDEN 12 _ZNSt8_Rb_treeIiSt4pairIK
60: 000009e7 0 FUNC LOCAL HIDDEN 12 __i686.get_pc_thunk.bx
61: 00002270 0 OBJECT LOCAL HIDDEN ABS _DYNAMIC
62: 00000d02 5 FUNC WEAK DEFAULT 12 _ZNSt4pairIKi1AED1Ev
63: 00000c4a 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
64: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
65: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
66: 00000000 0 FUNC GLOBAL DEFAULT UND _ZdlPv##GLIBCXX_3.4
67: 00000df8 0 FUNC GLOBAL DEFAULT 13 _fini
68: 00000d6c 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEEC1ISt
69: 00000dba 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
70: 00000cde 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEED1Ev
71: 00000d5e 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
72: 00000d90 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
73: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
74: 00000d96 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
75: 00000bac 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
76: 000023bc 0 NOTYPE GLOBAL DEFAULT ABS _end
77: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS _edata
78: 00000ac6 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
79: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0##CXX
80: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume##GCC_3.0
81: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.1
82: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
83: 000007f4 0 FUNC GLOBAL DEFAULT 10 _init
And afterward:
Symbol table '.dynsym' contains 23 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
2: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
3: 00000000 0 FUNC GLOBAL DEFAULT UND _ZdlPv#GLIBCXX_3.4 (2)
4: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0#CXXABI_1.3 (3)
5: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume#GCC_3.0 (4)
6: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.1.3 (5)
7: 00000d02 5 FUNC WEAK DEFAULT 12 _ZNSt4pairIKi1AED1Ev
8: 00000d6c 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEEC1ISt
9: 00000d96 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
10: 000023bc 0 NOTYPE GLOBAL DEFAULT ABS _end
11: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS _edata
12: 00000d5e 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
13: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
14: 00000bac 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
15: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
16: 000007f4 0 FUNC GLOBAL DEFAULT 10 _init
17: 00000c4a 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
18: 00000df8 0 FUNC GLOBAL DEFAULT 13 _fini
19: 00000dba 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
20: 00000cde 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEED1Ev
21: 00000d90 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
22: 00000ac6 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
Symbol table '.symtab' contains 51 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000f4 0 SECTION LOCAL DEFAULT 1
2: 00000118 0 SECTION LOCAL DEFAULT 2
3: 000001c0 0 SECTION LOCAL DEFAULT 3
4: 0000022c 0 SECTION LOCAL DEFAULT 4
5: 0000039c 0 SECTION LOCAL DEFAULT 5
6: 000006b6 0 SECTION LOCAL DEFAULT 6
7: 000006e4 0 SECTION LOCAL DEFAULT 7
8: 00000754 0 SECTION LOCAL DEFAULT 8
9: 0000077c 0 SECTION LOCAL DEFAULT 9
10: 000007f4 0 SECTION LOCAL DEFAULT 10
11: 00000824 0 SECTION LOCAL DEFAULT 11
12: 00000930 0 SECTION LOCAL DEFAULT 12
13: 00000df8 0 SECTION LOCAL DEFAULT 13
14: 00000e14 0 SECTION LOCAL DEFAULT 14
15: 00000ef8 0 SECTION LOCAL DEFAULT 15
16: 00001240 0 SECTION LOCAL DEFAULT 16
17: 0000225c 0 SECTION LOCAL DEFAULT 17
18: 00002264 0 SECTION LOCAL DEFAULT 18
19: 0000226c 0 SECTION LOCAL DEFAULT 19
20: 00002270 0 SECTION LOCAL DEFAULT 20
21: 00002358 0 SECTION LOCAL DEFAULT 21
22: 00002364 0 SECTION LOCAL DEFAULT 22
23: 000023ac 0 SECTION LOCAL DEFAULT 23
24: 000023b4 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
27: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
28: 00000000 0 FILE LOCAL DEFAULT ABS test.cpp
29: 00000d02 5 FUNC WEAK DEFAULT 12 _ZNSt4pairIKi1AED1Ev
30: 00000c4a 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
31: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
32: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
33: 00000000 0 FUNC GLOBAL DEFAULT UND _ZdlPv##GLIBCXX_3.4
34: 00000df8 0 FUNC GLOBAL DEFAULT 13 _fini
35: 00000d6c 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEEC1ISt
36: 00000dba 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
37: 00000cde 35 FUNC WEAK DEFAULT 12 _ZNSaISt4pairIKi1AEED1Ev
38: 00000d5e 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
39: 00000d90 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
40: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
41: 00000d96 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
42: 00000bac 5 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
43: 000023bc 0 NOTYPE GLOBAL DEFAULT ABS _end
44: 000023b4 0 NOTYPE GLOBAL DEFAULT ABS _edata
45: 00000ac6 35 FUNC WEAK DEFAULT 12 _ZNSaISt13_Rb_tree_nodeIS
46: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0##CXX
47: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume##GCC_3.0
48: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.1
49: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca
50: 000007f4 0 FUNC GLOBAL DEFAULT 10 _init
See also:
Visibility - GCC Wiki
Controlling Symbol Visibility
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36022:
The std::namespace is supposed to be exposed and is marked as such in the libstdc++ headers.
As for
#undef _GLIBCXX_VISIBILITY_ATTR
here is another quote:
If you were to hack in support for allowing namespace std to have
hidden visibility, and run the testsuite with -fvisibility=hidden (see attached
patch) you would notice the breakdown in testresults, with mass failures.
Disclaimer: I am not a GCC developer, and therefore this is a complete WAG (wild-ass guess):
My guess would be that GCC always exports template definitions, in order to allow the linker to remove duplicate copies of templates. If it were not exported and more than once source file used that template, the entire source for the std::map<k, v> class would be duplicated within the two files.
I think you're really paying more attention to this than it deserves. Exports are an implementation detail in C++. In C, it makes sense to not export internal functions, so that clients don't come to rely on them. But in C++, the exported functions never have to have anything to do with the source code. One version of GCC's std::map<k, v> might be completely different from another versions' and as a result the two binaries will not be link-compatible.
If you absolutely need portability, export a C interface and ignore the C++ specifics that get exported. Any client of your library trying to call such exports or do anything with them deserves to crash and burn for calling obvious internal implementation details.
EDIT: Made CW because I'm not 100% positive.
Maybe you could use objcopy with the --strip-symbol option?
The option is described in the objcopy man page
This might get tedious though...
In C++, if a template argument has limited visibility, this restriction is implicitly propagated to the template instantiation.
#include <map>
class __attribute__((visibility ("hidden"))) A {};
void doSomething() {
std::map<int, A> m;
}
should do the job.
-- edit --
One more thing, `#pragma GCC visibility' affects only namespace-scope declarations. Class members and template specializations are not affected (Visibility pragmas)