touch-packages team mailing list archive
-
touch-packages team
-
Mailing list archive
-
Message #27041
[Bug 1130768] Re: Chromium SEGV's before main() when linked with gold on armhf (12.04)
fixed; if a backport for 12.04 is needed, please nominate this issue
** Changed in: binutils (Ubuntu)
Status: Triaged => Fix Released
** Changed in: binutils (Ubuntu)
Assignee: Matthias Klose (doko) => (unassigned)
--
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to binutils in Ubuntu.
https://bugs.launchpad.net/bugs/1130768
Title:
Chromium SEGV's before main() when linked with gold on armhf (12.04)
Status in “binutils” package in Ubuntu:
Fix Released
Bug description:
Chromium crashes before reaching main() on armhf when linked with
gold, with the following stacktrace:
(gdb) bt
#0 0x0022a990 in ?? ()
#1 0x2bec9b5e in __libc_csu_init ()
#2 0xb63d9f98 in __libc_start_main (main=0x2a231689 <main+1>, argc=1, ubp_av=0xbefff334, init=0x2bec9b49 <__libc_csu_init+1>, fini=0x2bec9b8d <__libc_csu_fini+1>, rtld_fini=0xb6feb179 <_dl_fini>,
stack_end=0xbefff334) at libc-start.c:185
#3 0x2a2315fa in _start ()
(gdb) info registers
r0 0x1 1
r1 0xbefff334 3204444980
r2 0xbefff33c 3204444988
r3 0xb64a2bac 3058314156
r4 0x2bec9b49 736926537
r5 0x2ce65000 753291264
r6 0x1 1
r7 0xbefff334 3204444980
r8 0xbefff33c 3204444988
r9 0xf9b4f2 16364786
r10 0x2ce86834 753428532
r11 0x0 0
r12 0x0 0
sp 0xbefff1c8 0xbefff1c8
lr 0x2bec9b5f 736926559
pc 0x22a990 0x22a990
cpsr 0x600b0130 1611333936
Notice that the address in the program counter is the exact offset of
the .init section in the binary:
chr1s@wernstrom:/srv$ readelf -S /usr/lib/chromium-browser/chromium-browser
There are 32 section headers, starting at offset 0x2e87df4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 00000174 000174 000019 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00000190 000190 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 000001b0 0001b0 000024 00 A 0 0 4
[ 4] .dynsym DYNSYM 000001d4 0001d4 009a00 10 A 5 1 4
[ 5] .dynstr STRTAB 00009bd4 009bd4 00d2d4 00 A 0 0 1
[ 6] .gnu.hash GNU_HASH 00016ea8 016ea8 0001a8 04 A 4 0 4
[ 7] .gnu.version VERSYM 00017050 017050 001340 02 A 4 0 2
[ 8] .gnu.version_r VERNEED 00018390 018390 000390 00 A 5 13 4
[ 9] .rel.dyn REL 00018720 018720 20da68 08 A 4 0 4
[10] .rel.plt REL 00226188 226188 004808 08 A 4 12 4
[11] .init PROGBITS 0022a990 22a990 00000a 00 AX 0 0 4 <---------------------
[12] .plt PROGBITS 0022a99c 22a99c 006c20 00 AX 0 0 4
[13] .text PROGBITS 002315c0 2315c0 1c9a368 00 AX 0 0 16
[14] .fini PROGBITS 01ecb928 1ecb928 000006 00 AX 0 0 4
[15] .ARM.exidx ARM_EXIDX 01ecb930 1ecb930 000018 08 AL 13 0 4
[16] .rodata PROGBITS 01ecba00 1ecba00 e4b954 00 A 0 0 256
[17] .eh_frame PROGBITS 02d17354 2d17354 000004 00 A 0 0 4
[18] .eh_frame_hdr PROGBITS 02d17358 2d17358 000008 00 A 0 0 4
[19] .data.rel.ro.loca PROGBITS 02d18fb8 2d17fb8 0481e0 00 WA 0 0 8
[20] .jcr PROGBITS 02d61198 2d60198 000004 00 WA 0 0 4
[21] .data.rel.ro PROGBITS 02d611a0 2d601a0 103c30 00 WA 0 0 8
[22] .dynamic DYNAMIC 02e64dd0 2e63dd0 000230 08 WA 5 0 4
[23] .init_array INIT_ARRAY 02e65000 2e64000 000054 00 WA 0 0 4
[24] .fini_array FINI_ARRAY 02e65054 2e64054 000004 00 WA 0 0 4
[25] .data PROGBITS 02e65060 2e64060 01b2b0 00 WA 0 0 16
[26] .got PROGBITS 02e80310 2e7f310 008934 00 WA 0 0 4
[27] .bss NOBITS 02e88c48 2e87c44 0299de 00 WA 0 0 8
[28] .note.gnu.gold-ve NOTE 00000000 2e87c44 00001c 00 0 0 4
[29] .ARM.attributes ARM_ATTRIBUTES 00000000 2e87c60 000035 00 0 0 1
[30] .gnu_debuglink PROGBITS 00000000 2e87c95 000018 00 0 0 1
[31] .shstrtab STRTAB 00000000 2e87cad 000145 00 0 0 1
...but this is a relocatable binary, so this is wrong!
chr1s@wernstrom:/srv$ readelf -h /usr/lib/chromium-browser/chromium-browser
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x2315c1
Start of program headers: 52 (bytes into file)
Start of section headers: 48791028 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 10
Size of section headers: 40 (bytes)
Number of section headers: 32
Section header string table index: 31
Looking a bit closer at what __libc_csu_init is doing:
01ec9b48 <__xstat64+0x7fe1c4>:
1ec9b48: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr}
1ec9b4c: 4606 mov r6, r0
1ec9b4e: 4d0d ldr r5, [pc, #52] ; (1ec9b84 <__xstat64+0x7fe200>)
1ec9b50: 460f mov r7, r1
1ec9b52: f8df 9034 ldr.w r9, [pc, #52] ; 1ec9b88 <__xstat64+0x7fe204>
1ec9b56: 4690 mov r8, r2
1ec9b58: 447d add r5, pc
1ec9b5a: f001 eedc blx 1ecb914 <__xstat64+0x7fff90>
1ec9b5e: 44f9 add r9, pc
1ec9b60: ebc5 0909 rsb r9, r5, r9
1ec9b64: ea5f 09a9 movs.w r9, r9, asr #2
1ec9b68: d00a beq.n 1ec9b80 <__xstat64+0x7fe1fc>
1ec9b6a: 3d04 subs r5, #4
1ec9b6c: 2400 movs r4, #0
1ec9b6e: f855 3f04 ldr.w r3, [r5, #4]!
1ec9b72: 4630 mov r0, r6
1ec9b74: 4639 mov r1, r7
1ec9b76: 4642 mov r2, r8
1ec9b78: 3401 adds r4, #1
1ec9b7a: 4798 blx r3
1ec9b7c: 454c cmp r4, r9
1ec9b7e: d1f6 bne.n 1ec9b6e <__xstat64+0x7fe1ea>
1ec9b80: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc}
Here, it is doing a relative branch to offset 1db8 and switching to
ARM mode:
1ec9b5a: f001 eedc blx 1ecb914 <__xstat64+0x7fff90>
This is where it lands (now in ARM mode):
01ecb914 <.data+0x1ecb914>:
1ecb914: e51ff004 ldr pc, [pc, #-4] ; 0x1ecb918
1ecb918: 0022a991 mlaeq r2, r1, r9, sl
... which is basically doing a branch to address 0x22a990 by loading
the program counter with the absolute address stored in the binary.
For a relocatable binary, this is not right - it's like the linker
thought this is not relocatable ;)
The following simple test case reproduces the exact same bug:
chr1s@wernstrom:/srv$ cat ~/Desktop/test.cpp
__attribute__((section(".text"))) char test[60000000] = {0};
int main(int argc, char *argv[]) {}
Compile this with "g++ -o test test.cpp -fPIC -pie"
The key here is that the offset between __libc_csu_init() and the
start of the .init section in the binary must exceed the range of the
relative branch instructions (+/-16MB in thumb mode). If it isn't,
then the linker inserts a relative branch in __libc_csu_init() (as
opposed to the blx and then absolute branch from ARM mode that we get
now), and this works fine.
This is fixed in raring, and the bfd linker also does the right thing.
Here is what happens with the test case when linked with the bfd
linker:
03938d30 <.data+0x3938d30>:
3938d30: e59fc004 ldr ip, [pc, #4] ; 0x3938d3c
3938d34: e08fc00c add ip, pc, ip
3938d38: e12fff1c bx ip
... which basically loads an offset in to r12, adds the PC to it and
branches to it
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/binutils/+bug/1130768/+subscriptions