先来分析一个简单的.lds链接脚本


例1,假如现在有head.c init.c nand.c main.c这4个文件:

1.1 首先创建链接脚本nand.lds:

  1. SECTIONS {
  2. firtst 0x00000000 : { head.o init.o nand.o}
  3. second 0x30000000 : AT() { main.o }
  4. }

SECTIONS { ... }                  用来描述输出文件的内存布局。

这个脚本里规定了两个段,firtst和cecond

0x00000000   0x30000000   

表示链接地址或运行地址,指程序在SRAM、SDRAM实际运行的地址,也就是使PC等于这个地址。

这里指head.o init.o nand.o的加载地址为0,运行地址在0x00000000,main.o运行地址在0x30000000

AT(4096)    

表示加载地址或存储地址,指程序编译后存放的地址,一般存在ROM、FLASH中,也就是运行这个指令时,会先将4096地址~(4096+2048)地址处的内容复制到0x30000000处运行(因为已经初始化了SDRAM以及Nand Flash)。

这里指main.o的加载地址为Nand Flash里的地址4096,运行地址在SDRAM里的地址  0x30000000。

1.2 制作Makefile

  1. objs := head.o init.o nand.o main.o
  2. nand.bin : $(objs)  
  3. arm-linux-ld -Tnand.lds -o nand_elf $^
  4. arm-linux-objcopy -O binary -S nand_elf $@
  5. arm-linux-objdump -D -m arm nand_elf > nand.dis
  6. %.o:%.c
  7. arm-linux-gcc -Wall -c -O2 -o $@ $<
  8. %.o:%.S
  9. arm-linux-gcc -Wall -c -O2 -o $@ $<
  10. clean:
  11. rm -f nand.dis nand.bin nand_elf *.o

其中 objs 是代表的一个变量,表示obj文件,也可以是objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,后面就可以使用$(objs)来使用这个变量了。

$@               目标文件

$^                 所有的依赖文件

$<                 第一个依赖文件

例如: arm-linux-ld -Tnand.lds -o nand_elf $^          <<——  等价于  ——>>    arm-linux-ld  -o nand_elf  head.o init.o nand.o main.o

%.o:%.c                  表示所有的.o文件,依赖于对应的.c文件

%.o:%.S                  表示所有的.o文件,依赖于对应的.S文件


当有多个.o文件时,这时候.lds链接脚本 又该如何安排它们在可执行文件中的顺序?

这里就需要将多个目标文件的.text、.data和.bss等段链接在一起而链接脚本文件是告诉链接器从什么地址开始放置这些段

  • .text:代码段,存放程序执行代码的一块内存
  • .data:读/写数据段,存放已初始的全局变量或静态变量的一块内存
  • .rodata:只读数据段,存放只读数据段,比如全局const变量和#define定义的变量
  • .bss:存放未初始化的全局变量或静态变量,这里的变量存放只是用来预留位置,并不占用空间

常用命令:

ENTRY(SYMBOL);将SYMBOL的值设置成入口地址。一般设置为_start。

OUTPUT(FILENAME); 定义输出文件的名字。可以用它来指定默认的输出文件名称。当然我们一般都用手动-o进行指定,如果我们没有进行手动指定的话,输出文件名称就以这个FILENAME为输出文件名。

STARTUP(filename);指定filename为第一个输入文件。

OUTPUT_FORMAT(default, big, little);定义3种输出文件的格式。若有命令行选项-EB(大端),则使用第二个输出格式,有命令行指定-EL(小端),则使用第三个格式。否则使用默认的default输出格式。

OUT_ARCH(arch);设置输出文件的体系架构

SECTIONS :最重要的,最基本的,也是最主要的命令,它告诉链接器如何把输入文件的各个section输出到目标文件中的各个section中去。


例2:分析 board/100ask24x0/u-boot.lds链接脚本

  1. OUTPUT_ARCH(arm) //设置输出文件的体系架构。
  2. ENTRY(_start) //将_start这个全局符号设置成入口地址。
  3. SECTIONS //输出文件内容布局
  4. {
  5. . = 0x00000000; //指定地址0x00000000
  6.  
  7. . = ALIGN(4); //代码以4字节对齐
  8. .text : //指定.text section段(位于0x00000000)
  9. {
  10. cpu/arm920t/start.o (.text) //添加第一个目标文件: cpu/arm920t/start.o里面的.text代码段
  11. board/100ask24x0/boot_init.o (.text) //添加第二个目标文件: board/100ask24x0/boot_init.o里面的.text代码段
  12. *(.text) // *(.text) 表示添加剩下的全部文件的.text代码段
  13. }
  14.  
  15. . = ALIGN(4);
  16. .rodata : { *(.rodata) } //指定.rodata section段(位于0x00000000+.text section),将所有的.rodata只读数据段合并成一个.rodata只读数据段
  17.  
  18. . = ALIGN(4);
  19. .data : { *(.data) } //指定读写数据段, *(data):添加所有文件的数据段
  20.  
  21. . = ALIGN(4);
  22. .got : { *(.got) } //指定got段,got段是uboot自定义的一个段
  23.  
  24. . = .;
  25. __u_boot_cmd_start = .; //把__u_boot_cmd_start赋值为当前位置, 即起始位置
  26. .u_boot_cmd : { *(.u_boot_cmd) } // u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置
  27. __u_boot_cmd_end = .; // u_boot_cmd段结束位置
  28.  
  29. . = ALIGN(4);
  30. __bss_start = .; //把__bss_start赋值为当前位置,即bss段的开始位置
  31. .bss : { *(.bss) } //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段
  32. _end = .; //把_end赋值为当前位置,即bss段的结束位置
  33. }

  

随机推荐

  1. 实例甜点 Unreal Engine 4迷你教程(4)之用C++实现添加子Widget到VerticalBox中以及ClearChildren

    前置教程: 1. 实例甜点前面的三篇教程: 2. 最好看看笔者前面的一篇关于博文(后记:本来笔者想用C++做DragAndDrop的功能,但是失败了,下面是蓝图实现的方法): http://www.c ...

  2. [js高手之路] es6系列教程 - var, let, const详解

    function show( flag ){ console.log( a ); if( flag ){ var a = 'ghostwu'; return a; } else { console.l ...

  3. ASP.NET Core MVC – Caching Tag Helpers

    简介 缓存可以大大提高应用程序加载时间和响应速度.我们可以使用缓存Tag Helpers缓存不会频繁更改的HTML内容. 在上一篇文章中,我们谈到了Tag Helpers,演示Tag Helpers能 ...

  4. CPUImageRGBFilter 实现

    参考自: https://github.com/BradLarson/GPUImage GPUImageRGBFilter: Adjusts the individual RGB channels o ...

  5. 常用颜色RGB、灰度值

    128/0/0       深红         255/0/0       红           255/0/255     粉红        255/153/204 玫瑰红       153 ...

  6. MySQL开发指南

    数据库开发是数据库管理系统(DBMS)和数据库应用软件设计研发的总称,数据运维.参与数据库生产环境的问题优化和解决等方面的事宜. 1.关于MySQL数据库 2.搭建MySQL环境 3.入门常用SQL. ...

  7. vue的一些坑(第一天)

    1:刚开始在创建项目的时候一直出现vue不是内部或外部命令 关于这个的解决方案网上给出的很多的解决方案是配置环境,这个我就不在赘述了: 但是我觉得那样太麻烦,就没用,只是重新 npm i vue-cl ...

  8. 基于注解的Spring MVC的简单入门——简略版

    网上关于此教程各种版本,太多太多了,因为我之前没搭过框架,最近带着两个实习生,为了帮他们搭框架,我只好...惭愧啊...基本原理的话各位自己了解下,表示我自己从来没研究过Spring的源码,所以工作了 ...

  9. PL/SQL 编程(二)游标、存储过程、函数

    游标--数据的缓存区 游标:类似集合,可以让用户像操作数组一样操作查询出来的数据集,实质上,它提供了一种从集合性质的结果中提取单条记录的手段. 可以将游标形象的看成一个变动的光标,他实质上是一个指针, ...

  10. 王佩丰第一讲 认识excel笔记

    改变工作表表浅颜色 批量插入工作表 选择多张工作表然后插入 找到表格边界区域快捷键(找到表格的最后一行):快速到达最上下左右端 点击边框上下左右双击 从指定的位置开始冻结窗格 输入今天的日期 快捷键c ...