10259|1

95

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

ARM arm-ld链接器的作用 [复制链接]

如果用过arm交叉编译器,一定看过
arm-ld, arm-as, arm-gcc, arm-nm等一系列工具,它们的用途是干什么的呢?
(1)arm-as 用于将 xxx.s 汇编文件编译为 xxx.o 文件
  1. <font size="4">eg : arm-as -o add.o  add.s</font>
复制代码


(2)在写多文件工程的时候,每个汇编文件被 arm-as工具单独编译为.o文件,c文件用arm-gcc编译
而arm-ld则将所有的xxx.o 文件链接为二进制执行文件,因此称为链接器
有三种可执行文件:一种是.elf,一种是.bin,.hex是一种特殊的可执行文件

链接器有两个作用:
1.符号解析(Symbol Resolution)
2.重定向(Relocating)


下面以汇编文件为例来讲解:
汇编语句的语法如下:
  1. <font size="4">label:    instruction         @ comment</font>
复制代码

label 为标签, @ 后面是注释语句
instruction是执行的指令
一个简单的加法的例子如下:
  1. <font size="4">        .text
  2. start:                            @ Label, not really required
  3.         mov   r0, #5                    @ Load register r0 with the value 5
  4.         mov   r1, #4                    @ Load register r1 with the value 4
  5.         add   r2, r1, r0                 @ Add r0 and r1 and store in r2

  6. stop:   b stop                   @ Infinite loop to stop execution</font>
复制代码

1.符号解析
在单文件工程中,在生成目标文件时,所有指向labels的引用都被它们相应的地址所代替,这是由汇编器(assembler)实现。
但是在多文件工程里面,如果引用的标签是在另一个文件,那么汇编器无法解析,它会将这个标签标记为"unresolved"。当所有的xxx.o传递给链接器的时候,链接器通过具有这个标签的文件来决定这些引用的值。
一个求和的例子如下:
main.s 文件
  1. <font size="4">        .text
  2.         b start                            @ Skip over the data
  3. arr:    .byte 10, 20, 25         @ Read-only array of bytes
  4. eoa:                                @ Address of end of array + 1

  5.         .align
  6. start:
  7.         ldr   r0, =arr                       @ r0 = &arr
  8.         ldr   r1, =eoa                      @ r1 = &eoa

  9.         bl    sum                              @ Invoke the sum subroutine

  10. stop:   b stop</font>
复制代码
这里arr 是一个数组。指令首先调到 start,  r0寄存器装载arr数组的首地址, r1装载 eoa的地址(其实就是数组的末地址+1),然后跳转到 sum,这里使用bl ,是可返回跳转,lr寄存器会记录当前的位置
sum-sub.s 文件
  1. <font size="4">        @ Args
  2.         @ r0: Start address of array
  3.         @ r1: End address of array
  4.         @
  5.         @ Result
  6.         @ r3: Sum of Array

  7.         .global sum

  8. sum:    mov   r3, #0                    @ r3 = 0
  9. loop:   ldrb  r2, [r0], #1             @ r2 = *r0++    ; Get array element
  10.         add   r3, r2, r3                 @ r3 += r2      ; Calculate sum
  11.         cmp   r0, r1                     @ if (r0 != r1) ; Check if hit end-of-array
  12.         bne   loop                        @    goto loop  ; Loop
  13.         mov   pc, lr                      @ pc = lr       ; Return when done</font>
复制代码
这里的 sum 里面有一个 Loop循环,结束的条件就是r0 = r1, loop循环里面就是让 r2 = *r0++, r3 += r2
结束之后,调回到lr寄存器记录的位置。


这里.global 的作用声明label对其他文件可见.
在C语言里面,所有变量(variables)在函数外面声明对其他文件是可见的,除非显式声明为static
而在汇编语言里面,所有的标签(label)都是只对本文件可见,除非使用.global显式声明。


使用nm工具可以查看xxx.o文件的所有符号标签
  1. <font size="4">$ arm-nm main.o
  2. 00000004 t arr
  3. 00000007 t eoa
  4. 00000008 t start
  5. 00000018 t stop
  6.                U sum
  7. $ arm-nm sum-sub.o
  8. 00000004 t loop
  9. 00000000 T sum</font>
复制代码
这里  "t" 表示 这个符号是被定义的
"U" 表示这个符号没有被定义(undefined)
"T" 表示这个符号是全局的(.global)


2. 重定向
重定向是改变已经分配给label的地址的过程,这包含链接所有的标签引用来反映新的分配的地址
重定向执行的原因有两个: 段合并(section merging)和段放置(section placement)
要想了解重定向的过程吗,首先得了解 段(section)的概念
代码和数据有不同的运行要求。比如,代码是放置在只读Memory,而数据要求可读可写的Memory
如果代码和数据没有交错分布在memory里面,这就很方便实现。
基于这一目的,我们将program 分成一个一个的段
大部分的program至少有两个段,一个 .text 段用于代码,一个.data段用于数据
汇编器通过 xxx.s文件的  .text 和 .data 来识别要放到哪一个段里面

想象一个段是一个篮子。当汇编器一条一条指令编译的时候,它根据指示将 code 和data 放到各自的篮子里面。
如图所示


(1)段合并:
在执行多文件工程时,具有相同名字的段(比如: .text)可能会出现。链接器负责将输入文件(xxx.o)的段合并。默认情况下,每个文件相同名字的段连续放置,并且标签引用指向新的地址。
  1. <font size="4">$ arm-nm main.o
  2. 00000004 t arr
  3. 00000007 t eoa
  4. 00000008 t start
  5. 00000018 t stop
  6.                U sum
  7. $ arm-nm sum-sub.o
  8. 00000004 t loop ❶
  9. 00000000 T sum
  10. $ arm-ld -Ttext=0x0 -o sum.elf main.o sum-sub.o
  11. $ arm-nm sum.elf
  12. ...
  13. 00000004 t arr
  14. 00000007 t eoa
  15. 00000008 t start
  16. 00000018 t stop
  17. 00000028 t loop ❷
  18. 00000024 T sum</font>
复制代码
还是前面的例子,在经过链接器之后 ,  sum-sub.o 里面 .text段的标签 loop 被放在 main.o .text段的后面地址发生改变。而且main.o里面没有被解析的sum标签被解析为 新的地址


(2)段放置
在段被编译之后,每个段都被假定从地址0开始。每个标签都被分配相对于段起始位置的地址。当最终的可执行文件创建的时候,段的起始地址变为X,那么段里面所有定义的标签地址都增加X。
段放置的效果可以看每个 .o文件和最终的可执行文件的符号表(symbol table)
下面的例子里面我们将.text段放置在 0x100位置
  1. <font size="4">$ arm-none-eabi-as -o sum.o sum.s
  2. $ arm-none-eabi-nm -n sum.o
  3. 00000000 t entry ❶
  4. 00000004 t arr
  5. 00000007 t eoa
  6. 00000008 t start
  7. 00000014 t loop
  8. 00000024 t stop
  9. $ arm-none-eabi-ld -Ttext=0x100 -o sum.elf sum.o ❷
  10. $ arm-none-eabi-nm -n sum.elf
  11. 00000100 t entry ❸
  12. 00000104 t arr
  13. 00000107 t eoa
  14. 00000108 t start
  15. 00000114 t loop
  16. 00000124 t stop
  17. ...</font>
复制代码
注1 : xxx.o 文件的段的起始位置是从0开始的
    2: 在经过链接器之后, .text段被放置在0x100处
    3 :  所有的标签都被重新解析和定向,放置在新的位置


下面是整个过程


relocation.png (86.27 KB, 下载次数: 0)

relocation.png
此帖出自ARM技术论坛

最新回复

多谢楼主分享  详情 回复 发表于 2016-6-6 22:05

赞赏

2

查看全部赞赏

点赞 关注
 

回复
举报

6423

帖子

17

TA的资源

版主

沙发
 
多谢楼主分享
此帖出自ARM技术论坛
 
个人签名training
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表