This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
ARM mapping symbols and --strip-unneeded
- From: Michael Weiser <michael at weiser dot dinsnail dot net>
- To: binutils at sourceware dot org
- Date: Mon, 27 Jun 2016 00:13:36 +0200
- Subject: ARM mapping symbols and --strip-unneeded
- Authentication-results: sourceware.org; auth=none
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