GNU linker script,ld script,GNU链接脚本
https://blog.csdn.net/itxiebo/article/details/50937412
https://blog.csdn.net/itxiebo/article/details/50938753
[随笔]GNU linker script,ld script,GNU链接脚本
一、什么是GNU linker script?作用是什么?
.lds文件,即linker script,决定了可执行映像(image)的链接方式,以及各个段的装载地址(装载域)和执行地址(运行域)。
- 装载地址:运行之前各段的地址;
- 运行地址:运行时各段的地址。
二、对GNU linker script的简单认识
首先,完整版的官网Gnulinkerscript下载地址如下,此文件可作为参考文献使用。
http://pan.baidu.com/s/1hriLMb6
GNU官方网站上对.lds文件形式的基本描述:
SECTIONS
{
...
secname start BLOCK(align)(NOLOAD) : AT(ldadr)
{ contents } >region :phdr =fill
...
}
两个必须的(secname, contents),其他optional
secname:段名,用以命名此段。
contents:决定哪些内容放在本段,可以是整个目标文件(.o),也可以是目标文件中的某段(代码段、数据段等)。
start:是段的重定位地址,即本段运行的地址。如果代码中有位置无关指令,程序运行时这个段必须放在这个地址上。start可以用任意一种描述地址的符号来描述。
BLOCK(align) 指定块对齐。比如,前一个段从0x30000000到0x300003F1,此处标记ALIGN(4),表示此处最小占用4Bytes,即使下一个段是紧挨这个段,那么下一个段的起始地址(也就是运行地址)为0x300003F4。
NOLOAD:告诉加载器程序运行时不加载该段到内存。
AT(ldadr):定义本段存储(加载)的地址,如果不使用这个选项,则加载地址等于运行地址,通过这个选项可以控制各段分别保存于输出文件中不同的位置。
三、.lds相关的简单实例
例:
/* nand.lds */
SECTIONS
{
first 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(运行地址处),此过程也就需要读取flash,把程序拷贝到相应位置才能运行。这就是存储地址和运行地址的不同,称为加载时域和运行时域,可以在.lds连接脚本文件中分别指定。
另外,编写好的.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
四、常用section的定义
text section:存放程序代码
data section:存放数据
bss section:存放未初始化的数据,在镜像文件中,是不为 bss 段分配空间的,所以如果你开一个很大的全局的未初始化的数组,镜像文件的大小不会相应的变大。而只是在加载器将镜像加载进内存时,才会为 bss 段分配空间
链接器:把各个目标文件的各种段进行重新组合。
最后,两个命令,先保存起来,后面有机会再实践一下。
arm-linux-objdump -h vmlinux > vmlinux.txt
–输出linux内核段信息到vmlinux.txt文本中。
arm-linux-objdump -f vmlinux > sec_symbol.txt
–输出内核段信息和符号到sec_symbol.txt文本中。
本文回溯
什么是GNU linker script?作用是什么?
对GNU linker script的简单认识,核心SECTIONS的结构分析。
对链接器基本原理的理解。
完
u-boot分析 三 (u-boot.lds脚本)
目的,
了解链接器用到的脚本文件u-boot.lds。
在开始这篇博文之前,需要先了解一些GNU linker script的基本知识,可以参考博主的另外一篇分享《GNU linker script,ld script,GNU链接脚本》
在《u-boot分析 二》中,我们分析u-boot的目录结构,提及到了程序入口start.S,但在开始了解start.S之前,我们先聊聊链接器ld程序的脚本文件u-boot.lds。
下面我们就来品味一下UT4418开发板的u-boot.lds脚本,即u-boot/arch/arm/cpu/slsiap/u-boot.lds。如果读者正好需要看source code,可以参看之前的文章《u-boot分析 一》中的源码分享。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*指定输出可执行文件是elf格式,32位ARM指令,小端*/
OUTPUT_ARCH(arm)
/*指定输出可执行文件的平台为ARM*/
ENTRY(_stext)
/*指定输出可执行文件的起始代码段为_stext*/
SECTIONS
{
/*指定可执行文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。必须使编译器知道这个地址,通常都是修改此处来完成*/
. = 0x00000000;
/*从0x0位置开始*/
. = ALIGN(4);
/*代码以4字节对齐*/
.text :
/*代码段*/
{
*(.__image_copy_start)
/*u-boot将自己copy到RAM,此为需要copy的程序的start*/
SOCDIR/start.o (.text*)
/*./arch/arm/cpu/slsiap/s5p4418/start.S*/
SOCDIR/vectors.o (.text*)
/*./arch/arm/cpu/slsiap/s5p4418/vectors.S,异常向量表*/
*(.text*)
/*其他的代码段放在这里,即start.S/vector.S之后*/
}
. = ALIGN(4);
/*代码段结束后,有可能4bytes不对齐了,此时做好4bytes对齐,以开始后面的.rodata段*/
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
/*在代码段之后,存放read only数据段*/
. = ALIGN(4);
/*和前面一样,4bytes对齐,以开始接下来的.data段*/
.data : {
*(.data*)
/*可读写数据段*/
}
. = ALIGN(4);
/*和前面一样,4bytes对齐*/
. = .;
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
/*.data段结束后,紧接着存放u-boot自有的一些function,例如u-boot command等*/
}
. = ALIGN(4);
.image_copy_end :
{
*(.__image_copy_end)
/*至此,u-boot需要自拷贝的内容结束,总结一下,包括代码段,数据段,以及u_boot_list*/
}
.rel_dyn_start :
/*在老的uboot中,如果我们想要uboot启动后把自己拷贝到内存中的某个地方,只要把要拷贝的地址写给TEXT_BASE即可,然后boot启动后就会把自己拷贝到TEXT_BASE内的地址处运行,在拷贝之前的代码都是相对的,不能出现绝对的跳转,否则会跑飞。在新版的uboot里(2013.07),TEXT_BASE的含义改变了。它表示用户要把这段代码加载到哪里,通常是通过串口等工具。然后搬移的时候由uboot自己计算一个地址来进行搬移。新版的uboot采用了动态链接技术,在lds文件中有__rel_dyn_start和__rel_dyn_end,这两个符号之间的区域存放着动态链接符号,只要给这里面的符号加上一定的偏移,拷贝到内存中代码的后面相应的位置处,就可以在绝对跳转中找到正确的函数。*/
{
*(.__rel_dyn_start)
}
.rel.dyn : {
*(.rel*)
/*动态链接符存放在的段*/
}
.rel_dyn_end :
{
*(.__rel_dyn_end)
/*动态链接符段结束*/
}
.end :
{
*(.__end)
}
_image_binary_end = .;
/*bin文件结束*/
/*
* Deprecated: this MMU section is used by pxa at present but
* should not be used by new boards/CPUs.
*/
. = ALIGN(4096);
.mmutable : { /*for MMU*/
*(.mmutable)
}
/*
* Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
* __bss_base and __bss_limit are for linker only (overlay ordering)
*/
/*bss段的描述*/
.bss_start (OVERLAY) : {
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN(4);
__bss_limit = .;
}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
/*bss段的描述结束*/
.dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) }
.plt : { *(.plt*) }
.interp : { *(.interp*) }
.gnu.hash : { *(.gnu.hash) }
.gnu : { *(.gnu*) }
.ARM.exidx : { *(.ARM.exidx*) }
.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
}
总结一下,u-boot.lds脚本文件告诉链接器linker如何布局代码段、数据段、bss段等,已经配置了u-boot自拷贝(从flash到RAM的copy)的内容。另外,还简要的涉及了动态链接技术等。
完
GNU linker script,ld script,GNU链接脚本的更多相关文章
- 链接脚本(Linker Script)用法解析(一) 关键字SECTIONS与MEMORY
1.MEMORY关键字用于描述一个MCU ROM和RAM的内存地址分布(Memory Map),MEMORY中所做的内存描述主要用于SECTIONS中LMA和VMA的定义. 2.SECTIONS关键字 ...
- 链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行
将函数载入到RAM中运行需要以下三个步骤: (1)用编译器命令#pragma section "<section name>" <user functions&g ...
- 链接脚本(Linker Script)用法解析(二) clear_table & copy_table
可执行文件中的.bss段和.data段分别存放未赋初值的全局变量和已赋初值的全局变量,两者的特点分别为: (1).bss段:①无初值,所以不占ROM空间:②运行时存储于RAM:③默认初值为0 (2). ...
- ld - GNU linker (连接器)
总览 (SYNOPSIS) ld [-o output] objfile... [-Aarchitecture] [-b input-format] [-Bstatic] [-Bdynamic] [- ...
- Linker Scripts3--简单的链接脚本命令1
1.前言 这个部分我们描述了简单的链接脚本命令 2.设置entry point 程序中第一条运行的指令被称为入口点entry point,可以使用ENTRY链接脚本命令设置entry point,参数 ...
- Linker Scripts3--简单的链接脚本命令2-Assigning Values to Symbols
1.前言 本章继续讲述简单脚本命令的后半部分 2.Assigning Values to Symbols 你可以给一个符号(symbol)赋值,它会把这些定义的符号放入全局符号表(symbols ta ...
- 简单的ld链接脚本学习
一. 链接脚本的整体认识 什么是链接文件呢?作用是什么呢? 当编写了多个C文件时,我们将他们编译链接成一个可执行的文件,此时就需要用到链接脚本文件(ld).ld脚本主要功能就是:将多个目标文件(.o) ...
- [转]Linux下的lds链接脚本详解
转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml 一. 概论 每一个链接过程都由链接脚本(lin ...
- Linux下的lds链接脚本基础
转载:http://soft.chinabyte.com/os/104/12255104.shtml 今天在看uboot引导Linux部分,发现要对链接脚本深入了解,才能知道各个目标文件的内存分布 ...
随机推荐
- [BZOJ2822]:[AHOI2012]树屋阶梯(卡特兰数)
题目传送门 题目描述 暑假期间,小龙报名了一个模拟野外生存作战训练班来锻炼体魄,训练的第一个晚上,教官就给他们出了个难题.由于地上露营湿气重,必须选择在高处的树屋露营.小龙分配的树屋建立在一颗高度为N ...
- hashcode、equals、HashMap间的关系
1.从Object说起package com.hallo.collection; public class ObjectDemo { public static void main(String[] ...
- vue-router 2.0 跳转之router.push()
router.push(location) 除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现. router.push(location) 想要导航 ...
- jQuery easing动画效果扩展
引入Easing js文件 <script src="js/jquery.min.js"></script> <script src="js ...
- Oracle诊断:在程序的运行中,有时候数据库会断开连接
在程序的运行中,有时候数据库会断开连接,然后报下面错误: ORA-12519: TNS:no appropriate service handler found 可用的服务处理程序没有找到. 1. ...
- Parse error: syntax error, unexpected 'class' (T_CLASS)
电脑坏了重新下载代码. 结果报错 Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_ST ...
- vue +ts 的一次踩坑日记
在vue的方法里面写事件的时候比如写一个路由跳转,方法大概如下: goBack1() { console.log(this); this.$router. ...
- Fragment 基础使用及重叠问题
一 基本使用 Fragment依附于Activity使用,方面我们在一个页面里面切换显示多屏内容. Activity管理Fragment有两种方式,通过FragmentTransacation这个类来 ...
- PHP文件和目录操作
目录操作 创建目录:mkdir(目录地址, 权限, 是否递归创建=false); 删除目录:rmdir(目录地址);(仅仅可以删除空目录,不支持递归删除) 移动(改名):rename(旧地址, 新地址 ...
- SpringBoot 集成mongodb(1)单数据源配置
新项目要用到mongodb,于是在个人电脑上的虚拟环境linux上安装了下mongodb,练习熟悉下. 1.虚拟机上启动mongodb. 首先查看虚拟机ip地址,忘了哈~~ 命令行>ifconf ...