readelf output of the object file:
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS fp16.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 $t
6: 00000001 194 FUNC LOCAL DEFAULT 1 __gnu_f2h_internal
7: 00000010 0 NOTYPE LOCAL DEFAULT 5 $d
8: 00000000 0 SECTION LOCAL DEFAULT 5
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 000000c5 78 FUNC GLOBAL HIDDEN 1 __gnu_h2f_internal
11: 00000115 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_ieee
12: 00000119 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_ieee
13: 0000011d 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_alternative
14: 00000121 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_alternative
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000124 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00058c 000010 08 9 1 4
[ 3] .data PROGBITS 00000000 000158 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000158 000000 00 WA 0 0 1
[ 5] .debug_frame PROGBITS 00000000 000158 00008c 00 0 0 4
[ 6] .rel.debug_frame REL 00000000 00059c 000060 08 9 5 4
[ 7] .ARM.attributes ARM_ATTRIBUTES 00000000 0001e4 00002f 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 000213 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 00041c 0000f0 10 10 10 4
[10] .strtab STRTAB 00000000 00050c 00007e 00 0 0 1
Relocation section '.rel.text' at offset 0x58c contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000011a 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
00000122 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
Relocation section '.rel.debug_frame' at offset 0x59c contains 12 entries:
Offset Info Type Sym.Value Sym. Name
00000014 00000802 R_ARM_ABS32 00000000 .debug_frame
00000018 00000202 R_ARM_ABS32 00000000 .text
00000040 00000802 R_ARM_ABS32 00000000 .debug_frame
00000044 00000202 R_ARM_ABS32 00000000 .text
00000050 00000802 R_ARM_ABS32 00000000 .debug_frame
00000054 00000202 R_ARM_ABS32 00000000 .text
00000060 00000802 R_ARM_ABS32 00000000 .debug_frame
00000064 00000202 R_ARM_ABS32 00000000 .text
00000070 00000802 R_ARM_ABS32 00000000 .debug_frame
00000074 00000202 R_ARM_ABS32 00000000 .text
00000080 00000802 R_ARM_ABS32 00000000 .debug_frame
00000084 00000202 R_ARM_ABS32 00000000 .text
.text section structure as I understand it:
.text section has size of 0x124
0x0: unknown byte
0x1-0xC3: __gnu_f2h_internal
0xC3-0xC5: two unknown bytes between those functions (btw what are those?)
0xC5-0x113: __gnu_h2f_internal
0x113-0x115: two unknown bytes between those functions
0x115-0x119: __gnu_f2h_ieee
0x119-0x11D: __gnu_h2f_ieee
0x11D-0x121: __gnu_f2h_alternative
0x121-0x125: __gnu_h2f_alternative // section is only 0x124, what happened to the missing byte?
Notice that the section size is 0x124 and the last function end in 0x125, what happend to the missing byte?
Thanks.
Technically, your "missing byte" is the one right there at 0x0.
Note that you're looking at the value of the symbol, i.e. the runtime function address (this would be a lot clearer if your .text section VMA wasn't 0). Since they're Thumb functions, the addresses have bit 0 set such that the processor will switch to Thumb mode when calling them; the actual locations of those instructions are still halfword-aligned, i.e. 0x0, 0xc4, 0x114, etc. since they couldn't be executed otherwise (you'd take a fault for a misaligned PC). Strip off bit 0 as per what the ARM
ELF spec says about STT_FUNC symbols to get the actual VMA of the instruction corresponding to that symbol, then subtract the start of the section and you should have the same relative offset as within the object file itself.
<offset in section> = (<symbol value> & ~1) - <section VMA>
The extra halfword padding after some functions just ensures each symbol is word-aligned - there are probably various reasons for this, but the first one that comes to mind is that the adr instruction wouldn't work properly if they weren't.
Related
I have a .o object file which has a function that other functions in that same file are calling. That function is in it's own section and not exported. I need to replace this function with my own implementation. My own implementation needs external symbols aswell. I thought about simply patching that section so it calls an address that's placed at some location (so the old function is effectively just transfering control to my code), then I only need to add some kind of reference/relocation information so the linker knows that it needs to place the address of the function at that location (it looks like that's how it's done for all the other "imports"). But how do I do this using tools like objcopy, ld, gcc, and nm? Unfortunately I can't really use any additional tools (except for those present on a normal linux machine like sed, awk, dd and so on). I can see that the other imported symbols are listed in the symtab without an address and so on, but I can't see how they are referred to.
The output of readelf -Ws is
Symbol table '.symtab' contains 190 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 57
2: 00000000 0 SECTION LOCAL DEFAULT 58
3: 00000000 0 SECTION LOCAL DEFAULT 59
4: 00000000 0 SECTION LOCAL DEFAULT 61
5: 00000000 0 SECTION LOCAL DEFAULT 62
6: 00000000 0 SECTION LOCAL DEFAULT 64
7: 00000000 0 SECTION LOCAL DEFAULT 66
8: 00000000 0 SECTION LOCAL DEFAULT 68
9: 00000000 0 SECTION LOCAL DEFAULT 70
10: 00000000 0 SECTION LOCAL DEFAULT 72
11: 00000000 0 SECTION LOCAL DEFAULT 74
12: 00000000 0 SECTION LOCAL DEFAULT 76
13: 00000000 0 SECTION LOCAL DEFAULT 78
14: 00000000 0 SECTION LOCAL DEFAULT 80
15: 00000000 0 SECTION LOCAL DEFAULT 82
16: 00000000 0 SECTION LOCAL DEFAULT 84
17: 00000000 0 SECTION LOCAL DEFAULT 86
18: 00000000 0 SECTION LOCAL DEFAULT 88
19: 00000000 0 SECTION LOCAL DEFAULT 90
20: 00000000 0 SECTION LOCAL DEFAULT 92
21: 00000000 0 SECTION LOCAL DEFAULT 94
22: 00000000 0 SECTION LOCAL DEFAULT 96
23: 00000000 0 SECTION LOCAL DEFAULT 98
24: 00000000 0 SECTION LOCAL DEFAULT 100
25: 00000000 0 SECTION LOCAL DEFAULT 102
26: 00000000 0 SECTION LOCAL DEFAULT 104
27: 00000000 0 SECTION LOCAL DEFAULT 105
28: 00000000 0 SECTION LOCAL DEFAULT 107
29: 00000000 0 SECTION LOCAL DEFAULT 109
30: 00000000 0 SECTION LOCAL DEFAULT 111
31: 00000000 0 SECTION LOCAL DEFAULT 113
32: 00000000 0 SECTION LOCAL DEFAULT 115
33: 00000000 0 SECTION LOCAL DEFAULT 117
34: 00000000 0 SECTION LOCAL DEFAULT 119
35: 00000000 0 SECTION LOCAL DEFAULT 121
36: 00000000 0 SECTION LOCAL DEFAULT 123
37: 00000000 0 SECTION LOCAL DEFAULT 125
38: 00000000 0 SECTION LOCAL DEFAULT 126
39: 00000000 0 SECTION LOCAL DEFAULT 128
40: 00000000 0 SECTION LOCAL DEFAULT 130
41: 00000000 0 SECTION LOCAL DEFAULT 132
42: 00000000 0 SECTION LOCAL DEFAULT 134
43: 00000000 0 SECTION LOCAL DEFAULT 136
44: 00000000 0 SECTION LOCAL DEFAULT 138
45: 00000000 0 SECTION LOCAL DEFAULT 140
46: 00000000 0 SECTION LOCAL DEFAULT 142
47: 00000000 0 SECTION LOCAL DEFAULT 144
48: 00000000 0 SECTION LOCAL DEFAULT 146
49: 00000000 0 SECTION LOCAL DEFAULT 148
50: 00000000 0 SECTION LOCAL DEFAULT 150
51: 00000000 0 SECTION LOCAL DEFAULT 152
52: 00000000 0 SECTION LOCAL DEFAULT 154
53: 00000000 0 SECTION LOCAL DEFAULT 156
54: 00000000 0 SECTION LOCAL DEFAULT 158
55: 00000000 0 SECTION LOCAL DEFAULT 160
56: 00000000 0 SECTION LOCAL DEFAULT 162
57: 00000000 0 SECTION LOCAL DEFAULT 164
58: 00000000 0 SECTION LOCAL DEFAULT 166
59: 00000000 0 SECTION LOCAL DEFAULT 168
60: 00000000 0 SECTION LOCAL DEFAULT 1
61: 00000000 0 SECTION LOCAL DEFAULT 2
62: 00000000 0 SECTION LOCAL DEFAULT 3
63: 00000000 0 SECTION LOCAL DEFAULT 4
64: 00000000 0 SECTION LOCAL DEFAULT 5
65: 00000000 0 SECTION LOCAL DEFAULT 6
66: 00000000 0 SECTION LOCAL DEFAULT 7
67: 00000000 0 SECTION LOCAL DEFAULT 8
68: 00000000 0 SECTION LOCAL DEFAULT 9
69: 00000000 0 SECTION LOCAL DEFAULT 10
70: 00000000 0 SECTION LOCAL DEFAULT 11
71: 00000000 0 SECTION LOCAL DEFAULT 12
72: 00000000 0 SECTION LOCAL DEFAULT 13
73: 00000000 0 SECTION LOCAL DEFAULT 14
74: 00000000 0 SECTION LOCAL DEFAULT 15
75: 00000000 0 SECTION LOCAL DEFAULT 16
76: 00000000 0 SECTION LOCAL DEFAULT 17
77: 00000000 0 SECTION LOCAL DEFAULT 18
78: 00000000 0 SECTION LOCAL DEFAULT 19
79: 00000000 0 SECTION LOCAL DEFAULT 20
80: 00000000 0 SECTION LOCAL DEFAULT 21
81: 00000000 0 SECTION LOCAL DEFAULT 22
82: 00000000 0 SECTION LOCAL DEFAULT 23
83: 00000000 0 SECTION LOCAL DEFAULT 24
84: 00000000 0 SECTION LOCAL DEFAULT 25
85: 00000000 0 SECTION LOCAL DEFAULT 26
86: 00000000 0 SECTION LOCAL DEFAULT 27
87: 00000000 0 SECTION LOCAL DEFAULT 28
88: 00000000 0 SECTION LOCAL DEFAULT 29
89: 00000000 0 SECTION LOCAL DEFAULT 30
90: 00000000 0 SECTION LOCAL DEFAULT 31
91: 00000000 0 SECTION LOCAL DEFAULT 32
92: 00000000 0 SECTION LOCAL DEFAULT 33
93: 00000000 0 SECTION LOCAL DEFAULT 34
94: 00000000 0 SECTION LOCAL DEFAULT 35
95: 00000000 0 SECTION LOCAL DEFAULT 36
96: 00000000 0 SECTION LOCAL DEFAULT 37
97: 00000000 0 SECTION LOCAL DEFAULT 38
98: 00000000 0 SECTION LOCAL DEFAULT 39
99: 00000000 0 SECTION LOCAL DEFAULT 40
100: 00000000 0 SECTION LOCAL DEFAULT 41
101: 00000000 0 SECTION LOCAL DEFAULT 42
102: 00000000 0 SECTION LOCAL DEFAULT 43
103: 00000000 0 SECTION LOCAL DEFAULT 44
104: 00000000 0 SECTION LOCAL DEFAULT 45
105: 00000000 0 SECTION LOCAL DEFAULT 46
106: 00000000 0 SECTION LOCAL DEFAULT 47
107: 00000000 0 SECTION LOCAL DEFAULT 48
108: 00000000 0 SECTION LOCAL DEFAULT 49
109: 00000000 0 SECTION LOCAL DEFAULT 50
110: 00000000 0 SECTION LOCAL DEFAULT 51
111: 00000000 0 SECTION LOCAL DEFAULT 52
112: 00000000 0 SECTION LOCAL DEFAULT 53
113: 00000000 0 SECTION LOCAL DEFAULT 54
114: 00000000 0 SECTION LOCAL DEFAULT 55
115: 00000000 0 SECTION LOCAL DEFAULT 56
116: 00000000 0 SECTION LOCAL DEFAULT 170
117: 00000000 0 SECTION LOCAL DEFAULT 171
118: 00000000 0 SECTION LOCAL DEFAULT 172
119: 00000000 0 SECTION LOCAL DEFAULT 174
120: 00000000 0 NOTYPE GLOBAL DEFAULT UND wpabuf_put
121: 00000004 30 FUNC GLOBAL DEFAULT 64 eap_peer_get_eap_method
122: 00000004 29 FUNC GLOBAL DEFAULT 66 eap_peer_get_methods
123: 00000008 65 FUNC GLOBAL DEFAULT 68 eap_peer_get_type
124: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_strcmp
125: 00000008 52 FUNC GLOBAL DEFAULT 72 eap_get_phase2_type
126: 00000010 136 FUNC GLOBAL DEFAULT 74 eap_get_phase2_types
127: 00000000 0 NOTYPE GLOBAL DEFAULT UND pvPortMalloc
128: 00000008 51 FUNC GLOBAL DEFAULT 76 eap_peer_method_alloc
129: 00000000 0 NOTYPE GLOBAL DEFAULT UND pvPortZalloc
130: 00000008 24 FUNC GLOBAL DEFAULT 78 eap_peer_method_free
131: 00000000 0 NOTYPE GLOBAL DEFAULT UND vPortFree
132: 0000000c 99 FUNC GLOBAL DEFAULT 80 eap_peer_method_register
133: 00000008 48 FUNC GLOBAL DEFAULT 82 eap_peer_unregister_methods
134: 00000010 42 FUNC GLOBAL DEFAULT 84 eap_peer_register_methods
135: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_peer_tls_register
136: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_peer_mschapv2_register
137: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_peer_peap_register
138: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_peer_ttls_register
139: 00000000 0 NOTYPE GLOBAL DEFAULT UND g_ic
140: 00000000 0 NOTYPE GLOBAL DEFAULT UND ieee80211_output_pbuf
141: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_memset
142: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_memcpy
143: 00000008 59 FUNC GLOBAL DEFAULT 92 wpa2_sm_alloc_eapol
144: 00000000 0 NOTYPE GLOBAL DEFAULT UND pbuf_alloc
145: 00000020 145 FUNC GLOBAL DEFAULT 96 eap_sm_build_identity_resp
146: 00000000 5 FUNC GLOBAL DEFAULT 125 eap_get_config
147: 00000000 0 NOTYPE GLOBAL DEFAULT UND os_printf_plus
148: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_msg_alloc
149: 00000000 0 NOTYPE GLOBAL DEFAULT UND eap_update_len
150: 00000010 79 FUNC GLOBAL DEFAULT 100 eap_sm_send_eapol
151: 00000034 454 FUNC GLOBAL DEFAULT 102 eap_sm_process_request
152: 00000000 0 NOTYPE GLOBAL DEFAULT UND wpabuf_free
153: 0000001c 188 FUNC GLOBAL DEFAULT 105 wpa2_sm_rx_eapol
154: 00000000 0 NOTYPE GLOBAL DEFAULT UND wpabuf_alloc_copy
155: 00000000 0 NOTYPE GLOBAL DEFAULT UND wpa_set_pmk
156: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_bzero
157: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_strncpy
158: 00000000 0 NOTYPE GLOBAL DEFAULT UND wifi_get_macaddr
159: 00000000 0 NOTYPE GLOBAL DEFAULT UND tls_init
160: 00000000 0 NOTYPE GLOBAL DEFAULT UND tls_deinit
161: 00000004 37 FUNC GLOBAL DEFAULT 126 eap_get_config_identity
162: 00000004 37 FUNC GLOBAL DEFAULT 128 eap_get_config_password
163: 00000004 51 FUNC GLOBAL DEFAULT 130 eap_get_config_password2
164: 00000004 39 FUNC GLOBAL DEFAULT 132 eap_get_config_new_password
165: 00000004 63 FUNC GLOBAL DEFAULT 134 eap_get_config_blob
166: 00000000 0 NOTYPE GLOBAL DEFAULT UND ets_strncmp
167: 00000048 164 FUNC GLOBAL DEFAULT 136 wifi_station_set_wpa2_enterprise_auth
168: 00000004 36 FUNC GLOBAL DEFAULT 138 wifi_station_set_enterprise_cert_key
169: 00000004 21 FUNC GLOBAL DEFAULT 140 wifi_station_clear_enterprise_cert_key
170: 00000004 16 FUNC GLOBAL DEFAULT 142 wifi_station_set_enterprise_ca_cert
171: 00000004 11 FUNC GLOBAL DEFAULT 144 wifi_station_clear_enterprise_ca_cert
172: 00000024 109 FUNC GLOBAL DEFAULT 146 wifi_station_set_enterprise_identity
173: 00000010 40 FUNC GLOBAL DEFAULT 148 wifi_station_clear_enterprise_identity
174: 00000024 109 FUNC GLOBAL DEFAULT 150 wifi_station_set_enterprise_username
175: 00000010 40 FUNC GLOBAL DEFAULT 152 wifi_station_clear_enterprise_username
176: 00000024 103 FUNC GLOBAL DEFAULT 154 wifi_station_set_enterprise_password
177: 00000010 40 FUNC GLOBAL DEFAULT 156 wifi_station_clear_enterprise_password
178: 00000024 103 FUNC GLOBAL DEFAULT 158 wifi_station_set_enterprise_new_password
179: 00000010 40 FUNC GLOBAL DEFAULT 160 wifi_station_clear_enterprise_new_password
180: 00000004 8 FUNC GLOBAL DEFAULT 162 wifi_station_set_enterprise_disable_time_check
181: 00000004 8 FUNC GLOBAL DEFAULT 164 wifi_station_get_enterprise_disable_time_check
182: 00000004 8 FUNC GLOBAL DEFAULT 166 wpa2_enterprise_set_user_get_time
183: 00000004 28 FUNC GLOBAL DEFAULT 168 wpa2_get_time
184: 00000004 36 FUNC GLOBAL DEFAULT 138 wifi_station_set_cert_key
185: 00000004 21 FUNC GLOBAL DEFAULT 140 wifi_station_clear_cert_key
186: 00000024 109 FUNC GLOBAL DEFAULT 146 wifi_station_set_identity
187: 00000010 40 FUNC GLOBAL DEFAULT 148 wifi_station_clear_identity
188: 00000024 109 FUNC GLOBAL DEFAULT 150 wifi_station_set_username
189: 00000010 40 FUNC GLOBAL DEFAULT 152 wifi_station_clear_username
and readelf -t says this about the section/function I need to modify:
There are 179 section headers, starting at offset 0x96b0:
Section Headers:
[Nr] Name
Type Addr Off Size ES Lk Inf Al
Flags
...
[113] .text.eap_peer_config_deinit
PROGBITS 00000000 000dd0 000868 00 0 0 4
[00000006]: ALLOC, EXEC
[114] .rela.text.eap_peer_config_deinit
RELA 00000000 005d68 000000 0c 176 113 4
[00000040]: INFO LINK
I had to cut the output as I reached the character limit.
I have a .o object file which has a function that other functions in that same file are calling. That function is in it's own section and not exported.
The function I want to modify is basically calling free on the first member of a struct and then zeroing out that struct. I need to call free on the other members of the struct as well before it's all zeroed out.
The simplest solution is to remove the function from the .o file with objcopy --remove-section ... --remove-relocations ..., and add your own implementation in a separate .o.
That's much simpler than editing existing .o to "splice in" different implementation, and appears to satisfy your requirements.
Because of vastly better C++ compile times I've recently added the option to compile a project for an ARM Cortex-M4 microcontroller with Clang instead of the arm-none-eabi-gcc toolchain. The whole process ran quite smoothly and I quickly had working ELF and HEX files. It wasn't until yesterday evening that I noticed that the ELF files actually differ quite a lot...
Before I continue let's inspect the ELF produced by GCC to get some kind of baseline.
GCC's ELF contains the following sections (apart from debug stuff)
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .vector_table PROGBITS 08000000 010000 000010 00 A 0 0 4
[ 2] .version NOBITS 08000010 010010 000010 00 WA 0 0 1
[ 3] .text PROGBITS 08000020 010020 000138 00 AX 0 0 4
[ 4] .rodata PROGBITS 08000158 010158 000000 00 WA 0 0 1
[ 5] .data PROGBITS 20000000 010158 000000 00 WA 0 0 1
[ 6] .data2 PROGBITS 10000000 010158 000000 00 W 0 0 1
[ 7] .bss NOBITS 20000000 020000 00038c 00 WA 0 0 512
[ 8] .bss2 PROGBITS 2000038c 010158 000000 00 W 0 0 1
[ 9] ._user_heap_stack NOBITS 2000038c 020000 000e04 00 WA 0 0 1
But despite .data and .bss being marked with an "A" (alloc) flag only loads the following
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x08000000 0x08000000 0x00158 0x00158 RWE 0x10000
LOAD 0x000000 0x20000000 0x20000000 0x00000 0x01190 RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .vector_table .version .text
01 .bss ._user_heap_stack
So far so good.
The problem emerged when I tried to create binaries from an ELF produced by Clang. Those files where huge in size (256MB) which is nowhere near what I had expected. Now, if you're not familiar with ARM microcontrollers, they usually contain FLASH and RAM memory at very different address locations (e.g. 0x0800'0000 for FLASH and 0x2000'0000 for RAM as seen above). So I already had some suspicion on what's going on... I checked my linker script and put a NOLOAD directive on every section which goes solely to RAM. Problem solved?
Well... not really. In fact my binaries grew even bigger.
Let's take a look at Clang's ELF. It's bugging me a little that Clang doesn't seem to remove the section for unwinding (ARM.exidx) although I compile with -fno-unwind-tables and -gc-sections but ok, I can live with those 16B.
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .vector_table PROGBITS 08000000 001000 000010 00 A 0 0 4
[ 2] .version PROGBITS 08000010 001010 000010 00 A 0 0 1
[ 3] .text PROGBITS 08000020 001020 000334 00 AX 0 0 4
[ 4] .rodata PROGBITS 08000354 001354 000000 00 AX 0 0 1
[ 5] .ARM.exidx ARM_EXIDX 08000354 001354 000010 00 AL 3 0 4
[ 6] .preinit_array PROGBITS 08000364 001364 000000 00 A 0 0 1
[ 7] .init_array INIT_ARRAY 08000364 001364 000004 04 WA 0 0 4
[ 8] .fini_array FINI_ARRAY 08000368 001368 000004 04 WA 0 0 4
[ 9] .data PROGBITS 20000000 002000 000000 00 WA 0 0 1
[10] .data2 PROGBITS 10000000 002000 000000 00 WA 0 0 1
[11] .bss NOBITS 20000000 002000 0001ac 00 WA 0 0 512
[12] .bss2 PROGBITS 200001ac 002000 000000 00 WA 0 0 1
[13] ._user_heap_stack PROGBITS 200001ac 002000 000e04 00 WA 0 0 1
Now this is where it gets interesting and where I have no clue whats happening. What is GNU_RELRO and GNU_STACK and how does it end up there? Why is GNU_STACK at address 0. Any chance this entry is bloating my binaries?
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x08000000 0x08000000 0x00364 0x00364 R E 0x1000
LOAD 0x001364 0x08000364 0x08000364 0x00008 0x00008 RW 0x1000
GNU_RELRO 0x001364 0x08000364 0x08000364 0x00008 0x00c9c R 0x1
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
EXIDX 0x001354 0x08000354 0x08000354 0x00010 0x00010 R 0x4
Section to Segment mapping:
Segment Sections...
00 .vector_table .version .text .rodata .ARM.exidx
01 .preinit_array .init_array .fini_array
02 .preinit_array .init_array .fini_array
03
04 .rodata .ARM.exidx
Further questions:
How is GCC able to remove all the RAM sections despite them
previously not having a NOLOAD directive in the linker script?
Running size on Clang's ELF counts the minimum stack size I define in the linker script to the .data section whereas on GCC's ELF it doesn't. How is that? My linker script contains a section which looks like this
._user_heap_stack (NOLOAD) :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
but to my knowledge this should only "check" that there is at least
enough RAM left to cover my defined minimum heap and stack size. This
section doesn't actually contain anything so how can it be counted to
.data?
I know that I could remove unwanted sections with objcopy when actually creating the binaries, but I'd really like to understand those subtle differences between GCC and Clang.
/edit
I just noticed that my ._user_heap_stack section has different types depending on the compiler (NOBITS vs PROGBITS). Guess that explains why it's counted to .data...
/edit
Now a (potential) bug over # LLVM
https://bugs.llvm.org/show_bug.cgi?id=46299
/edit
And closed as of lld 10.0.1
https://bugs.llvm.org/show_bug.cgi?id=46225
I have a STM32 project which involves a bootloader. The bootloader CRCs the entire application region of flash and then compares this value against a firmware header stored just after the application image region in flash.
I wrote a python script which runs after the binary is built. The script takes the elf file resulting from the build, and loads each section into a "virtual flash" image, which represents what should be exactly what is present on the mcu after the elf would be normally loaded. The array starts out being the size of the application region, with initial values of 0xff for every byte, just as flash would be after a full erase. Then, the script takes each section from the elf and overwrites the section of the virtual flash images where that section should reside.
Finally, the script CRCs the application region and injects the resulting value into the original elf.
This all works fine, but I am seeing additional data in the actual flash contents of the mcu that I cannot determine the origin of. The flash is erased fully before programming the elf so this data is coming from the elf loaded onto the device.
I'm guessing that what is going on here is that there are sections in the elf that my script is ignoring but that are still being written to flash when flashed using conventional means.
The following is the result of a readelf on my application image:
Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .isr_vector PROGBITS 08020000 010000 0001f8 00 WA 0 0 4
[ 2] .firmware_header_ PROGBITS 080201f8 0101f8 000004 00 WA 0 0 4
[ 3] .text PROGBITS 08020200 010200 01e11c 00 AX 0 0 64
[ 4] .ARM.extab PROGBITS 0803e31c 033a68 000000 00 W 0 0 1
[ 5] .exidx ARM_EXIDX 0803e31c 02e31c 000008 00 AL 3 0 4
[ 6] .ARM.attributes ARM_ATTRIBUTES 0803e324 033a68 000030 00 0 0 1
[ 7] .init_array INIT_ARRAY 0803e324 02e324 000008 04 WA 0 0 4
[ 8] .fini_array FINI_ARRAY 0803e32c 02e32c 000004 04 WA 0 0 4
[ 9] .firmware_header PROGBITS 0803e330 02e330 000008 00 WA 0 0 4
[10] .data PROGBITS 20000000 030000 0009c8 00 WA 0 0 8
[11] .RxDecripSection PROGBITS 200009c8 0309c8 000080 00 WA 0 0 4
[12] .RxarraySection PROGBITS 20000a48 030a48 0017d0 00 WA 0 0 4
[13] .TxDescripSection PROGBITS 20002218 032218 000080 00 WA 0 0 4
[14] .TxarraySection PROGBITS 20002298 032298 0017d0 00 WA 0 0 4
[15] .bss NOBITS 20003a68 033a68 045bc0 00 WA 0 0 8
[16] .heap PROGBITS 20049628 033a98 000000 00 W 0 0 1
[17] .reserved_for_sta PROGBITS 20049628 033a98 000000 00 W 0 0 1
[18] .battery_backed_s NOBITS 40024000 034000 00000c 00 WA 0 0 4
[19] .comment PROGBITS 00000000 033a98 000075 01 MS 0 0 1
[20] .debug_frame PROGBITS 00000000 033b10 001404 00 0 0 4
[21] .stab PROGBITS 00000000 034f14 000084 0c 22 0 4
[22] .stabstr STRTAB 00000000 034f98 000117 00 0 0 1
[23] .symtab SYMTAB 00000000 0350b0 009010 10 24 1646 4
[24] .strtab STRTAB 00000000 03e0c0 003dc8 00 0 0 1
[25] .shstrtab STRTAB 00000000 041e88 000132 00 0 0 1
I am loading the following sections into my virtual flash image: .isr_vector, .firmware_header_vector, .text, .exidx, .ARM.attributes, .init_array, .fini_array
I do notice that some sections do have addresses of 0. Are some of these perhaps simply appended to flash?
The additional sections are most probably initial data for DATA segments. The startup code of most systems copies the contents into the RAM space allocated for those segments. This way static variables initialized with non-zero values are set up.
For example static int x = 23; should give you a segment with "23" in it. The address of this "23" in flash is not the address of x in RAM.
readelf output of the object file:
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS fp16.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 $t
6: 00000001 194 FUNC LOCAL DEFAULT 1 __gnu_f2h_internal
7: 00000010 0 NOTYPE LOCAL DEFAULT 5 $d
8: 00000000 0 SECTION LOCAL DEFAULT 5
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 000000c5 78 FUNC GLOBAL HIDDEN 1 __gnu_h2f_internal
11: 00000115 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_ieee
12: 00000119 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_ieee
13: 0000011d 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_alternative
14: 00000121 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_alternative
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000124 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00058c 000010 08 9 1 4
[ 3] .data PROGBITS 00000000 000158 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000158 000000 00 WA 0 0 1
[ 5] .debug_frame PROGBITS 00000000 000158 00008c 00 0 0 4
[ 6] .rel.debug_frame REL 00000000 00059c 000060 08 9 5 4
[ 7] .ARM.attributes ARM_ATTRIBUTES 00000000 0001e4 00002f 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 000213 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 00041c 0000f0 10 10 10 4
[10] .strtab STRTAB 00000000 00050c 00007e 00 0 0 1
Relocation section '.rel.text' at offset 0x58c contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000011a 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
00000122 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
Relocation section '.rel.debug_frame' at offset 0x59c contains 12 entries:
Offset Info Type Sym.Value Sym. Name
00000014 00000802 R_ARM_ABS32 00000000 .debug_frame
00000018 00000202 R_ARM_ABS32 00000000 .text
00000040 00000802 R_ARM_ABS32 00000000 .debug_frame
00000044 00000202 R_ARM_ABS32 00000000 .text
00000050 00000802 R_ARM_ABS32 00000000 .debug_frame
00000054 00000202 R_ARM_ABS32 00000000 .text
00000060 00000802 R_ARM_ABS32 00000000 .debug_frame
00000064 00000202 R_ARM_ABS32 00000000 .text
00000070 00000802 R_ARM_ABS32 00000000 .debug_frame
00000074 00000202 R_ARM_ABS32 00000000 .text
00000080 00000802 R_ARM_ABS32 00000000 .debug_frame
00000084 00000202 R_ARM_ABS32 00000000 .text
.text section structure as I understand it:
.text section has size of 0x124
0x0: unknown byte
0x1-0xC3: __gnu_f2h_internal
0xC3-0xC5: two unknown bytes between those functions (btw what are those?)
0xC5-0x113: __gnu_h2f_internal
0x113-0x115: two unknown bytes between those functions
0x115-0x119: __gnu_f2h_ieee
0x119-0x11D: __gnu_h2f_ieee
0x11D-0x121: __gnu_f2h_alternative
0x121-0x125: __gnu_h2f_alternative // section is only 0x124, what happened to the missing byte?
Notice that the section size is 0x124 and the last function end in 0x125, what happend to the missing byte?
Thanks.
Technically, your "missing byte" is the one right there at 0x0.
Note that you're looking at the value of the symbol, i.e. the runtime function address (this would be a lot clearer if your .text section VMA wasn't 0). Since they're Thumb functions, the addresses have bit 0 set such that the processor will switch to Thumb mode when calling them; the actual locations of those instructions are still halfword-aligned, i.e. 0x0, 0xc4, 0x114, etc. since they couldn't be executed otherwise (you'd take a fault for a misaligned PC). Strip off bit 0 as per what the ARM
ELF spec says about STT_FUNC symbols to get the actual VMA of the instruction corresponding to that symbol, then subtract the start of the section and you should have the same relative offset as within the object file itself.
<offset in section> = (<symbol value> & ~1) - <section VMA>
The extra halfword padding after some functions just ensures each symbol is word-aligned - there are probably various reasons for this, but the first one that comes to mind is that the adr instruction wouldn't work properly if they weren't.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I want to create a c program that creates .o files for the linker on my computer (ld). Gcc does this when I do the command gcc -c myfile.c. Are there any resources that show how to make an object file for a linker?
In order to create a file similar to a file produced by gcc -c, it is important to first understand the format of the file produced.
First, create a file with gcc, and then see if it's format can be reverse-engineered. I will use the following C program (hello.c) to perform this task:
#include <stdio.h>
int main(void)
{
printf("Hello world\n");
return(0);
}
Now, compile the file without linking it:
gcc -Wall -c -o hello.o hello.c
The above code will create hello.o from hello.c. This file is compiled, but not yet linked.
Many files today contain bytes in the header of the file that help identify its format. These identifying bytes are termed 'file magic'. Google 'file magic' and you can find details on how to identify may types of files.
To identify this file type, look for a magic number in the first few lines of a hexdump of the file:
> hexdump -Cn 64 hello.o
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 3e 00 01 00 00 00 50 04 40 00 00 00 00 00 |..>.....P.#.....|
00000020 40 00 00 00 00 00 00 00 18 1a 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 09 00 40 00 2a 00 27 00 |....#.8...#.*.'.|
00000040
The identity of the file's format is revealed, in this case, by the first few bytes of the file; 45 4c 46 = ELF. Hence, the output of gcc -c is a file in the ElF format.
Hence, in order to create similar output from a C program, an understanding of the ELF file format is required.
Many *nix systems include a program called readelf that will translate the contents of an ELF file. For example:
> readelf -a hello.o
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400450
Start of program headers: 64 (bytes into file)
Start of section headers: 6680 (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: 42
Section header string table index: 39
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 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.SuSE NOTE 0000000000400274 00000274
0000000000000018 0000000000000000 A 0 0 4
[ 4] .note.gnu.build-i NOTE 000000000040028c 0000028c
0000000000000024 0000000000000000 A 0 0 4
[ 5] .hash HASH 00000000004002b0 000002b0
0000000000000024 0000000000000004 A 7 0 8
[ 6] .gnu.hash GNU_HASH 00000000004002d8 000002d8
000000000000001c 0000000000000000 A 7 0 8
[ 7] .dynsym DYNSYM 00000000004002f8 000002f8
0000000000000060 0000000000000018 A 8 1 8
[ 8] .dynstr STRTAB 0000000000400358 00000358
000000000000003d 0000000000000000 A 0 0 1
[ 9] .gnu.version VERSYM 0000000000400396 00000396
0000000000000008 0000000000000002 A 7 0 2
[10] .gnu.version_r VERNEED 00000000004003a0 000003a0
0000000000000020 0000000000000000 A 8 1 8
[11] .rela.dyn RELA 00000000004003c0 000003c0
0000000000000018 0000000000000018 A 7 0 8
[12] .rela.plt RELA 00000000004003d8 000003d8
0000000000000030 0000000000000018 A 7 14 8
[13] .init PROGBITS 0000000000400408 00000408
0000000000000018 0000000000000000 AX 0 0 4
[14] .plt PROGBITS 0000000000400420 00000420
0000000000000030 0000000000000010 AX 0 0 16
[15] .text PROGBITS 0000000000400450 00000450
00000000000001e8 0000000000000000 AX 0 0 16
[16] .fini PROGBITS 0000000000400638 00000638
0000000000000016 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 0000000000400650 00000650
0000000000000010 0000000000000000 A 0 0 4
[18] .eh_frame_hdr PROGBITS 0000000000400660 00000660
0000000000000034 0000000000000000 A 0 0 4
[19] .eh_frame PROGBITS 0000000000400698 00000698
00000000000000dc 0000000000000000 A 0 0 8
[20] .ctors PROGBITS 0000000000600e30 00000e30
0000000000000010 0000000000000000 WA 0 0 8
[21] .dtors PROGBITS 0000000000600e40 00000e40
0000000000000010 0000000000000000 WA 0 0 8
[22] .jcr PROGBITS 0000000000600e50 00000e50
0000000000000008 0000000000000000 WA 0 0 8
[23] .dynamic DYNAMIC 0000000000600e58 00000e58
00000000000001a0 0000000000000010 WA 8 0 8
[24] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[25] .got.plt PROGBITS 0000000000601000 00001000
0000000000000028 0000000000000008 WA 0 0 8
[26] .data PROGBITS 0000000000601028 00001028
0000000000000010 0000000000000000 WA 0 0 8
[27] .bss NOBITS 0000000000601038 00001038
0000000000000010 0000000000000000 WA 0 0 8
[28] .comment PROGBITS 0000000000000000 00001038
0000000000000039 0000000000000001 MS 0 0 1
[29] .comment.SUSE.OPT PROGBITS 0000000000000000 00001071
0000000000000006 0000000000000001 MS 0 0 1
[30] .debug_aranges PROGBITS 0000000000000000 00001080
0000000000000060 0000000000000000 0 0 16
[31] .debug_pubnames PROGBITS 0000000000000000 000010e0
000000000000005f 0000000000000000 0 0 1
[32] .debug_info PROGBITS 0000000000000000 0000113f
0000000000000232 0000000000000000 0 0 1
[33] .debug_abbrev PROGBITS 0000000000000000 00001371
0000000000000133 0000000000000000 0 0 1
[34] .debug_line PROGBITS 0000000000000000 000014a4
000000000000011e 0000000000000000 0 0 1
[35] .debug_frame PROGBITS 0000000000000000 000015c8
0000000000000058 0000000000000000 0 0 8
[36] .debug_str PROGBITS 0000000000000000 00001620
0000000000000115 0000000000000001 MS 0 0 1
[37] .debug_loc PROGBITS 0000000000000000 00001735
00000000000000fe 0000000000000000 0 0 1
[38] .debug_ranges PROGBITS 0000000000000000 00001833
0000000000000050 0000000000000000 0 0 1
[39] .shstrtab STRTAB 0000000000000000 00001883
0000000000000192 0000000000000000 0 0 1
[40] .symtab SYMTAB 0000000000000000 00002498
00000000000007c8 0000000000000018 41 65 8
[41] .strtab STRTAB 0000000000000000 00002c60
0000000000000244 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)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000774 0x0000000000000774 R E 200000
LOAD 0x0000000000000e30 0x0000000000600e30 0x0000000000600e30
0x0000000000000208 0x0000000000000218 RW 200000
DYNAMIC 0x0000000000000e58 0x0000000000600e58 0x0000000000600e58
0x00000000000001a0 0x00000000000001a0 RW 8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x000000000000005c 0x000000000000005c R 4
GNU_EH_FRAME 0x0000000000000660 0x0000000000400660 0x0000000000400660
0x0000000000000034 0x0000000000000034 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
GNU_RELRO 0x0000000000000e30 0x0000000000600e30 0x0000000000600e30
0x00000000000001d0 0x00000000000001d0 R 1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.SuSE .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.SuSE .note.gnu.build-id
06 .eh_frame_hdr
07
08 .ctors .dtors .jcr .dynamic .got
Dynamic section at offset 0xe58 contains 21 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x400408
0x000000000000000d (FINI) 0x400638
0x0000000000000004 (HASH) 0x4002b0
0x000000006ffffef5 (GNU_HASH) 0x4002d8
0x0000000000000005 (STRTAB) 0x400358
0x0000000000000006 (SYMTAB) 0x4002f8
0x000000000000000a (STRSZ) 61 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x601000
0x0000000000000002 (PLTRELSZ) 48 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x4003d8
0x0000000000000007 (RELA) 0x4003c0
0x0000000000000008 (RELASZ) 24 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x4003a0
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x400396
0x0000000000000000 (NULL) 0x0
Relocation section '.rela.dyn' at offset 0x3c0 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
Relocation section '.rela.plt' at offset 0x3d8 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.dynsym' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts#GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (2)
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 83 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400238 0 SECTION LOCAL DEFAULT 1
2: 0000000000400254 0 SECTION LOCAL DEFAULT 2
3: 0000000000400274 0 SECTION LOCAL DEFAULT 3
4: 000000000040028c 0 SECTION LOCAL DEFAULT 4
5: 00000000004002b0 0 SECTION LOCAL DEFAULT 5
6: 00000000004002d8 0 SECTION LOCAL DEFAULT 6
7: 00000000004002f8 0 SECTION LOCAL DEFAULT 7
8: 0000000000400358 0 SECTION LOCAL DEFAULT 8
9: 0000000000400396 0 SECTION LOCAL DEFAULT 9
10: 00000000004003a0 0 SECTION LOCAL DEFAULT 10
11: 00000000004003c0 0 SECTION LOCAL DEFAULT 11
12: 00000000004003d8 0 SECTION LOCAL DEFAULT 12
13: 0000000000400408 0 SECTION LOCAL DEFAULT 13
14: 0000000000400420 0 SECTION LOCAL DEFAULT 14
15: 0000000000400450 0 SECTION LOCAL DEFAULT 15
16: 0000000000400638 0 SECTION LOCAL DEFAULT 16
17: 0000000000400650 0 SECTION LOCAL DEFAULT 17
18: 0000000000400660 0 SECTION LOCAL DEFAULT 18
19: 0000000000400698 0 SECTION LOCAL DEFAULT 19
20: 0000000000600e30 0 SECTION LOCAL DEFAULT 20
21: 0000000000600e40 0 SECTION LOCAL DEFAULT 21
22: 0000000000600e50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600e58 0 SECTION LOCAL DEFAULT 23
24: 0000000000600ff8 0 SECTION LOCAL DEFAULT 24
25: 0000000000601000 0 SECTION LOCAL DEFAULT 25
26: 0000000000601028 0 SECTION LOCAL DEFAULT 26
27: 0000000000601038 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 SECTION LOCAL DEFAULT 34
35: 0000000000000000 0 SECTION LOCAL DEFAULT 35
36: 0000000000000000 0 SECTION LOCAL DEFAULT 36
37: 0000000000000000 0 SECTION LOCAL DEFAULT 37
38: 0000000000000000 0 SECTION LOCAL DEFAULT 38
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
40: 0000000000000000 0 FILE LOCAL DEFAULT ABS
41: 0000000000000000 0 FILE LOCAL DEFAULT ABS initfini.c
42: 000000000040047c 0 FUNC LOCAL DEFAULT 15 call_gmon_start
43: 0000000000400648 0 NOTYPE LOCAL DEFAULT 16 _real_fini
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
45: 0000000000600e30 0 OBJECT LOCAL DEFAULT 20 __CTOR_LIST__
46: 0000000000600e40 0 OBJECT LOCAL DEFAULT 21 __DTOR_LIST__
47: 0000000000600e50 0 OBJECT LOCAL DEFAULT 22 __JCR_LIST__
48: 00000000004004a0 0 FUNC LOCAL DEFAULT 15 __do_global_dtors_aux
49: 0000000000601038 1 OBJECT LOCAL DEFAULT 27 completed.6159
50: 0000000000601040 8 OBJECT LOCAL DEFAULT 27 dtor_idx.6161
51: 0000000000400510 0 FUNC LOCAL DEFAULT 15 frame_dummy
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
53: 0000000000600e38 0 OBJECT LOCAL DEFAULT 20 __CTOR_END__
54: 0000000000400770 0 OBJECT LOCAL DEFAULT 19 __FRAME_END__
55: 0000000000600e50 0 OBJECT LOCAL DEFAULT 22 __JCR_END__
56: 0000000000400600 0 FUNC LOCAL DEFAULT 15 __do_global_ctors_aux
57: 0000000000000000 0 FILE LOCAL DEFAULT ABS initfini.c
58: 0000000000000000 0 FILE LOCAL DEFAULT ABS 24173361_generating-an-ob
59: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.c
60: 0000000000000000 0 FILE LOCAL DEFAULT ABS
61: 0000000000600e2c 0 NOTYPE LOCAL DEFAULT 20 __init_array_end
62: 0000000000600e58 0 OBJECT LOCAL DEFAULT 23 _DYNAMIC
63: 0000000000600e2c 0 NOTYPE LOCAL DEFAULT 20 __init_array_start
64: 0000000000601000 0 OBJECT LOCAL DEFAULT 25 _GLOBAL_OFFSET_TABLE_
65: 0000000000400560 2 FUNC GLOBAL DEFAULT 15 __libc_csu_fini
66: 0000000000601028 0 NOTYPE WEAK DEFAULT 26 data_start
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts##GLIBC_2.2.5
68: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 26 _edata
69: 0000000000400638 16 FUNC GLOBAL DEFAULT 16 _fini
70: 0000000000600e48 0 OBJECT GLOBAL HIDDEN 21 __DTOR_END__
71: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_
72: 0000000000601028 0 NOTYPE GLOBAL DEFAULT 26 __data_start
73: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
74: 0000000000601030 0 OBJECT GLOBAL HIDDEN 26 __dso_handle
75: 0000000000400650 4 OBJECT GLOBAL DEFAULT 17 _IO_stdin_used
76: 0000000000400570 137 FUNC GLOBAL DEFAULT 15 __libc_csu_init
77: 0000000000601048 0 NOTYPE GLOBAL DEFAULT 27 _end
78: 0000000000400450 0 FUNC GLOBAL DEFAULT 15 _start
79: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 27 __bss_start
80: 000000000040053c 21 FUNC GLOBAL DEFAULT 15 main
81: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
82: 0000000000400408 0 FUNC GLOBAL DEFAULT 13 _init
Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 1 ( 33.3%)
1 1 ( 33.3%) 33.3%
2 1 ( 33.3%) 100.0%
Version symbols section '.gnu.version' contains 4 entries:
Addr: 0000000000400396 Offset: 0x000396 Link: 7 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x00000000004003a0 Offset: 0x0003a0 Link: 8 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 1
0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2
Notes at offset 0x00000254 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6.4
Notes at offset 0x00000274 with length 0x00000018:
Owner Data size Description
SuSE 0x00000004 Unknown note type: (0x45537553)
Notes at offset 0x0000028c with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 710ef458701fed230f91233a227b7b10c024e2ed
While, that is a lot of detail for such a little file. Here is how to break it down problematically. First, the elf(64) header:
typedef struct elf64_hdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
The secret to creating an elf file is to understand the above structure. This is the first bit of the file your C program must write. Although too lengthy to detail here, you can find this structure in elf.h; which is located (on most Linux systems) here: /usr/include/elf.h.