0

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,

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
yo3hcv
  • 1,531
  • 2
  • 17
  • 27

1 Answers1

0

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

The provided excerpt of the map file does not show the symbol hex2num, it only shows that there's an input section called .text.hex2num. The section is called after the function that the compiler put there (this behavior is enabled with -ffunction-sections switch to gcc).

objdump cannot find the symbol hex2num(), it's completely missing.

If you readelf the source library, libwpa.a you'd see that the symbol is missing there as well:

File: libwpa.a(common.o)

Symbol table '.symtab' contains 35 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT   11 
     2: 00000000     0 SECTION LOCAL  DEFAULT   13 
     3: 00000000     0 SECTION LOCAL  DEFAULT   14 
     4: 00000000     0 SECTION LOCAL  DEFAULT   16 
     5: 00000000     0 SECTION LOCAL  DEFAULT   18 
     6: 00000000     0 SECTION LOCAL  DEFAULT   20 
     7: 00000000     0 SECTION LOCAL  DEFAULT   22 
     8: 00000000     0 SECTION LOCAL  DEFAULT   24 
     9: 00000000     0 SECTION LOCAL  DEFAULT    1 
    10: 00000000     0 SECTION LOCAL  DEFAULT    2 
    11: 00000000     0 SECTION LOCAL  DEFAULT    3 
    12: 00000000     0 SECTION LOCAL  DEFAULT    4 
    13: 00000000     0 SECTION LOCAL  DEFAULT    5 
    14: 00000000     0 SECTION LOCAL  DEFAULT    6 
    15: 00000000     0 SECTION LOCAL  DEFAULT    7 
    16: 00000000     0 SECTION LOCAL  DEFAULT    8 
    17: 00000000     0 SECTION LOCAL  DEFAULT    9 
    18: 00000000     0 SECTION LOCAL  DEFAULT   10 
    19: 00000000     0 SECTION LOCAL  DEFAULT   26 
    20: 00000000     0 SECTION LOCAL  DEFAULT   27 
    21: 00000000     0 SECTION LOCAL  DEFAULT   28 
    22: 00000000     0 SECTION LOCAL  DEFAULT   30 
    23: 00000000    29 FUNC    GLOBAL DEFAULT   11 inc_byte_array
    24: 00000008    57 FUNC    GLOBAL DEFAULT   16 hex2byte
    25: 00000004    68 FUNC    GLOBAL DEFAULT   18 hexstr2bin
    26: 0000001c   145 FUNC    GLOBAL DEFAULT   20 wpa_get_ntp_timestamp
    27: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND os_get_time
    28: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND ets_memcpy
    29: 00000034   266 FUNC    GLOBAL DEFAULT   22 wpa_config_parse_string
    30: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND ets_strlen
    31: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND pvPortMalloc
    32: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND vPortFree
    33: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND ets_strrchr
    34: 0000000c    72 FUNC    GLOBAL DEFAULT   24 dup_binstr

The symbol hex2num does not exist in the source library, gcc (or, more specifically, ld) did not remove it in the process of linking the final ELF image.

jcmvbkbc
  • 723
  • 1
  • 4
  • 5