I have a issue with gcc (5.2.0) for Xtensa LX106 CPU (ESP8266) that appears to omit some symbol names from executable (ELF) while they exists in *.map file and I am trying to understand why.
This is part of *.map file
*fill* 0x4021487b 0x0
*fill* 0x4021487b 0x0
*fill* 0x4021487b 0x1
.text.inc_byte_array
0x4021487c 0x1d W:\sensor_ovi\sw\sensor\app\esp8266\lib300\libwpa.a(common.o)
0x4021487c inc_byte_array
*fill* 0x40214899 0x3
.text.hex2num 0x4021489c 0x33 W:\sensor_ovi\sw\sensor\app\esp8266\lib300\libwpa.a(common.o)
*fill* 0x402148cf 0x0
*fill* 0x402148cf 0x0
*fill* 0x402148cf 0x0
*fill* 0x402148cf 0x1
.text.os_get_time
0x402148d0 0x4 W:\sensor_ovi\sw\sensor\app\esp8266\lib300\libwpa.a(os_xtensa.o)
0x402148d0 os_get_time
*fill* 0x402148d4 0x0
*fill* 0x402148d4 0x0
*fill* 0x402148d4 0x0
As you can see, there is no difference from inc_byte_array() to hex2num(), both functions gets linked since they are used.
But objdump cannot find the symbol hex2num(), it's completely missing. As a consequence, dumped assembly is wrong:
4021487c <inc_byte_array>:
inc_byte_array():
4021487c: 530b addi.n a5, a3, -1
4021487e: 1513a6 blti a3, 1, 40214897 <inc_byte_array+0x1b>
40214881: 352a add.n a3, a5, a2
40214883: 220b addi.n a2, a2, -1
40214885: 000342 l8ui a4, a3, 0
40214888: 441b addi.n a4, a4, 1
4021488a: 744040 extui a4, a4, 0, 8
4021488d: 004342 s8i a4, a3, 0
40214890: 34cc bnez.n a4, 40214897 <inc_byte_array+0x1b>
40214892: 330b addi.n a3, a3, -1
40214894: ed9327 bne a3, a2, 40214885 <inc_byte_array+0x9>
40214897: f00d ret.n
// here stops inc_byte_array()
40214899: 000000 ill
// here is linker padding fill 0x40214899 0x3
// and here starts the hex2num() but ELF is missing the symbol :(
4021489c: f32c movi.n a3, 47
4021489e: 09b327 bgeu a3, a2, 402148ab <inc_byte_array+0x2f>
402148a1: 943c movi.n a4, 57
402148a3: 043427 bltu a4, a2, 402148ab <inc_byte_array+0x2f>
402148a6: d0c222 addi a2, a2, -48
402148a9: f00d ret.n
402148ab: 60a052 movi a5, 96
402148ae: 0ab527 bgeu a5, a2, 402148bc <inc_byte_array+0x40>
402148b1: 66a062 movi a6, 102
402148b4: 043627 bltu a6, a2, 402148bc <inc_byte_array+0x40>
402148b7: a9c222 addi a2, a2, -87
402148ba: f00d ret.n
402148bc: 074c movi.n a7, 64
402148be: 09b727 bgeu a7, a2, 402148cb <inc_byte_array+0x4f>
402148c1: 684c movi.n a8, 70
402148c3: 043827 bltu a8, a2, 402148cb <inc_byte_array+0x4f>
402148c6: c9c222 addi a2, a2, -55
402148c9: f00d ret.n
402148cb: f27c movi.n a2, -1
402148cd: f00d ret.n
402148cf: 020c00 andb b0, b12, b0
Now this was a easy example, calling hex2num() it's straight forward. But there are situations that ASM dumped is completely wrong, since because symbol is missing, objdump just mess with the literals dumped before function (Xtensa LX106 is similar to Cortex M0)
Moreover, even *.map is wrong in some occasions, for example, says
libwpa.a:(.literal. .text.*) .text.hostapd_derive_psk 0x40210000 0x56 W:\sensor_ovi\sw\sensor\app\esp8266\lib300\libwpa.a(ap_config.o) fill 0x40210056 0x2 .text.hostapd_setup_wpa_psk 0x40210058 0x31 W:\sensor_ovi\sw\sensor\app\esp8266\lib300\libwpa.a(ap_config.o) 0x35 (size before relaxing) 0x40210058 hostapd_setup_wpa_psk
So we should find hostapd_derive_psk() at 40210000, size 0x56 followed by 2 bytes padding then hostapd_setup_wpa_psk() at 0x40210058
This is what was dumped by objdump:
40210000 <hostapd_setup_wpa_psk-0x58>:
// missing symbol completely hostapd_derive_psk() 40210000: 241630 extui a1, a3, 6, 3 40210003: df6540 excw 40210006: 2ac840100e583ffe { excw; extui a0, a0, 0, 2; add a12, a10, a8 } 4021000e: b44000 extui a4, a0, 0, 12 40210011: 0018 l32i.n a1, a0, 0 40210013: fb3140 excw 40210016: ff .byte 0xff 40210017: 22a142 movi a4, 0x122 4021001a: f0c112 addi a1, a1, -16 4021001d: 11c9 s32i.n a12, a1, 4 4021001f: 0109 s32i.n a0, a1, 0 40210021: 02cd mov.n a12, a2 40210023: 023c movi.n a2, 48 40210025: fff801 l32r a0, 40210008 <_irom0_text_start+0x8> 40210028: 0000c0 callx0 a0 4021002b: ac29 s32i.n a2, a12, 40 4021002d: 32cc bnez.n a2, 40210034 <_irom0_text_start+0x34> 4021002f: f27c movi.n a2, -1 40210031: 000606 j 4021004d <_irom0_text_start+0x4d> 40210034: bc28 l32i.n a2, a12, 44 40210036: fff501 l32r a0, 4021000c <_irom0_text_start+0xc> 40210039: 0000c0 callx0 a0 4021003c: fff231 l32r a3, 40210004 <_irom0_text_start+0x4> 4021003f: ac28 l32i.n a2, a12, 40 40210041: 042c movi.n a4, 32 40210043: 228b addi.n a2, a2, 8 40210045: fff201 l32r a0, 40210010 <_irom0_text_start+0x10> 40210048: 0000c0 callx0 a0 4021004b: 020c movi.n a2, 0 4021004d: 11c8 l32i.n a12, a1, 4 4021004f: 0108 l32i.n a0, a1, 0 40210051: 10c112 addi a1, a1, 16 40210054: f00d ret.n 40210056: 120000 andbc b0, b0, b0
40210058 <hostapd_setup_wpa_psk>:
hostapd_setup_wpa_psk():
// CORRECT 40210058: f0c112 addi a1, a1, -16 4021005b: 016102 s32i a0, a1, 4 4021005e: 0f2202 l32i a0, a2, 60 40210061: 01b016 beqz a0, 40210080 40210064: e208 l32i.n a0, a2, 56 40210066: 0129 s32i.n a2, a1, 0 40210068: 00dc bnez.n a0, 4021007c 4021006a: 10c222 addi a2, a2, 16 4021006d: fffa45 call0 40210014
// Oopss.. we have a call to 40210014 which is not listed anywhere, not even in *.map !!!
<_irom0_text_start+0x14> 40210070: 0042d6 bgez a2, 40210078 ...
So let's dump manually for correct code
xtensa-lx106-elf-objdump -dz --start-address=0x40210014 --stop-address=0x40210057 sensor.elf > sensor.txt
As you can see, this is the correct dumped assembly code
40210014: fffb31 l32r a3, 40210000 <_irom0_text_start>
40210017: 22a142 movi a4, 0x122
4021001a: f0c112 addi a1, a1, -16
4021001d: 11c9 s32i.n a12, a1, 4
4021001f: 0109 s32i.n a0, a1, 0
40210021: 02cd mov.n a12, a2
40210023: 023c movi.n a2, 48
40210025: fff801 l32r a0, 40210008 <_irom0_text_start+0x8>
40210028: 0000c0 callx0 a0
4021002b: ac29 s32i.n a2, a12, 40
4021002d: 32cc bnez.n a2, 40210034 <_irom0_text_start+0x34>
4021002f: f27c movi.n a2, -1
40210031: 000606 j 4021004d <_irom0_text_start+0x4d>
40210034: bc28 l32i.n a2, a12, 44
40210036: fff501 l32r a0, 4021000c <_irom0_text_start+0xc>
40210039: 0000c0 callx0 a0
4021003c: fff231 l32r a3, 40210004 <_irom0_text_start+0x4>
4021003f: ac28 l32i.n a2, a12, 40
40210041: 042c movi.n a4, 32
40210043: 228b addi.n a2, a2, 8
40210045: fff201 l32r a0, 40210010 <_irom0_text_start+0x10>
40210048: 0000c0 callx0 a0
4021004b: 020c movi.n a2, 0
4021004d: 11c8 l32i.n a12, a1, 4
4021004f: 0108 l32i.n a0, a1, 0
40210051: 10c112 addi a1, a1, 16
40210054: f00d ret.n
40210056: 120000 andbc b0, b0, b0
So back to original question, why gcc strip symbols that exists in *.map file?
Thanks for clarifications,