OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 7:52 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Tue May 21, 2013 5:52 am 
Offline
Member
Member

Joined: Sat Nov 04, 2006 5:38 am
Posts: 31
Location: Earth
Hi :)
I have a Problem with my linker, I explain the problem at the function stCalibrateVref out of a proprietary library called simplemac. The problem appears everywhere inside the library. The processor is a cortex-m3.

The stCalibrateVref function out of the library:
Code:
arm-none-eabi-objdump -d -j .text libsimplemac.a > libsimplemac.dump
00000076 <stCalibrateVref>:
  76:   b530            push    {r4, r5, lr}
  78:   b087            sub     sp, #28
  7a:   230a            movs    r3, #10
  7c:   227f            movs    r2, #127        ; 0x7f
  7e:   f85f 0004       ldr.w   r0, [pc, #-4]   ; 650 <??DataTable15_4>
  82:   8801            ldrh    r1, [r0, #0]
  84:   a803            add     r0, sp, #12
  86:   f7ff fffe       bl      0 <halInternalGetMfgTokenData>
  8a:   f8bd 1012       ldrh.w  r1, [sp, #18]
  8e:   f85f 5004       ldr.w   r5, [pc, #-4]   ; 64c <??DataTable15_3>
  92:   f64f 72ff       movw    r2, #65535      ; 0xffff
  96:   4291            cmp     r1, r2
  98:   d002            beq.n   a0 <??stCalibrateVref_0>
  9a:   7b28            ldrb    r0, [r5, #12]
  9c:   07c0            lsls    r0, r0, #31
  9e:   d57c            bpl.n   19a <??stCalibrateVref_1>



The stCalibrateVref function after linking:
Code:
arm-none-eabi-objdump -d -j .text binary.elf > binary.dump
08007972 <stCalibrateVref>:
8007972:       b530            push    {r4, r5, lr}
8007974:       b087            sub     sp, #28
8007976:       230a            movs    r3, #10
8007978:       227f            movs    r2, #127        ; 0x7f
800797a:       f8df 05ce       ldr.w   r0, [pc, #1486] ; 8007f4a <??DataTable15_3+0x2>
800797e:       8801            ldrh    r1, [r0, #0]
8007980:       a803            add     r0, sp, #12
8007982:       f7fc faf5       bl      8003f70 <halInternalGetMfgTokenData>
8007986:       f8bd 1012       ldrh.w  r1, [sp, #18]
800798a:       f8df 55ba       ldr.w   r5, [pc, #1466] ; 8007f46 <??DataTable15_2+0x2>
800798e:       f64f 72ff       movw    r2, #65535      ; 0xffff
8007992:       4291            cmp     r1, r2
8007994:       d002            beq.n   800799c <??stCalibrateVref_0>
8007996:       7b28            ldrb    r0, [r5, #12]
8007998:       07c0            lsls    r0, r0, #31
800799a:       d57c            bpl.n   8007a96 <??stCalibrateVref_1>


Stack after crash
Code:
  xPSR: 0x01000000
    PC: 0x0800797E
    LR: 0x08004AD7
   R12: 0x88000081
   R3 : 0x0000000A
   R2 : 0x0000007F
   R1 : 0x00000001
   R0 : 0xF4042000


So, the program crashs at address 0x0800797E.
Problem: r0 contains a wrong value. This wrong value comes from the instruction above. (@ 0x0800797a)

It reads a value from PC+1486 = 0x08007F4A (At the time, the address gets calculated, the PC points at the second half-word of the
instruction) which points to the value 0xF4042000
Code:
(gdb) x/x 0x8007f4A
0x8007f4a <??DataTable15_3+2>:  0xf4042000


Increasing this invalid address by 2 leads to 0x8007F4C
At this address the wished value is stored, that is addressed in the libraries dump
Code:
(gdb) x/x 0x8007f4C
0x8007f4c <??DataTable15_4>:    0x0800f404

This values points to data which seems to be the a valid argument for the following function-call (halInternalGetMfgTokenData)
Code:
(gdb) x/x 0x800f404
0x800f404 <TOKEN_MFG_ANALOG_TRIM_BOTH>: 0x07dc07d2


So, why the hell does the linker link to <??DataTable15_3+2> and not to <??DataTable15_4>?

I use the following setup:
Code:
CFLAGS="-Wall -nostdlib -fno-common -fno-builtin -O0 -g -mcpu=cortex-m3 -mthumb -c -std=c99 -fshort-wchar $DEFINES $HEADERPATHES"
LDFLAGS="-nostartfiles -nostdlib -static -A cortex-m3 -T$LDFILE $LIBPATHES"


I tested it with the following versions (same result with both)
Code:
arm-none-eabi-ld --version
-> GNU ld (GNU Binutils) 2.23.1
-> GNU ld (GNU Binutils) 2.21.1
arm-none-eabi-gcc --version
-> arm-none-eabi-gcc (Linaro GCC 4.7-2013.01) 4.7.3 20130102
-> arm-none-eabi-gcc (Linaro GCC 4.6-2011.10) 4.6.2 20111004


This is my linker-script
Code:
/*based on stm32_flash.ld form STM*/
ENTRY(Reset_Handler)

_estack = 0x20004000;
_Min_Heap_Size = 0x100;
_Min_Stack_Size = 4K;
_stack_size = _Min_Stack_Size;

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 256K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 16K
}

SECTIONS
{
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } >FLASH

  .text :
  {
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.rodata)
    *(.rodata*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    *(.constdata)
    *(.rev16_text)
    *(.revsh_text)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;
  } >FLASH

  _sidata = .;

  .data : AT ( _sidata )
  {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } >RAM

  . = ALIGN(4);
  .bss :
  {
    _sbss = .;
    __bss_start__ = _sbss;

    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  } >RAM

  ._user_heap_stack :
  {
    . = ALIGN(4);
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM


/* source: http://eehusky.wordpress.com/2012/12/17/using-gcc-with-the-ti-stellaris-launchpad-newlib/ */
    _heap_bottom = .;
    heap_low = _heap_bottom;
    _heap_top = ORIGIN(RAM) + LENGTH(RAM) - _stack_size;
    heap_top = _heap_top;

    _stack_bottom = _heap_top;
    _stack_top = ORIGIN(RAM) + LENGTH(RAM);

  .ARM.attributes 0 : { *(.ARM.attributes) }
}


Some information about the ABI:
analogue.o is part of the libsimplemac.a
Code:
readelf -a analogue.o | grep ABI
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Flags:                             0x5000000, Version5 EABI
  Tag_ABI_PCS_GOT_use: direct
  Tag_ABI_FP_denormal: Sign only
  Tag_ABI_FP_number_model: Finite
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_optimization_goals: Aggressive Size
  Tag_ABI_PCS_GOT_use: direct
  Tag_ABI_PCS_wchar_t: 2
  Tag_ABI_FP_denormal: Sign only
  Tag_ABI_FP_number_model: Finite
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: small
  Tag_ABI_optimization_goals: Prefer Size


The code which uses the library
Code:
readelf -a main.o | grep ABI
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Flags:                             0x5000000, Version5 EABI
  Tag_ABI_PCS_wchar_t: 2
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: small
  Tag_ABI_optimization_goals: Aggressive Debug


I hope someone has a good idea or a hint :)

_________________
mfg.: RedEagle


Top
 Profile  
 
 Post subject: Re: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Tue May 21, 2013 7:28 am 
Offline
Member
Member
User avatar

Joined: Wed Mar 21, 2012 3:01 pm
Posts: 930
Hi, this is an overwhelming amount of debugging information, but good to have it. :-)

I can't spot your problem, but perhaps the problem seems to be related to position independent code since it loads the address relative to the program counter. Perhaps there is some problem with alignment or it thinks it is being linked at a wrong location.

In addition, you are passing some bad flags to your compiler, but that is likely irrelevant to this problem. You shouldn't pass the -fno-builtin option as it allows the compiler to optimize your code knowing what common functions do (assuming your standard functions such as 'strlen' does what one would expect). Note how -nostdlib is equal to -nodefaultlibs -nostartfiles, so your additional -nostartfiles is redundant.


Top
 Profile  
 
 Post subject: Re: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Tue May 21, 2013 1:17 pm 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
Could you display the output of the disassembly of the object file with the relocation types too? (i.e. objdump -dr ...)

Do you have access to the source for this library? If so, perhaps you could try compiling it in ARM mode (rather than thumb) and seeing if that helps.

Regards,
John

_________________
Tysos | rpi-boot


Top
 Profile  
 
 Post subject: Re: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Wed May 22, 2013 12:39 am 
Offline
Member
Member

Joined: Sat Nov 04, 2006 5:38 am
Posts: 31
Location: Earth
I forgot to mention that I tried . = ALIGN(4); and . = ALIGN(2); but it didn't change anything.

@jnc100: No, there is no source code for this library available :(
arm-none-eabi-objdump -dr libsimplemac.a
Code:
00000076 <stCalibrateVref>:
  76:   b530            push    {r4, r5, lr}
  78:   b087            sub     sp, #28
  7a:   230a            movs    r3, #10
  7c:   227f            movs    r2, #127        ; 0x7f
  7e:   f85f 0004       ldr.w   r0, [pc, #-4]   ; 650 <??DataTable15_4>
                        7e: R_ARM_THM_PC12      ??DataTable15_4
  82:   8801            ldrh    r1, [r0, #0]
  84:   a803            add     r0, sp, #12
  86:   f7ff fffe       bl      0 <halInternalGetMfgTokenData>
                        86: R_ARM_THM_CALL      halInternalGetMfgTokenData
  8a:   f8bd 1012       ldrh.w  r1, [sp, #18]
  8e:   f85f 5004       ldr.w   r5, [pc, #-4]   ; 64c <??DataTable15_3>
                        8e: R_ARM_THM_PC12      ??DataTable15_3
  92:   f64f 72ff       movw    r2, #65535      ; 0xffff
  96:   4291            cmp     r1, r2
  98:   d002            beq.n   a0 <??stCalibrateVref_0>
  9a:   7b28            ldrb    r0, [r5, #12]
  9c:   07c0            lsls    r0, r0, #31
  9e:   d57c            bpl.n   19a <??stCalibrateVref_1>

_________________
mfg.: RedEagle


Top
 Profile  
 
 Post subject: Re: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Wed May 22, 2013 4:00 am 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
I am no expert on the Thumb instruction set (I've only worked with 32-bit ARM instructions), but I wonder whether ld is at fault here (or you're missing some options that I can't seem to find):

According to the ARM manual, the Thumb32 encoding of ldr.w (literal) calculates the target address as Align(PC, 4) + SignExtend(imm12). Given that in Thumb mode, PC is 4 bytes ahead of the current instruction, this equates (in the output binary) to: Align(0x0800797e, 4) + 0x000005ce = 0x0800797c + 0x000005ce = 0x08007f4a, which as observed is wrong. The reason here I think is that the calculation used to generate the 0x5ce is wrong.

According to the ARM ELF supplement, R_ARM_THM_PC12 is calculated as S + A - Pa, where S is the target (i.e. 0x08007f4c), A is the addend (here -4 to account for the fact that PC is 4 bytes ahead in Thumb mode) and Pa = P & 0xfffffffc, where P is the place being relocated (here 0x0800797a, thus Pa = 0x08007978). The reason Pa is used instead of P is to account for the alignment of PC in the ldr.w instruction above.

S + A - Pa = 0x5d0, which when added to 0x0800797c gives the correct address.
S + A - P = 0x5ce, which doesn't. I wonder whether this is the calculation ld is using here.

Did ALIGN(4) cause the stCalibrateVref function to be aligned on a 4 byte boundary? If not, trying to enforce this is the only other thing I can suggest. Other than this, unless anyone else has any suggestions, perhaps you could ask on the binutils mailing list?

Regards,
John.

_________________
Tysos | rpi-boot


Top
 Profile  
 
 Post subject: Re: Linker links to a wrong address (ARM, GNU LD)
PostPosted: Wed Jan 28, 2015 7:52 am 
Offline

Joined: Wed Jan 28, 2015 7:35 am
Posts: 1
Heh, I just registered on this forum learning about ABI-s and other terms in embedded software development. Nonetheless, I will post something more like a question.

It looks like the library is compiled for hardware floating point support (by looking in Tag_ABI_FP_number_model: Finite); while the code that needs to use it compiles for a target with software floating point: Tag_ABI_FP_number_model: IEEE 754. Does this work? I am a beginner so this may seem a bit idiotic. :o In case you know general details about this, please explain.

Thanks!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 37 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group