ARM 重定位引入和链接脚本

news2024/9/9 7:20:50

一、一个事实:大部分指令是位置有关编码

位置无关编码(PIC,position independent code):汇编源文件被编码成二进制可执行程序时,编码方式与位置(内存地址)无关。

位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关的。


我们在设计一个程序时,会给这个程序指定一个运行地址(链接地址)。就是说我们在编译程序时,其实心里是知道我们程序将来被运行时的地址(运行地址)的,而且必须给编译器链接器指定这个地址(链接地址)才行。最后得到的二进制程序,理论上是和你指定的运行地址有关的,将来这个程序被执行时必须放在当时编译链接时给定的那个地址(链接地址)下才行,否则不能运行(就叫位置有关代码)。但是有个别特别的指令,他可以跟指定的地址(链接地址)没有关系,也就是说这些代码实际运行时不管放在哪里都能正常运行。


对比:位置无关代码要好一些,适应性强,放在哪里都能正常运行;位置有关代码就必须运行在链接时指定的地址上,适应性差。位置无关码有一些限制,不能完成所有功能,有时候不得不使用位置有关代码。


二、链接地址和运行地址:可能相同也可能不同

对于位置有关代码来说:最终执行时的运行地址和编译链接时给定的链接地址必须相同,否则一定出错

我们之前的裸机程序中,Makefile 中用 -Ttext 0x0 来指定链接地址是0x0。这意味着我们认为这个程序将来会放在0x0这个内存地址去运行。

但是实际上,我们运行时的地址是 0xd0020010 (我们用 dnw 下载时指定的下载地址)。这两个地址看似不同,但是实际相同。这是因为 S5PV210 内部做了映射,把 SRAM 映射到了 0x0 地址去。

在这里插入图片描述


分清楚这两个概念
链接地址:链接时指定的地址(指定方式为:Makefile中用-Ttext,或者链接脚本)
运行地址:程序实际运行时地址(指定方式:由实际运行时被加载到内存的哪个位置说了算)


三、再解 S5PV210的启动过程

三星推荐方式和uboot的实现方式是不同的

三星推荐的启动方式中:bootloader 必须小于 96KB 并大于 16KB,假定 bootloader 为 80KB,启动过程是这样子:先开机上电后 BL0 运行,BL0 会加载外部启动设备中的 bootloader 的前 16KB(BL1) 到 SRAM 中去运行,BL1 运行时会加载 BL2(bootloader 中 80-16=64KB )到 SRAM 中(从 SRAM 的1 6KB 处开始用)去运行;BL2 运行时会初始化 DDR 并且将 OS 搬运到 DDR 去执行 OS,启动完成。

uboot 实际使用的方式:uboot 大小随意,假定为 200KB。启动过程是这样子:先开机上电后 BL0 运行,BL0 会加载外部启动设备中的 uboot 的前 16KB(BL1)到 SRAM 中去运行,BL1 运行时会初始化 DDR,然后将整个 uboot 搬运到 DDR 中,然后用一句长跳转(从 SRAM 跳转到DDR )指令从 SRAM 中直接跳转到 DDR 中继续执行 uboot 直到 uboot 完全启动。uboot 启动后在 uboot 命令行中去启动 OS


四、现在明白为什么要重定位了吧?

原因

链接地址和运行地址有时候必须不相同,而且还不能全部用位置无关码,这时候只能重定位。

扩展

分散加载:把 uboot 分成 2 部分(BL1 和整个 uboot),两部分分别指定不同的链接地址。启动时将两部分加载到不同的地址(BL1 加载到 SRAM,整个 uboot 加载到 DDR ),这时候不用重定位也能启动。


评价:分散加载其实相当于手工重定位。重定位是用代码来进行重定位,分散加载是手工操作重定位的。


五、运行时地址由什么决定?

运行时的地址是由运行时决定的(编译链接时是无法绝对确定运行时地址的)


链接地址由什么决定?

链接地址是由程序员在编译链接的过程中,通过 Makefile 中 -Ttext xxx 或者在链接脚本中指定的。程序员事先会预知自己的程序的执行要求,并且有一个期望的执行地址,并且会用这个地址来做链接地址。


举例

1、linux 中的应用程序。gcc hello.c -o hello,这时使用默认的链接地址就是 0x0,所以应用程序都是链接在 0 地址的。因为应用程序运行在操作系统的一个进程中,在这个进程中这个应用程序独享 4G 的虚拟地址空间。所以应用程序都可以链接到 0 地址,因为每个进程都是从 0 地址开始的。(编译时可以不给定链接地址而都使用 0)

2、210 中的裸机程序。运行地址由我们下载时确定,下载时下载到 0xd0020010,所以就从这里开始运行。(这个下载地址也不是我们随意定的,是 iROM 中的 BL0 加载 BL1 时事先指定好的地址,这是由 CPU 的设计决定的)。所以理论上我们编译链接时应该将地址指定到 0xd0020010,但是实际上我们在之前裸机程序中都是使用位置无关码 PIC,所以链接地址可以是 0。


六、从源码到可执行程序的步骤:预编译、编译、链接、strip

预编译:预编译器执行。譬如 C 中的宏定义就是由预编译器处理,注释等也是由预编译器处理的。
编译:  编译器来执行。把源码 .c .S 编程机器码 .o 文件。
链接:	链接器来执行。把 .o 文件中的各函数(段)按照一定规则(链接脚本来指定)累积在一起,
		形成可执行文件。
strip: strip 是把可执行程序中的符号信息给拿掉,以节省空间。(Debug 版本和 Release 版本)
objcopy:由可执行程序生成可烧录的镜像 bin 文件。

程序段的概念: 代码段、数据段、bss段(ZI段)、自定义段

段就是程序的一部分,我们把整个程序的所有东西分成了一个一个的段,给每个段起个名字,然后在链接时就可以用这个名字来指示这些段。也就是说给段命名就是为了在链接脚本中用段名来让段站在合适的位置。

段名分为 2 种:一种是编译器链接器内部定好的,先天性的名字;一种是程序员自己指定的、自定义的段名。
先天性段名:
	代码段:(.text),又叫文本段,代码段其实就是函数编译后生成的东西
	数据段:(.data),数据段就是C语言中有显式初始化为非0的全局变量
	bss段:(.bss),又叫ZI(zero initial)段,就是零初始化段,对应C语言中初始化为0的全局变量。
	
后天性段名:
	段名由程序员自己定义,段的属性和特征也由程序员自己定义。

分析一些问题,跟这里结合,然后试图明白一些本质:
1、C 语言中全局变量如果未显式初始化,值是 0。本质就是 C 语言把这类全局变量放在了 bss 段,从而保证了为 0 。
2、C 运行时环境如何保证显式初始化为非 0 的全局变量的值在 main 之前就被赋值了?就是因为它把这类变量放在了.data 段中,而 .data 段会在 main 执行之前被处理(初始化)。


链接脚本究竟要做什么?

链接脚本其实是个规则文件,他是程序员用来指挥链接器工作的。

链接器会参考链接脚本,并且使用其中规定的规则来处理 .o 文件中那些段,将其链接成一个可执行程序。

链接脚本的关键内容有2部分:段名 + 地址(作为链接地址的内存地址)
链接脚本的理解:
SECTIONS {}	这个是整个链接脚本
. 点号在链接脚本中代表当前位置。
= 等号代表赋值

源自朱有鹏老师.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式智能家居项目雏形

需求分析 客户端进入室内后(局域网)能够主动发现服务(如: 环境服务,灯光服务) 各种服务可以有不同的载体(如:由不同设备提供) 各种服务之间,服务与客户端之间完全无耦合(服务可自由增减) 客户端可以是移动APP,也可以是桌面软件…

【计算机毕业设计】基于JSP的房产中介系统的设计与实现

分类号:TP315 U D C:D10621-408-(2007) 6032 -0 密 级:公 开 编 号:2003211030 学位论文 基于JSP的房产中介系统的设计与实现 摘要 计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着科学技术的不断提高&#xff…

2022SDNU-ACM结训赛题解

首先感谢一下各位出题人的精心准备、验题人的辛勤付出、以及选手的积极参加 题解 Problem A 柳予欣的归来【数学】 出题人&#xff1a; bhq 没想到一血是被打完山大的牛客比赛后来结训赛玩的wyx拿走的&#xff01; 题目描述&#xff1a; 计算(∑0<d<pd−1)m(\sum_{0…

Procreate iPad绘画教程

Procreate iPad绘画教程 通过动手绘画课程了解您需要了解的有关 Procreate 的所有信息。现在为 Procreate 5 更新 课程英文名&#xff1a;Drawing and Painting on the iPad with Procreate 此视频教程共11.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#x…

Qt第二十八章:异步

所有的数据处理都应该通过异步进行 定义信号# 自定义信号源 class QCustomSignal(QObject):signal_update_table Signal(list)signal_get_token Signal(str)signal_send_mq Signal() 处理函数 Slot()def handle_search(self):def thread_function():user_info get_use…

uImage的制作工具mkimage详解(源码编译、使用方法、添加的头解析、uImage的制作)

1、mkimage工具的源码 (1)mkimage是uboot下面的一个工具&#xff0c;用来将zImage制作成uImage&#xff0c;制作内核启动镜像(给zImage镜像添加64字节的头信息成uImage)&#xff1b; (2)mkimage的源码在"uboot/tool"目录下&#xff0c;在编译uboot时默认会编译出mkim…

假设检验(2)参数的假设检验

下面我们分情况讨论参数的假设检验问题&#xff0e; 3.2. 1 一个正态总体均值的检验&#xff08;方差已知时&#xff09; 例3.2. 1 某车间生产铜丝&#xff0c;铜丝的主要质量指标是折断力&#xff0c;根据过去的经验知该车间生产的铜丝折断力江今换了一批质量较好的原材料&am…

手把手实例教你短视频定位,人设和变现方式,学会节省半年摸索时间

手把手实例教你短视频定位,人设和变现方式,学会节省半年摸索时间 昨天在我赢助手的公开课上分享了一个变现模型&#xff0c;不光是做短视频可以用&#xff0c;在所有互联网项目都可以用。 基础概念就是单价、客户数量和时间的关系。 举个例子&#xff1a; 你的目标是一年赚1…

数据结构:二叉树的链式结构

文章目录一.前言二.二叉树遍历2.1前序遍历/先根遍历2.2中序遍历/中根遍历2.3后序遍历/后根遍历2.4层序遍历2.5二叉树的销毁三.二叉树节点个数四.二叉树叶子节点的个数五.二叉树的高度六.二叉树第K层的节点个数七.找二叉树的节点八.题目8.1判断单值二叉树8.2相同的树8.3另一棵子…

[Redis-实战] 企业常用的缓存使用方案(查询、更新、击穿、穿透、雪崩) 附源码

目录 &#x1f34a; 缓存查询策略 &#x1f369; 缓存更新策略 &#x1f36d; 缓存穿透 &#x1f363; 缓存雪崩 &#x1f355; 缓存击穿 &#x1f47e; 项目源码下载​​​​​​​ &#x1f34a; 缓存查询策略 我们要查询的业务数据并不是经常改变的, 这里我们可以放到Redis…

用visa进行仪表通信

第二份工作一直跟仪表打交道&#xff0c;用仪表来测试&#xff0c;当然主要还是搞自动化。仪表连接通信当然需要用到visa啦。 一.NI VISA的安装和TCP/IP配置 这里看到有人对于安装NI VISA介绍的很清楚&#xff0c;具体想了解就看他的吧。 NI VISA安装和TCP/IP配置 二.安装Py…

第6部分 单区域OSPF

目录 6.1 OSPF 概述 6.2 实验1&#xff1a;点到点链路上的OSPF 1.实验目的 2.实验拓扑 3.实验步骤 4.实验调试 &#xff08;1&#xff09;show ip route &#xff08;2&#xff09;show ip ospf neighbor 6.3 OSPF 命令汇总 OSPF(Open Shortest Path First&#xff0c…

Java实现 LeetCode 500.键盘行

500.键盘行 给你一个字符串数组 words &#xff0c;只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。 美式键盘 中&#xff1a; 第一行由字符 “qwertyuiop” 组成。第二行由字符 “asdfghjkl” 组成。第三行由字符 “zxcvbnm” 组成。 示例 1&…

【mysql是怎样运行的】-mysql字符集

文章目录1. 服务器级别2. 数据库级别3. 表级别4. 列级别MySQL 有 4 个级别的字符集和比较规则&#xff0c;分别是 服务器级别、数据库级别、表级别、列级别.1. 服务器级别 SHOW VARIABLES like character_set_server SHOW VARIABLES like collation_server在启动服务器程序时&a…

Vue响应式系统的作用与实现(一)

响应式系统的作用与实现 0.写在前面&#xff1a; 写了mini-vue之后的疑惑更多了&#xff0c;比如为什么要这样设计&#xff1f;这样做的好处是啥&#xff1f;为什么我想不出来&#xff1f;&#xff08;我真菜于是决定去看霍春阳大佬的Vue.js设计与实现。一些参考资料&#xf…

x265 帧间预测

帧间编码入口函数&#xff1a; 从 Analysis::compressCTU 是ctu编码的入口函数&#xff0c;根据 slice 类型判断是 I 还是 BP&#xff0c;如果是BP则执行帧间编码函数 Analysis::compressInterCU_rdx_x&#xff1a;&#xff1a;/*压缩分析CTU过程&#xff1a;1.为当前CTU加载QP…

m基于16QAM的自适应波束形成matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 16QAM全称正交幅度调制是英文Quadrature Amplitude Modulation的缩略语简称&#xff0c;意思是正交幅度调制&#xff0c;是一种数字调制方式。产生的方法有正交调幅法和复合相移法。 波束形成是…

工业级数据分发服务DDS之安全篇

目录引出问题分析问题未授权订阅者未授权发布者截胡篡改跨域攻击解决问题官方标准DDS的安全特性基于域的安全保护域内保护RTI方案RTI安全插件的特性DDS支持的加解密算法用于数据流保护的密码算法用于密钥交换的密码算法用于数字签名的密码算法RTPS-HMAC-Only插件用于数据流保护…

数据结构(10)图的概念、存储

目录 10.1.概念 10.2.存储 10.2.1.邻接矩阵 10.2.2.邻接表 10.1.概念 定义: 图&#xff0c;用来表示多对多的关系&#xff0c;比如地图里城市之间的通路、比如人际关系。 图由顶点和边组成&#xff0c;顶点是图里的每个结点&#xff0c;边是顶点之间的通路&#xff0c;可…

【计算机网络】网络基础(三)

自从计算机、手机被广泛应用于工作、生活、娱乐、学习&#xff0c;那你有没有考虑过QQ的消息、爱奇艺的视频、钉钉的网络会议的数据是如何传输的&#xff1f;这些信息自然是通过网络&#xff08;WIFI、蜂窝网络等&#xff09;传播的&#xff0c;而一个简单的通信网络是由路由器…