bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/15302] Branching to linker script symbol is resolved to improper


From: terry.guo at arm dot com
Subject: [Bug ld/15302] Branching to linker script symbol is resolved to improperly BLX instruction for cortex-m3
Date: Fri, 21 Jun 2013 03:23:38 +0000

http://sourceware.org/bugzilla/show_bug.cgi?id=15302

Terry Guo <terry.guo at arm dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
   Last reconfirmed|                            |2013-06-21
         Resolution|FIXED                       |---
     Ever confirmed|0                           |1

--- Comment #7 from Terry Guo <terry.guo at arm dot com> ---
I am sorry that I have to reopen it. The proposed patch will cause below issue. 

In the below concrete case, the __init_array_start is allocated at address
0x11a40 actually. But any relocations using address of __init_array_start will
be resolved to use address 0x11a41 by linker, thus the subsequential deference
on __init_array_start is a deference on wrong address (0x11a41). 

This is because the proposed patch set ST_BRANCH_TO_THUMB to the symbol
__init_array_start, then the last bit of its address is set by the linker
function elf32_arm_swap_symbol_out.

To reproduce this issue, an ARM baremetal toolchain using Newlib as C library
is needed. Then use below command to build a project with empty main function:
arm-none-eabi-gcc -mthumb -mcpu=cortex-m3 -O2 -lc -lrdimon -specs=rdimon.specs
test.c -o test.out -Wl,-verbose -Wl,-Map=test.map

Then run test.out on QEMU, a Segmentation falut will be reported.
qemu-system-arm -cpu cortex-m3 -nographic -monitor null -serial null
-semihosting -kernel ./test.out

This QEMU segmentation fault is caused by deference of __init_array_start in
function __libc_init_array.

Here are some investigations:
Disassemble the test.out with command "arm-none-eabi-objdump -D test.out" and
we will see:

Disassembly of section .init_array:

00011a40 <__init_array_start>:
   11a40:       0000802d        andeq   r8, r0, sp, lsr #32


The __init_array_start is allocated at address 0x11a40 actually.

Meanwhile the command "arm-none-eabi-readelf -s test.out", we will get symbol
table:

   222: 00011a41     0 FUNC    LOCAL  DEFAULT    7 __init_array_start

Thus any instructions using __init_array_start will be resolved to 0x11a41
instead of 0x11a40.

movw    r5, #:lower16:__init_array_start
movt    r5, #:upper16:__init_array_start
ldr     r3, [r5, #4]!
blx     r3

in the above case, the r5 will get wrong value 0x11a41, then r3 will get wrong
value, finally the blx will cause the fault.

Here are some background on Newlib:

In Newlib init.c we have code:

extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));

void
__libc_init_array (void)
{
  size_t count;
  size_t i;

................

  count = __init_array_end - __init_array_start;
  for (i = 0; i < count; i++)
    __init_array_start[i] ();
}

Both __init_array_start and __init_array_end are defined in linker script as:

  .init_array     :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array ))
    PROVIDE_HIDDEN (__init_array_end = .);
  }

-- 
You are receiving this mail because:
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]