arm-none-eabi-ld是否重写bl指令? [英] Does arm-none-eabi-ld rewrite the bl instruction?

查看:414
本文介绍了arm-none-eabi-ld是否重写bl指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解为什么一些Cortex-M0代码在链接与未链接时表现不同。在这两种情况下,它都被加载到 0x20000000 。尽管我尽最大努力通过将 -fPIC 传递给编译器来生成位置无关的代码,但是显示了 bl 指令在代码通过链接器后会有所不同。我是否正确地阅读了这篇文章,是否仅仅是ARM Thumb中链接器工作的一部分,并且有没有更好的方法来生成一个与位置无关的函数调用?

链接:

  20000000:
20000000:0003 movs r3,r0
20000002:4852 ldr r0,[pc, #328]
20000004:4685 mov sp,r0
20000006:0018 movs r0,r3
20000008:f000 f802 bl 20000010
2000000c:46c0 nop; (mov r8,r8)
2000000e:46c0 nop; (mov r8,r8)

取消关联:

  00000000:
0:0003 movs r3,r0
2:4852 ldr r0,[pc,#328]
4:4685 mov sp, r0
6:0018 movs r0,r3
8:f7ff fffe bl 10
c:46c0 nop; (mov r8,r8)
e:46c0 nop; (mov r8,r8)


解决方案

start.s



  .globl _start 
_start:
.word 0x20001000
.word重置
。 word hang
.word hang

.thumb

.thumb_func
reset:
bl b $ not
.thumb_func
hang:
b。

notmain.c

  unsigned int x; 

unsigned int fun(unsigned int);
void notmain(void)
{
x = fun(x + 5);
}

fun.c

  unsigned int y; 
unsigned int fun(unsigned int z)
{
return(y + z + 1);



 MEMORY 
{
ram:ORIGIN = 0x20000000,LENGTH = 0x1000
}

SECTIONS
{
.text:{*(.text *)}> ram
.bss:{*(.bss *)}> ram
}

建立

  arm-none-eabi-as start.s -o start.o 
arm-none-eabi-gcc -fPIC -O2 -c -mthumb fun.c -o fun .o
arm-none-eabi-gcc -fPIC -O2 -c -mthumb notmain.c -o notmain.o
arm-none-eabi -ld -T memmap start.o notmain.o fun .o -o so.elf

产生

  20000000< _start> ;: 
20000000:20001000 andcs r1,r0,r0
20000004:20000011 andcs r0,r0,r1,lsl r0
20000008:20000015 andcs r0,r0,r5,lsl r0
2000000c:20000015 andcs r0,r0,r5,lsl r0

20000010
20000010:f000 f802 bl 20000018< notmain>

20000014< hang> ;:
20000014:e7fe b.n 20000014< hang>
...

20000018< notmain> ;:
20000018:b510 push {r4,lr}
2000001a:4b06 ldr r3,[pc,#24] ; (20000034< notmain + 0x1c>)
2000001c:4a06 ldr r2,[pc,#24]; (20000038< notmain + 0x20>)
2000001e:447b add r3,pc
20000020:589c ldr r4,[r3,r2]
20000022:6823 ldr r3,[r4,#0 ]
20000024:1d58增加r0,r3,#5
20000026:f000 f809 bl 2000003c< fun>
2000002a:6020 str r0,[r4,#0]
2000002c:bc10 pop {r4}
2000002e:bc01 pop {r0}
20000030:4700 bx r0
20000032:46c0 nop; (mov r8,r8)
20000034:00000032 andeq r0,r0,r2,lsr r0
20000038:00000000 anddeq r0,r0,r0

2000003c
2000003c:4b03 ldr r3,[pc,#12]; (2000004c< fun + 0x10>)
2000003e:4a04 ldr r2,[pc,#16]; (20000050< fun + 0x14>)
20000040:447b add r3,pc
20000042:589b ldr r3,[r3,r2]
20000044:681b ldr r3,[r3,#0 ]
20000046:3301增加r3,#1
20000048:1818增加r0,r3,r0
2000004a:4770 bx lr
2000004c:00000010 andeq r0,r0,r0,lsl r0
20000050:00000004 andeq r0,r0,r4

反汇编section .got:

20000054< .got> ;:
20000054:20000068 andcs r0,r0,r8,rrx
20000058:2000006c andcs r0,r0,ip,rrx

反汇编section .got.plt:

2000005c< _GLOBAL_OFFSET_TABLE_>:
...

反汇编section .bss:

20000068< x>:
20000068:00000000 andeq r0,r0, r0

2000006c< y> ;:
2000006c:00000000 andeq r0,r0,r0

当它想要找到全局变量x它看起来所做的事情是需要的程序计数器和链接器提供/修改的偏移量0x32,并使用它来查找全局偏移表中的条目。然后从中找到一个偏移量来找到X.对于Y来说是一样的。所以看起来当你重新定位时,你将需要在运行时或加载时间修改全局偏移量表。



如果我摆脱了那些全局变量,除了硬编码而不是PIC的矢量表(无论如何编译),这都是独立的位置。

  20000000< _start> ;: 
20000000:20001000 andcs r1,r0,r0
20000004:20000011 andcs r0,r0,r1,lsl r0
20000008: 20000015 andcs r0,r0,r5,lsl r0
2000000c:20000015 andcs r0,r0,r5,lsl r0

20000010< reset> ;:
20000010:f000 f802 bl 20000018 < notmain>

20000014< hang> ;:
20000014:e7fe b.n 20000014< hang>
...

20000018< notmain> ;:
20000018:b508 push {r3,lr}
2000001a:2005 movs r0,#5
2000001c:f000 f804 bl 20000028< fun>
20000020:3006增加r0,#6
20000022:bc08 pop {r3}
20000024:bc02 pop {r1}
20000026:4708 bx r1

20000028< fun> ;:
20000028:3001增加r0,#1
2000002a:4770 bx lr

返回到此版本

  unsigned int y; 
unsigned int fun(unsigned int z)
{
return(y + z + 1);

$ / code>

持仓

  00000000< fun>:
0:4b03 ldr r3,[pc,#12]; (10< fun + 0x10>)
2:4a04 ldr r2,[pc,#16]; (14
4:447b add r3,pc
6:589b ldr r3,[r3,r2]
8:681b ldr r3,[r3,#0 ]
a:3301增加r3,#1
c:1818增加r0,r3,r0
e:4770 bx lr
10:00000008 andeq r0,r0,r8
14 :00000000 andeq r0,r0,r0

不是位置独立的

  00000000< fun>:
0:4b02 ldr r3,[pc,#8]; (c< fun + 0xc>)
2:681b ldr r3,[r3,#0]
4:3301增加r3,#1
6:1818增加r0,r3,r0
8:4770 bx lr
a:46c0 nop; (mov r8,r8)
c:00000000 andeq r0,r0,r0

做更多的工作来访问外部变量。一些工作因为它是外部的而不是那么多。链接器将填写所需的项目,以使其工作...链接...



该elf文件包含链接器知道要做到这一点的信息。

 位于偏移量0x1a4的重定位部分'.rel.text'包含2个条目:
偏移量信息类型Sym.Value Sym 。名称
00000010 00000a19 R_ARM_BASE_PREL 00000000 _GLOBAL_OFFSET_TABLE_
00000014 00000b1a R_ARM_GOT_BREL 00000004 y

 重定位部分'.rel.text'在偏移量0x174包含1个条目:
偏移量信息类型符号值符号。名称
0000000c 00000a02 R_ARM_ABS32 00000004 y

notmain have these PIC

 位于偏移量0x1cc处的重定位部分'.rel.text'包含3个条目:
偏移量信息类型符号值符号。名称
0000000e 00000a0a R_ARM_THM_CALL 00000000 fun
0000001c 00000b19 R_ARM_BASE_PREL 00000000 _GLOBAL_OFFSET_TABLE_
00000020 00000c1a R_ARM_GOT_BREL 00000004 x

并且没有。

 重定位部分'.rel.text'在偏移量0x198包含2个条目:
偏移量信息类型Sym.Value Sym。 Name
00000008 00000a0a R_ARM_THM_CALL 00000000 fun
00000014 00000b02 R_ARM_ABS32 00000004 x

工具链正在做它的工作,你不需要重新做它的工作。并注意这与手臂或拇指无关。无论何时您使用对象和链接器模型并允许来自对象的外部项目,链接器都必须对其进行修补以将代码粘合在一起。这就是它的工作原理。


I'm trying to understand why some Cortex-M0 code behaves differently when it is linked versus unlinked. In both cases it is loaded to 0x20000000. It looks like despite my best efforts to generate position independent code by passing -fPIC to the compiler, the bl instruction appears to differ after the code has passed through the linker. Am I reading this correctly, is that just a part of the linker's job in ARM Thumb, and is there a better way to generate a position independent function call?

Linked:

20000000:
20000000:       0003            movs    r3, r0
20000002:       4852            ldr     r0, [pc, #328]
20000004:       4685            mov     sp, r0
20000006:       0018            movs    r0, r3
20000008:       f000 f802       bl      20000010
2000000c:       46c0            nop                     ; (mov r8, r8)
2000000e:       46c0            nop                     ; (mov r8, r8)

Unlinked:

00000000:
   0:   0003            movs    r3, r0
   2:   4852            ldr     r0, [pc, #328]
   4:   4685            mov     sp, r0
   6:   0018            movs    r0, r3
   8:   f7ff fffe       bl      10
   c:   46c0            nop                     ; (mov r8, r8)
   e:   46c0            nop                     ; (mov r8, r8)

解决方案

start.s

.globl _start
_start:
.word 0x20001000
.word reset
.word hang
.word hang

.thumb

.thumb_func
reset:
    bl notmain
.thumb_func
hang:
    b .

notmain.c

unsigned int x;

unsigned int fun ( unsigned int );
void notmain ( void )
{
    x=fun(x+5);
}

fun.c

unsigned int y;
unsigned int fun ( unsigned int z )
{
    return(y+z+1);
}

memmap

MEMORY
{
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > ram
    .bss : { *(.bss*) } > ram
}

build

arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -fPIC -O2 -c -mthumb fun.c -o fun.o
arm-none-eabi-gcc -fPIC -O2 -c -mthumb notmain.c -o notmain.o
arm-none-eabi-ld -T memmap start.o notmain.o fun.o -o so.elf

produces

20000000 <_start>:
20000000:   20001000    andcs   r1, r0, r0
20000004:   20000011    andcs   r0, r0, r1, lsl r0
20000008:   20000015    andcs   r0, r0, r5, lsl r0
2000000c:   20000015    andcs   r0, r0, r5, lsl r0

20000010 <reset>:
20000010:   f000 f802   bl  20000018 <notmain>

20000014 <hang>:
20000014:   e7fe        b.n 20000014 <hang>
    ...

20000018 <notmain>:
20000018:   b510        push    {r4, lr}
2000001a:   4b06        ldr r3, [pc, #24]   ; (20000034 <notmain+0x1c>)
2000001c:   4a06        ldr r2, [pc, #24]   ; (20000038 <notmain+0x20>)
2000001e:   447b        add r3, pc
20000020:   589c        ldr r4, [r3, r2]
20000022:   6823        ldr r3, [r4, #0]
20000024:   1d58        adds    r0, r3, #5
20000026:   f000 f809   bl  2000003c <fun>
2000002a:   6020        str r0, [r4, #0]
2000002c:   bc10        pop {r4}
2000002e:   bc01        pop {r0}
20000030:   4700        bx  r0
20000032:   46c0        nop         ; (mov r8, r8)
20000034:   00000032    andeq   r0, r0, r2, lsr r0
20000038:   00000000    andeq   r0, r0, r0

2000003c <fun>:
2000003c:   4b03        ldr r3, [pc, #12]   ; (2000004c <fun+0x10>)
2000003e:   4a04        ldr r2, [pc, #16]   ; (20000050 <fun+0x14>)
20000040:   447b        add r3, pc
20000042:   589b        ldr r3, [r3, r2]
20000044:   681b        ldr r3, [r3, #0]
20000046:   3301        adds    r3, #1
20000048:   1818        adds    r0, r3, r0
2000004a:   4770        bx  lr
2000004c:   00000010    andeq   r0, r0, r0, lsl r0
20000050:   00000004    andeq   r0, r0, r4

Disassembly of section .got:

20000054 <.got>:
20000054:   20000068    andcs   r0, r0, r8, rrx
20000058:   2000006c    andcs   r0, r0, ip, rrx

Disassembly of section .got.plt:

2000005c <_GLOBAL_OFFSET_TABLE_>:
    ...

Disassembly of section .bss:

20000068 <x>:
20000068:   00000000    andeq   r0, r0, r0

2000006c <y>:
2000006c:   00000000    andeq   r0, r0, r0

when it wants to find the global variable x what it appears to have done is it takes the program counter and a linker supplied/modfied offset 0x32 and uses that to find the entry in the global offset table. then takes an offset from that to find X. same for Y. so it appears that when you relocate you will need to modify the global offset table at runtime or load time depending.

If I get rid of those global variables, other than the vector table which is hardcoded and not PIC (and wasnt compiled anyway), this is all position independent.

20000000 <_start>:
20000000:   20001000    andcs   r1, r0, r0
20000004:   20000011    andcs   r0, r0, r1, lsl r0
20000008:   20000015    andcs   r0, r0, r5, lsl r0
2000000c:   20000015    andcs   r0, r0, r5, lsl r0

20000010 <reset>:
20000010:   f000 f802   bl  20000018 <notmain>

20000014 <hang>:
20000014:   e7fe        b.n 20000014 <hang>
    ...

20000018 <notmain>:
20000018:   b508        push    {r3, lr}
2000001a:   2005        movs    r0, #5
2000001c:   f000 f804   bl  20000028 <fun>
20000020:   3006        adds    r0, #6
20000022:   bc08        pop {r3}
20000024:   bc02        pop {r1}
20000026:   4708        bx  r1

20000028 <fun>:
20000028:   3001        adds    r0, #1
2000002a:   4770        bx  lr

back to this version

unsigned int y;
unsigned int fun ( unsigned int z )
{
    return(y+z+1);
}

position independent

00000000 <fun>:
   0:   4b03        ldr r3, [pc, #12]   ; (10 <fun+0x10>)
   2:   4a04        ldr r2, [pc, #16]   ; (14 <fun+0x14>)
   4:   447b        add r3, pc
   6:   589b        ldr r3, [r3, r2]
   8:   681b        ldr r3, [r3, #0]
   a:   3301        adds    r3, #1
   c:   1818        adds    r0, r3, r0
   e:   4770        bx  lr
  10:   00000008    andeq   r0, r0, r8
  14:   00000000    andeq   r0, r0, r0

not position independent

00000000 <fun>:
   0:   4b02        ldr r3, [pc, #8]    ; (c <fun+0xc>)
   2:   681b        ldr r3, [r3, #0]
   4:   3301        adds    r3, #1
   6:   1818        adds    r0, r3, r0
   8:   4770        bx  lr
   a:   46c0        nop         ; (mov r8, r8)
   c:   00000000    andeq   r0, r0, r0

the code has to do a bit more work to access the external variable. position dependent, some work because it is external but not as much. the linker will fill in the required items to make it work...to link it...

the elf file contains information for the linker to know to do this.

Relocation section '.rel.text' at offset 0x1a4 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000010  00000a19 R_ARM_BASE_PREL   00000000   _GLOBAL_OFFSET_TABLE_
00000014  00000b1a R_ARM_GOT_BREL    00000004   y

or

Relocation section '.rel.text' at offset 0x174 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000000c  00000a02 R_ARM_ABS32       00000004   y

notmain had these PIC

Relocation section '.rel.text' at offset 0x1cc contains 3 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000000e  00000a0a R_ARM_THM_CALL    00000000   fun
0000001c  00000b19 R_ARM_BASE_PREL   00000000   _GLOBAL_OFFSET_TABLE_
00000020  00000c1a R_ARM_GOT_BREL    00000004   x

and without.

Relocation section '.rel.text' at offset 0x198 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000008  00000a0a R_ARM_THM_CALL    00000000   fun
00000014  00000b02 R_ARM_ABS32       00000004   x

so in short the toolchain is doing its job, you dont need to re-do its job. And note this has nothing to do with arm or thumb. any time you use the object and linker model and allow for external items from an object the linker has to patch things up to glue the code together. thats just how it works.

这篇关于arm-none-eabi-ld是否重写bl指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆