石家庄建设网站公司,恩施网站建设教程,dedecms网站迁移,网站编辑外包目录链接脚本的简介以及简单编写编写本试验的链接脚本链接脚本的简介以及简单编写
链接脚本描述了要链接的文件#xff0c;以及链接顺序、链接首地址。
在博文ARM#xff08;IMX6U#xff09;裸机C语言版本LED驱动实验中#xff0c;我们在编译过程中使用Makefile 来链接代…
目录链接脚本的简介以及简单编写编写本试验的链接脚本链接脚本的简介以及简单编写
链接脚本描述了要链接的文件以及链接顺序、链接首地址。
在博文ARMIMX6U裸机C语言版本LED驱动实验中我们在编译过程中使用Makefile 来链接代码其中使用了如下语句
arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^上面语句中我们是通过“-Ttext”来指定链接地址是 0X87800000 的这样的话所有的文件都会链接到以 0X87800000 为起始地址的区域。
有时候我们很多文件需要链接到指定的区域或者叫做段里面比如在 Linux 里面初始化函数就会放到 init 段里面。因此我们需要能够自定义一些段这些段的起始地址我们可以自由指定同样的我们也可以指定一个文件或者函数应该存放到哪个段里面去。
要完成这个功能我们就需要使用到链接脚本看名字就知道链接脚本主要用于链接的用于描述文件应该如何被链接在一起形成最终的可执行文件。其主要目的是描述输入文件中的段如何被映射到输出文件中并且控制输出文件中的内存排布。比如我们编译生成的文件一般都包含 text 段、 data 段等等。
链接脚本的语法很简单就是编写一系列的命令这些命令组成了链接脚本每个命令是一个带有参数的关键字或者一个对符号的赋值可以使用分号分隔命令。像文件名之类的字符串可以直接键入也可以使用通配符“*”。最简单的链接脚本可以只包含一个命令“SECTIONS”,我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、 data、 bss 和 rodata 这四个段内假设现在的代码要被链接到 0X10000000 这个地址数据要被链接到 0X30000000 这个地方下面就是完成此功能的最简单的链接脚本
创建后缀名为.lds的文件
SECTIONS{. 0X10000000;.text : {*(.text)}. 0X30000000;.data ALIGN(4) : { *(.data) }.bss ALIGN(4) : { *(.bss) }}第 1 行我们先写了一个关键字“SECTIONS”后面跟了一个大括号这个大括号和第 7 行的大括号是一对这是必须的。看起来就跟 C 语言里面的函数一样。
第 2 行对一个特殊符号“.”进行赋值“.”在链接脚本里面叫做定位计数器默认的定位计数器为 0。我们要求代码链接到以 0X10000000 为起始地址的地方因此这一行给“.”赋值0X10000000表示以 0X10000000 开始后面的文件或者段都会以 0X10000000 为起始地址开始链接。
第 3 行的“.text”是段名代码段后面的冒号是语法要求冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件“(.text)”中的“”是通配符表示所有输入文件的.text段都放到“.text”中。
第 4 行我们的要求是数据放到 0X30000000 开始的地方所以我们需要重新设置定位计数器“.”将其改为 0X30000000。如果不重新设置的话会怎么样假设“.text”段大小为 0X10000那么接下来的.data 段开始地址就是 0X100000000X100000X10010000这明显不符合我们的要求。所以我们必须调整定位计数器为 0X30000000。
第 5 行跟第 3 行一样定义了一个名为“.data”的段数据段然后所有文件的“.data”段都放到这里面。但是这一行多了一个“ALIGN(4)”这是什么意思呢这是用来对“.data”这个段的起始地址做字节对齐的 ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被 4 整除一般常见的都是 ALIGN(4)或者 ALIGN(8)也就是 4 字节或者 8 字节对齐。
第 6 行定义了一个“.bss”段bss数据段x表示定义了但是还没有初始化的数据段所有文件中的“.bss”数据都会被放到这个里面“.bss”数据就是那些定义了但是没有被初始化的变量。
编写本试验的链接脚本 上面就是链接脚本最基本的语法格式我们接下来就按照这个基本的语法格式来编写我们本试验的链接脚本我们本试验的链接脚本要求如下 ①、链接起始地址为0X87800000。 ②、start.o 要被链接到最开始的地方因为start.o 里面包含这第一个要执行的命令。 根据要求在Makefile 同目录下新建一个名为“imx6ul.lds”的文件然后在此文件里面输入如下所示代码
imx6u.lds
SECTIONS{. 0X87800000;.text :{start.omain.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : { *(.data) }__bss_start .;.bss ALIGN(4) : { *(.bss) *(COMMON) }__bss_end .;}上述代码“text :”中的冒号要和text段名空格隔开。 上面的链接脚本文件和示例代码基本一致的。
第2 行设置定位计数器为0X87800000因为我们的链接地址就是0X87800000。
第5 行设置链接到开始位置的文件为start.o因为start.o 里面包含着第一个要执行的指令所以一定要链接到最开始的地方。
第6行是main.o这个文件其实可以不用写出来因为main.o 的位置就无所谓了可以由编译器自行决定链接位置。
第9行rodata 表示read only只读数据段。
在第11、13 行有“__bss_start”和“__bss_end”这两个东西这个是什么呢“__bss_start”和“__bss_end”是符号第11、13 这两行其实就是对这两个符号进行赋值其值为定位符“.”这两个符号用来保存.bss 段的起始地址和结束地址。 前面说了.bss 段是定义了但是没有被初始化的变量我们需要手动对.bss 段的变量清零的因此我们需要知道.bss 段的起始和结束地址这样我们直接对这段内存赋0 即可完成清零。通过第11、13 行代码.bss 段的起始地址和结束地址就保存在了“__bss_start”和“__bss_end”中我们就可以直接在汇编或者C 文件里面使用这两个符号。
编写完这个链接脚本怎么去使用这个链接脚本呢
在Makefile文件里面添加进来就OK了如图
最后查看反汇编文件发现start已经链接到指定的位置当中了。