makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析【转】
转自:http://www.cnblogs.com/lifexy/p/7089873.html
先来分析一个简单的.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(4096) { 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

objs := head.o init.o nand.o main.o nand.bin : $(objs)
arm-linux-ld -Tnand.lds -o nand_elf $^
arm-linux-objcopy -O binary -S nand_elf $@
arm-linux-objdump -D -m arm nand_elf > nand.dis %.o:%.c
arm-linux-gcc -Wall -c -O2 -o $@ $< %.o:%.S
arm-linux-gcc -Wall -c -O2 -o $@ $< clean:
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
OUTPUT_ARCH(arm) //设置输出文件的体系架构。ENTRY(_start) //将_start这个全局符号设置成入口地址。 SECTIONS //输出文件内容布局{ . = 0x00000000; //指定地址0x00000000 . = ALIGN(4); //代码以4字节对齐 .text : //指定.text section段(位于0x00000000) { cpu/arm920t/start.o (.text) //添加第一个目标文件: cpu/arm920t/start.o里面的.text代码段 board/100ask24x0/boot_init.o (.text) //添加第二个目标文件: board/100ask24x0/boot_init.o里面的.text代码段 *(.text) // *(.text) 表示添加剩下的全部文件的.text代码段 } . = ALIGN(4); .rodata : { *(.rodata) } //指定.rodata section段(位于0x00000000+.text section),将所有的.rodata只读数据段合并成一个.rodata只读数据段 . = ALIGN(4); .data : { *(.data) } //指定读写数据段, *(data):添加所有文件的数据段 . = ALIGN(4); .got : { *(.got) } //指定got段,got段是uboot自定义的一个段 . = .; __u_boot_cmd_start = .; //把__u_boot_cmd_start赋值为当前位置, 即起始位置 .u_boot_cmd : { *(.u_boot_cmd) } // u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置 __u_boot_cmd_end = .; // u_boot_cmd段结束位置 . = ALIGN(4); __bss_start = .; //把__bss_start赋值为当前位置,即bss段的开始位置 .bss : { *(.bss) } //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段 _end = .; //把_end赋值为当前位置,即bss段的结束位置} |
有什么不懂的或有误的地方欢迎指出,非常感谢
版权声明:本文为博主原创文章,未经博主允许不得转载。
随机推荐
- iOS 关于MVC和MVVM设计模式的那些事
一.概述 在 iOS 开发中,MVC(Model View Controller)是构建iOS App的标准模式,是苹果推荐的一个用来组织代码的权威范式.Apple甚至是这么说的.在MVC下,所有的对 ...
- vue使用过程中的一些小技巧
这些也是自己平时项目中遇到过的一些问题,看到有人整理了出来,也就转载保存一下 文章内容总结: 组件style的scoped Vue 数组/对象更新 视图不更新 vue filters 过滤器的使用 列 ...
- Android 通过浏览器打开应用
在很多应用的web站,其实都有这样一个功能,就是直接在网页中打开应用,接下来的就来探讨一下这个功能的实现,有些地方也我还没弄明白,还请懂的大神指点. 首先,得说一点不好消息,在微信中,这样的方式是行不 ...
- 【BZOJ1088】扫雷(递推)
[BZOJ1088]扫雷(递推) 题面 BZOJ 题解 忽然发现这就是一道逗逼题. 只需要枚举一下第一个是什么,后面都能够推出来了.. #include<iostream> using n ...
- 【51Nod1386】双马尾机器人Description 解题报告
[51Nod1386]双马尾机器人Description 给定\(n\)和\(k\),我们要在\(1,2,3,...,n\)中选择若干的数,每一种选择的方案被称为选数方案. 我们定义一种选数方 ...
- 洛谷 P2900 [USACO08MAR]土地征用Land Acquisition 解题报告
P2900 [USACO08MAR]土地征用Land Acquisition 题目描述 约翰准备扩大他的农场,眼前他正在考虑购买N块长方形的土地.如果约翰单买一块土 地,价格就是土地的面积.但他可以选 ...
- C++——内存对象 禁止产生堆对象 禁止产生栈对象
用C或C++写程序,需要更多地关注内存,这不仅仅是因为内存的分配是否合理直接影响着程序的效率和性能,更为主要的是,当我们操作内存的时候一不小心就会出现问题,而且很多时候,这些问题都是不易发觉的,比如内 ...
- 【bzoj3589】动态树
Portal --> bzoj3589 Description 给你一棵\(n\)个节点的树,总共有\(q\)次操作,每次操作是以下两种中的一种: 操作\((0,x,delta)\):给以\(x ...
- PID控制算法的C语言实现九
(1)微分先行PID控制算法 微分先行PID控制的特点是只对输出量yout(k)进行微分,而对给定值rin(k)不进行微分.这样,在改变给定值时,输出不会改变,而被控量的变化通常是比较缓和的.这种输出 ...
- Linux下安装python-2.7 先zlib
2018-04-25 发布 Linux下安装python-2.7 python 1.1k 次阅读 · 读完需要 25 分钟 1 安装依赖的库 yum -y install python-deve ...