How does the linker (microcontroller context) work?

I have been programming in C and C ++ for quite some time now, so I am familiar with the binding process as a user: the preprocessor extends all prototypes and macros in each .c file, which is then compiled separately into its own object file and all object files along with static libraries associated with an executable file.

However, I would like to know more about this process: how does the linker link object files (what do they contain?)? Alignment of declared but undefined functions with their definitions in other files (how?)? Translation into the exact content of program memory (context: microcontrollers)?

Application example

Ideally, I'm looking for a detailed step-by-step description of what this process does, based on the following simplified example. Since he is not mentioned anywhere, glory and glory to those who respond in this way.

main.c

#include "otherfile.h"

int main(void) {
   otherfile_print("Foo");

   return 0;
}

otherfile.h

void otherfile_print(char const *);

otherfile.c

#include "otherfile.h"
#include <stdio.h>

void otherfile_print(char const *str) {
   printf(str);
}
+4
source share
1 answer

printf is insanely complex, very bad for an example microcontroller hi, flashing LEDs are better, but it depends on the microcontroller. this will be enough for communication.

two.c

unsigned int glob;
unsigned int two ( unsigned int a, unsigned int b )
{
    glob=5;
    return(a+b+7);
}

one.c

extern unsigned int glob;
unsigned int two ( unsigned int, unsigned int );
unsigned int one ( void )
{
    return(two(5,6)+glob);
}

start.s

.globl _start
_start:
    bl one
    b .

build everything.

% arm-none-eabi-gcc -O2 -c one.c -o one.o
% arm-none-eabi-gcc -O2 -c two.c -o two.o
% touch start.s
% arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c one.c -o one.o
% arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c two.c -o two.o
% arm-none-eabi-as start.s -o start.o
% arm-none-eabi-ld -Ttext=0x10000000 start.o one.o two.o -o onetwo.elf

now let's see ...

arm-none-eabi-objdump -D start.o
...
00000000 <_start>:
   0:   ebfffffe    bl  0 <one>
   4:   eafffffe    b   4 <_start+0x4>

/, , , 0, , , , .

00000000 <one>:
   0:   e92d4008    push    {r3, lr}
   4:   e3a00005    mov r0, #5
   8:   e3a01006    mov r1, #6
   c:   ebfffffe    bl  0 <two>
  10:   e59f300c    ldr r3, [pc, #12]   ; 24 <one+0x24>
  14:   e5933000    ldr r3, [r3]
  18:   e0800003    add r0, r0, r3
  1c:   e8bd4008    pop {r3, lr}
  20:   e12fff1e    bx  lr
  24:   00000000    andeq   r0, r0, r0

glob . , , , , glob -.data not.text.

00000000 <two>:
   0:   e59f3010    ldr r3, [pc, #16]   ; 18 <two+0x18>
   4:   e2811007    add r1, r1, #7
   8:   e3a02005    mov r2, #5
   c:   e0810000    add r0, r1, r0
  10:   e5832000    str r2, [r3]
  14:   e12fff1e    bx  lr
  18:   00000000    andeq   r0, r0, r0

.data , .data , .

, gnu linker , _start (main - , , , ). script, gnu , , , . ...

10000000 <_start>:
10000000:   eb000000    bl  10000008 <one>
10000004:   eafffffe    b   10000004 <_start+0x4>

10000008 <one>:
10000008:   e92d4008    push    {r3, lr}
1000000c:   e3a00005    mov r0, #5
10000010:   e3a01006    mov r1, #6
10000014:   eb000005    bl  10000030 <two>
10000018:   e59f300c    ldr r3, [pc, #12]   ; 1000002c <one+0x24>
1000001c:   e5933000    ldr r3, [r3]
10000020:   e0800003    add r0, r0, r3
10000024:   e8bd4008    pop {r3, lr}
10000028:   e12fff1e    bx  lr
1000002c:   1000804c    andne   r8, r0, ip, asr #32

10000030 <two>:
10000030:   e59f3010    ldr r3, [pc, #16]   ; 10000048 <two+0x18>
10000034:   e2811007    add r1, r1, #7
10000038:   e3a02005    mov r2, #5
1000003c:   e0810000    add r0, r1, r0
10000040:   e5832000    str r2, [r3]
10000044:   e12fff1e    bx  lr
10000048:   1000804c    andne   r8, r0, ip, asr #32

Disassembly of section .bss:

1000804c <__bss_start>:
1000804c:   00000000    andeq   r0, r0, r0

start.o, , , , . . 8 , one.o 0x10000008. , bl start.s , (_start + 8, pc , , pc + 0 - )

one.o , , , two.o, , .bss not.data, .

0x10000030, bl () , - glob 1000804c ( , ram , gnu- - ). , , , , (), ().

, () , (), , , , . , , , , , , , . pc. , bl. gnu- , , , ( , ).

, , , ... . . , , C/++. Gnu- . , , ( ). , , ( ), . / . , . , , two() , pc (, 0xF0000000), , , : , /, , gnu linker . - , . pc, , , , , - , , pc ( 0x10000000 0xF0000000, ). , , , , . , , , , , . -, pc-relative, , ( ).

gyrations esp , x86, . , , . , gnu.

test.s

   ldr r1,locdat
   nop
   nop
   nop
   nop
   nop
   b over
locdat: .word 0x12345678
top:
    nop
    nop
    nop
    nop
    nop
    nop
over:
    b top

00000000 <locdat-0x1c>:
   0:   e59f1014    ldr r1, [pc, #20]   ; 1c <locdat>
   4:   e1a00000    nop         ; (mov r0, r0)
   8:   e1a00000    nop         ; (mov r0, r0)
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   e1a00000    nop         ; (mov r0, r0)
  14:   e1a00000    nop         ; (mov r0, r0)
  18:   ea000006    b   38 <over>

0000001c <locdat>:
  1c:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

00000020 <top>:
  20:   e1a00000    nop         ; (mov r0, r0)
  24:   e1a00000    nop         ; (mov r0, r0)
  28:   e1a00000    nop         ; (mov r0, r0)
  2c:   e1a00000    nop         ; (mov r0, r0)
  30:   e1a00000    nop         ; (mov r0, r0)
  34:   e1a00000    nop         ; (mov r0, r0)

00000038 <over>:
  38:   eafffff8    b   20 <top>

. - , , .

- , . , , , , .

+10

All Articles