This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ARM mapping symbols and --strip-unneeded


Hi,

I ran into a curious problem when cross-compiling a big-endian ARM Linux
userland: Programs would keep segfaulting with "illegal instruction" on
the real hardware as well as when run via qemu-user/binfmt_misc.

After some digging I figured out that this was because the ARM mapping
symbols ($a, $d, $t) had been stripped from GCC and glibc startup code
files (crt{1,i,n,begin}.o et.al) by my host system's package manager
that created the cross-toolchain (Gentoo portage/crossdev) using option
--strip-unneeded.

After disabling stripping, the produced binaries now run fine.

An otherwise identical toolchain for the same hardware but little-endian
userland also has those symbols stripped but does not show the problem. It
seems to make no difference whether the produced binaries are BE8 or BE32
either.

A symptom of this can be observed when disassembling a binary: If the
mapping symbols had been stripped before linking, objdump will not be
able to disassemble the corresponding instructions and just show .word.

So, is it reasonable to assume that ld relies on the mapping symbols
when producing output for big-endian ARM to get the byte order of those
instructions right that are somehow not otherwise obviously
instructions?

Based on this I'm wondering about the definition of "unneeded" (being:
"Remove all symbols that are not needed for relocation processing."):
Should the mapping symbols perhaps be considered needed and not
stripped?

In the meaintime: Is there another way than --preserve-symbol= to tell
strip to preserve mapping symbols? Because the symbol names contain $
it'd be a real pain to get --preserve-symbol=$a onto the strip command
line everywhere it's needed without the shell expanding $a away.

Finally, the simplest reproducer I can think of, adopted from glibc's
sysdeps/arm/crtn.S:

t.c:
int main(void) {}

a.s:
        .section .a,"ax",%progbits
        pop {r3, pc}

# armv7veb-hardfloat-linux-gnueabi-gcc -c -o t.o t.c
# armv7veb-hardfloat-linux-gnueabi-gcc -c -o a.o a.S
# armv7veb-hardfloat-linux-gnueabi-readelf --syms a.o

Symbol table '.symtab' contains 7 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 NOTYPE  LOCAL  DEFAULT    4 $a
     6: 00000000     0 SECTION LOCAL  DEFAULT    5 

# armv7veb-hardfloat-linux-gnueabi-objdump -d a.o

a.o:     file format elf32-bigarm


Disassembly of section .a:
00000000 <.a>:
   0:   e8bd8008        pop     {r3, pc}

# armv7veb-hardfloat-linux-gnueabi-gcc -o t t.o a.o
# armv7veb-hardfloat-linux-gnueabi-objdump -d -j .a t

t:     file format elf32-bigarm


Disassembly of section .a:

00010458 <.a>:
   10458:       e8bd8008        pop     {r3, pc}

# armv7veb-hardfloat-linux-gnueabi-strip --strip-unneeded a.o
# armv7veb-hardfloat-linux-gnueabi-readelf --syms a.o
# armv7veb-hardfloat-linux-gnueabi-objdump -d a.o

a.o:     file format elf32-bigarm


Disassembly of section .a:

00000000 <.a>:
   0:   e8bd8008        pop     {r3, pc}
# armv7veb-hardfloat-linux-gnueabi-gcc -o t t.o a.o
# armv7veb-hardfloat-linux-gnueabi-objdump -d -j .a t

t:     file format elf32-bigarm


Disassembly of section .a:
00010458 <.a>:
   10458:       e8bd8008        .word   0xe8bd8008
-- 
thanks, Micha


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]