您的位置 首页 5G

arm-linux衔接以及衔接脚本

前言:armlinux的连接工具可以使用arm-linux-ld,在进行连接时可以使用-T命令采用脚本控制,如不指明脚本,则使用默认的脚本文件,参见ar…

前语:arm linux的衔接东西能够运用arm-linux-ld,在进行衔接时能够运用-T指令选用脚本操控,如不指明脚本,则运用默许的脚本文件,拜见arm-linux-ld的缺省linker script。

一.方针文件格局与类型

GNU C compiler依据源文件的后缀名来对文件进行预处理、汇编或编译操作。在编译链接时,生成的方针文件都是ELF格局的(可履行链接格局,Executable and Linking Format)。Object文件格局有三种类型:

(1)可重定位(relocatable)文件:用来和其他的object文件一同链接为一个可履行文件(executable)或一个同享文件(.so文件,shared object)。

(2)可履行(executable)文件;

(3)同享方针文件(shared object file):用于被下面的两个链接器链接。一是链接编辑器(ld),能够和其他的relocatable或shared object file来创立其他的方针文件,例如.so同享库(可用file指令检查其特点);二是动态链接器,联合一个可履行文件和其他的shared object file来创立一个进程映像。

二.链接与链接脚本

链接器ld把object文件中的每个section都作为一个全体,为其分配运转的地址(memory layout),这个进程便是重定位(relocation);终究把一切方针文件合并为一个方针文件。

链接经过一个linker script来操控,这个脚本描绘了输入文件的sections到输出文件的映射,以及输出文件的memory layout。

因而,linker总会运用一个linker script,假如不特别指定,则运用默许的script;能够运用‘-T’指令行选项来指定一个linker script。

1. 映像文件的输入段与输出段

linker把多个输入文件合并为一个输出文件。输出文件和输入文件都是方针文件(object file),输出文件一般被称为可履行文件(executable)。

每个方针文件都有一系列section,输入文件的section称为input section,输出文件的section则称为output section。

一个section能够是loadable的,即输出文件运转时需要将这样的section加载到memory(类似于RO&RW段);也能够是allocatable的,这样的section没有任何内容,某些时分用0对相应的memory区域进行初始化(类似于ZI段);假如一个section既非loadable也非allocatable,则它一般包括的是调试信息。

每个loadable或allocatable的output section都有两个地址,一是VMA(virtual memory address),是该section的运转时域地址;二是LMA(load memory address),是该section的加载时域地址。

能够经过objdump东西附加-h选项来检查方针文件中的sections。

2. 简略的Linker script

(1) SECTIONS指令:

The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.

指令格局如下:

SECTIONS

{

sections-command

sections-command

……

}

其间sections-command能够是ENTRY指令,符号赋值,输出段描绘,也能够是overlay描绘。

(2)地址计数器‘.’(location counter):

该符号只能用于SECTIONS指令内部,初始值为‘0’,能够对该符号进行赋值,也能够运用该符号进行核算或赋值给其他符号。它会主动依据SECTIONS指令内部所描绘的输出段的巨细来核算当时的地址。

(3)输出段描绘(output section description):

前面说到在SECTIONS指令中能够作输出段描绘,描绘的格局如下:

sectionname [address] [(type)] : [AT(lma)]

{

output-section-command

output-section-command

} [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp]

许多附加选项是用不到的。其间的output-section-command又能够是符号赋值,输入段描绘,要直接包括的数据值,或许某一特定的输出段关键字。

3. 举例

下面看一个常用的用于涣散加载(即存储或加载地址<加载域>和链接或运转地址<运转域>不同)的格局:

SECTIONS {

secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region :phdr =fill

}

secname和contents是有必要的,其他的都是可选的。下面挑几个常用的看看:
(1)secname:段名

(2)contents:决议哪些内容放在本段,能够是整个方针文件,也能够是方针文件中的某段(代码段、数据段等)

(3)start:本段衔接(运转)的地址,假如没有运用AT(ldadr),本段存储的地址也是start。GNU网站上说start能够用恣意一种描绘地址的符号来描绘。

(4)AT(ldadr):界说本段存储(加载)的地址。

SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}

以上,head.o放在0x00000000地址开端处,init.o放在head.o后边,他们的运转地址也是0x00000000,即衔接和存储地址相同(没有AT指定);main.o放在4096(0x1000,是AT指定的,存储地址)开端处,可是它的运转地址在0x30000000,运转之前需要从0x1000(加载处)复制到0x30000000(运转处),此进程也就用到了读取Nand flash。

编写好的.lds文件,在用arm-linux-ld衔接指令时带-Tfilename来调用履行,如
arm-linux-ld –Tnand.lds x.o y.o –o xy.o。也用-Ttext参数直接指定衔接地址,如
arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o。

4. ARM汇编中完成跳转

因为会运用涣散加载,因而在运用汇编完成跳转时应该留意。ARM汇编中,常有两种跳转办法:b跳转指令、ldr指令向PC赋值。

(1) b step1 :b跳转指令是相对跳转,依靠当时PC的值,偏移量是经过该指令自身的bit[23:0]算出来的,这使得运用b指令的程序不依靠于要跳到的代码的方位,只看指令自身。

(2) ldr pc, =step1 :该指令是从内存中的某个方位(step1)读出数据并赋给PC,相同依靠当时PC的值,可是偏移量是那个方位(step1)的衔接地址(运转时的地址),因而不论终究程序在什么地方运转,所得到的都是相同的地址(肯定地址),所以能够用它完成从Flash到RAM的程序跳转。

参考资料:

1.arm-linuxbootloader准备之GNUld机理,http://blog.21ic.com/user1/1028/archives/2008/47653.html

2. 对.lds衔接脚本文件的剖析,http://blog.chinaunix.net/u1/58780/showart.php?id=462971

3. 用GNU东西开发根据ARM的嵌入式体系,http://blog.163.com/liren0@126/blog/static/32897598200821211144696/

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/5g/275661.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部