7.4.1. BPABI relocation example

Example 7.1. C source file, foo.c with a reference to bar and x

__declspec(dllimport) void bar(void);
__declspec(dllimport) extern int x;

int foo(void)
{
    bar();
    return x;
}

Example 7.2. Shared library, shared.c defining bar and x

__declspec(dllexport) int x = 1;

__declspec(dllexport) void bar(void)
{
    x++;
}

In Example 7.1 there is a reference to a function called bar and a variable called x. Both symbols are marked as being defined in another module with the __declspec(dllimport) attribute. When the ELF object, generated from this example code, is statically linked with the shared library (Example 7.2) that defines bar and x, a dynamic relocation section, .dyn, is generated in the executable image, for example:

** Section #5 '.dyn' (SHT_REL)
    Size    : 16 bytes (alignment 4)
    Symbol table #3 '.dynsym'
    2 relocations applied to section #0 '[Anonymous Section]'

    #    Offset        Relocation Type      Wrt    Symbol    Defined in

    0    0x0000800C    2 R_ARM_ABS32        2      bar       Ref
    1    0x00008024    2 R_ARM_ABS32        3      x         Ref

The relocation type added to the image is R_ARM_ABS32 (relocation number 2 from section 4.6.18 of the ABI ELF for the ARM Architecture document). This is an ARM absolute 32-bit relocation, which is commonly found in static and dynamic relocation sections. To get a better feel for relocations, it is a good idea to have read the ELF for the ARM Architecture document.

At load or run-time the dynamic linker might load the shared library into memory, if it is required by the application or another shared library (module). When the dynamic linker has loaded the shared library, it has to know the addresses given to symbols x and bar. Using this information, the dynamic linker then needs to resolve all dynamic relocations to these symbols from the executable image, or any other application or module that requires this shared library.

"Table 4-8, Relocation codes" from the ELF for the ARM Architecture document shows the operation required to calculate the address used for the R_ARM_ABS32 type relocation:

(S + A) | T

S = the address of the S A = the addend for the relocation T = 1 if the target symbol S has type STT_FUNC and the symbol addresses is a Thumb instruction; it is 0 otherwise.

In Example 7.1, the symbol x does not have type STT_FUNC, and neither is it the symbol address of a Thumb function. Therefore, T = 0.The relocations in the image are of type SHT_REL, so the addend for the relocation is encoded into the address which the dynamic linker needs to fill in to resolve the relocation at run-time. This is address 0x00008024, which has a value of 0x00000000 in the executable image:

** Section #1 'ER_RO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
    Size    : 40 bytes (alignment 4)
    Address: 0x00008000

    :
    :

    $a
    .text
    foo
        0x00008010:    E92D4010    .@-.    PUSH      {r4,lr}
        0x00008014:    EBFFFFFA    ....    BL        0x8004 ; 0x8004
        0x00008018:    E59F0004    ....    LDR       r0,[pc,#4] ; [0x8024] = 0
        0x0000801C:    E5900000    ....    LDR       r0,[r0,#0]
        0x00008020:    E8BD8010    ....    POP       {r4,pc}
    $d
        0x00008024:    00000000    ....    DCD    0

Therefore, there is no addend; A is 0x0.

The following disassembly listing shows the code and data sections of the shared library:

** Section #1 'ER_RO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
    Size    : 24 bytes (alignment 4)
    Address: 0x00008000

    $a
    .text
    bar
        0x00008000:    E59F000C ....    LDR    r0,[pc,#12] ; [0x8014] = 0
        0x00008004:    E5901000 ....    LDR    r1,[r0,#0]
        0x00008008:    E2811001 ....    ADD    r1,r1,#1
        0x0000800C:    E5801000 ....    STR    r1,[r0,#0]
        0x00008010:    E12FFF1E ../.    BX     lr
    $d
        0x00008014:    00000000 .... DCD 0

** Section #2 'ER_RW' (SHT_PROGBITS) [SHF_ALLOC + SHF_WRITE]
    Size    : 4 bytes (alignment 4)
    Address: 0x00000000

    0x000000:    01 00 00 00                                    ....

Note

Although the fromelf output shows ER_RO starting at address 0x8000, it can be relocated or loaded to a different address such as 0x9000 by the dynamic linker.

Suppose the dynamic linker loads the shared object (module) that contains the symbol x to address 0x9000. This means that the first instruction in the code section (#1) starts at address 0x9000 and the last instruction is at address 0x9014.

Assuming the dynamic linker loads the data section (#2) of the shared library directly after the code section, the address of symbol x is 0x9018, and the following calculation can be applied:

(S + A) | T
= (0x9018 + 0) | 0
= 0x9018

Therefore, the dynamic linker must write the value 0x9018 to address 0x8024 to ensure that the function foo can access the variable x. It also needs to write the same value to address 0x9014 once the shared library is loaded into memory.

Copyright © 2010 ARM. All rights reserved.ARM DAI 0242A
Non-ConfidentialID011411