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

-- 
Mailing list: https://launchpad.net/~touch-packages
Post to     : touch-packages@lists.launchpad.net
Unsubscribe : https://launchpad.net/~touch-packages
More help   : https://help.launchpad.net/ListHelp

Reply via email to