驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址
驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址
最近重新看了乾龙_Heron的《ARM 上电启动及 Uboot 代码分析》(下简称《代码分析》)
文档里写道:
Uboot.lds文件中起始地址是0x00,但是config.mk中的TEXT_BASE是0x57e00000,但是生成的uboot反汇编文件中,为什
么start.s的第一条指令地址也是0x57e00000?不应该是0x00么?因为start.s的加载地址和运行地址都是0x00啊!? 答:Uboot.lds的0x00: 跟在SECTION后面的第一条 location counter,总是默认初始化为0。config.mk中的TEXT_BASE就是ROM在CPU上的地址,也就是说,
不同的CPU已经规定了不同的ROM地址
先来看看笔者这篇文章标题的关键字:链接地址 加载地址
《代码分析》中也给了答案
连接地址<==>运行地址 存储地址<==>加载地址 (1)对于有操作系统时,运行地址与加载地址不同,在加载过程中装载器就把段加载到它应该去的连接地址处(也就是生成该段时的运行地址) (2)对于uboot,运行地址与加载地址不同时,需要它自己(例如前4k代码)将自己加载到运行地址处执行。
那么什么是链接脚本地址,来看一段链接脚本的内容:
SECTIONS
{
. = 0x08048000;
tinytext : { *(.test) *(.rodata)}
. = 0x08088000;
tinydata : {*(.data)}
}
用过脚本代码的人知道,.test段和.rodata将紧跟在0x08048000地址后面,这种在链接脚本上假定的地址,称为链接脚本地址(未知是否有更专业的名称,暂用此名)。为什么我要说是假定呢?因为在ld命令中可以覆盖lds脚本设定段的地址,就是《代码分析》中出现的.lds的地址被.mk文件(.mk文件,其实就是makefile文件)中的TEXT_BASE修改了。
上面已经提到,链接地址就是代码运行地址,运行地址我们可以通过对执行文件的反汇编得到;那我们来做一个实验,看lds文件中的地址是不是代码链接地址,
下面用gcc -c 和 ld 来编译链接代码(参考程序员的自我修养 p125)
c代码
int aa=8;
void main(void)
{
int i=0;
aa = i;
}
.lds 代码
ENTRY(main)
SECTIONS
{
. = 0x08048000;
tinytext : { *(.test) *(.rodata)}
. = 0x08088000;
tinydata : {*(.data)}
}
然后
$ gcc -c -fno-builtin ttext.c
$ ld -static -T test_Ttext.lds -o ttext ttext.o
$ objdump -S ttext
ttext: file format elf64-x86-64
Disassembly of section .text:
0000000008048000 <main>:
8048000: 55 push %rbp
8048001: 48 89 e5 mov %rsp,%rbp
8048004: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
804800b: 8b 45 fc mov -0x4(%rbp),%eax
804800e: 89 05 ec ff 03 00 mov %eax,0x3ffec(%rip) # 8088000 <aa>
8048014: 5d pop %rbp
8048015: c3 retq
我们看看符号表:
$ objdump -t ttext
ttext: file format elf64-x86-64
SYMBOL TABLE:
0000000008048000 l d .text 0000000000000000 .text
0000000008048018 l d .eh_frame 0000000000000000 .eh_frame
0000000008088000 l d tinydata 0000000000000000 tinydata
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l df *ABS* 0000000000000000 ttext.c
0000000000000000 l df *ABS* 0000000000000000
0000000008088000 g O tinydata 0000000000000004 aa
0000000008048000 g F .text 0000000000000016 main
从上面这个实验,我们可以看出来,链接脚本地址和链接地址居然是一样的!
那么,到底.mk文件里面做了什么,使TEXT_BASE成为了代码的地址?关键一点就是.mk在ld 中加了一个选项 -Ttext,这个选项使得.text地址的链接地址为此选项的参数TEXT_BASE。
我们来看一下是不是:
之前我们的ld没有加选项-Ttext,现在加上试试 $ ld -static -T test_Ttext.lds -o ttext ttext.o -Ttext 0xff $ objdump -S ttext
ttext: file format elf64-x86-64
Disassembly of section .text:
00000000000000ff <main>:
ff: 55 push %rbp
100: 48 89 e5 mov %rsp,%rbp
103: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
10a: 8b 45 fc mov -0x4(%rbp),%eax
10d: 89 05 ed 7e 08 08 mov %eax,0x8087eed(%rip) # 8088000 <aa>
113: 5d pop %rbp
114: c3 retq 我们可以发现,.text的地址变成了0xff 跟我们输入的参数一样
再看看符号表 $ objdump -t ttext ttext: file format elf64-x86-64 SYMBOL TABLE: 0000000008088000 l d tinydata 0000000000000000 tinydata 00000000000000ff l d .text 0000000000000000 .text 0000000008088008 l d .eh_frame 0000000000000000 .eh_frame 0000000000000000 l d .comment 0000000000000000 .comment 0000000000000000 l df *ABS* 0000000000000000 ttext.c 0000000000000000 l df *ABS* 0000000000000000 0000000008088000 g O tinydata 0000000000000004 aa 00000000000000ff g F .text 0000000000000016 main
.text 段地址的确是变了,但是没有影响 data段
在这样的试验结果下,可以确定的说,-Ttext选项会改变.text段的地址,这就是TEXT_BASE成为Uboot的代码段链接地址的原因
文章讨论Uboot代码段链接地址的问题到这里就结束了,下面将测试-Ttext 选项对.data是否会产生影响;
上面的实验将.data放在另一段,如果将.data放在tinytext中,是否会随着-Ttext改变.text的时候同时被改变呢?
$ cat test_Ttext.lds ENTRY(main) SECTIONS
{ . = 0x08048000; tinytext : { *(.test)*(.data) *(.rodata)}
} $ ld -static -T test_Ttext.lds -o ttext ttext.o -Ttext 0xff
$ objdump -S ttext
ttext: file format elf64-x86-64
Disassembly of section .text:
00000000000000ff <main>:
ff: 55 push %rbp
100: 48 89 e5 mov %rsp,%rbp
103: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
10a: 8b 45 fc mov -0x4(%rbp),%eax
10d: 89 05 ed 7e 04 08 mov %eax,0x8047eed(%rip) # 8048000 <aa>
113: 5d pop %rbp
114: c3 retq 咦,怎么aa变成了tinytext的地址呢?
我们看看符号表
$ objdump -t ttext
ttext: file format elf64-x86-64
SYMBOL TABLE:
0000000008048000 l d tinytext 0000000000000000 tinytext
00000000000000ff l d .text 0000000000000000 .text
0000000008048008 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l df *ABS* 0000000000000000 ttext.c
0000000000000000 l df *ABS* 0000000000000000
0000000008048000 g O tinytext 0000000000000004 aa
00000000000000ff g F .text 0000000000000016 main
发现.text改变了,但是aa(.data)没有随.text而变,而是紧跟着tinytext的首地址
一个疑问,在开发过程中,可能板子的RAM地址比较低/高,那么我们要怎么改data和rodata字段使其符合内存的范围限制呢?
驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址的更多相关文章
- 驱动开发学习笔记. 0.02 基于EASYARM-IMX283 烧写uboot和linux系统
驱动开发读书笔记. 0.02 基于EASYARM-IMX283 怎么烧写自己裁剪的linux内核?(非所有arm9通用) 手上有一块tq2440,但是不知道什么原因,没有办法烧boot进norflas ...
- 驱动开发学习笔记. 0.06 嵌入式linux视频开发之预备知识
驱动开发读书笔记. 0.06 嵌入式linux视频开发之预备知识 由于毕业设计选择了嵌入式linux视频开发相关的项目,于是找了相关的资料,下面是一下预备知识 UVC : UVC,全称为:USB v ...
- 驱动开发学习笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇
驱动开发读书笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇下面这段摘自 linux源码里面的文档 : Documentatio ...
- 驱动开发学习笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇
驱动开发读书笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇 下面这段摘自 linux源码里面的文档 : 内核版本2.6.22Doc ...
- 驱动开发学习笔记. 0.01 配置arm-linux-gcc 交叉编译器
驱动开发读书笔记. 0.01 配置arm-linux-gcc 交叉编译器 什么是gcc: 就像windows上的VS 工具,用来编译代码,具体请自己搜索相关资料 怎么用PC机的gcc 和 arm-li ...
- Android学习笔记(二)之异步加载图片
最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...
- [PyTorch 学习笔记] 7.1 模型保存与加载
本章代码: https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson7/model_save.py https://githu ...
- Linux驱动开发学习笔记(1):LINUX驱动版本的hello world
1.关于目录 /lib/modules/2.6.9-42.ELsmp/build/ 这个是内核源码所在的目录 一般使用这样的命令进入这个目录:cd /lib/modules/$(una ...
- Django 学习笔记(三) --- HTML 模版加载 css、js、img 静态文件
人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...
随机推荐
- oracle查询中文数据出现乱码
首先,在oracle中,输入select userenv('language') from dual,查询出oracle使用的编码方式,我的是SIMPLIFIED CHINESE_CHINA.ZHS1 ...
- 嵌套 QQ、微博 通讯工具到HTML中
自己QQ.微博的实例: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Defa ...
- Java反射机制DOME
Java反射机制 public class TestHibernate { @Test public void TestHb(){ try { Class cs = Class.forName(&qu ...
- Android签名机制
Android APK 签名比对 发布过Android应用的朋友们应该都知道,Android APK的发布是需要签名的.签名机制在Android应用和框架中有着十分重要的作用. 例如,Android系 ...
- JS获取IMG图片高宽
前段时间在LJW写的touchslider.js轮播代码里添加自适应屏幕大小的功能时,遇到一个问题.不管用什么样的方法都无法获取到IMG标签的高宽,最后只有给图片定一个高宽的比例值:趁今天有空我就写了 ...
- Linux学习笔记2_mysql安装
查看文件内容的命令有很多:cat, tac, more, less, head, tail, nl. cat由第一行开始显示档案内容:tac从最后一行开始显示,可以看出tac是cat的倒着写:more ...
- Xmodem Bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 多年前玩Cisco交换 ...
- wc命令
wc命令的功能为统计指定文件中的字节数.字数.行数, 并将统计结果显示输出. 语法:wc [选项] 文件- 说明:该命令统计给定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同 ...
- 16.C语言中数据类型的本质含义是:表示一个内存格子的长度和解析方法。
数据类型决定长度的含义:我们一个内存地址(0x30000000),本来这个地址只代表1个字节的长度,但是实际上我们可以通过给他一个类型(int),让他有了长度(4),这样这个代表内存地址的数字(0x3 ...
- 向IPython Notebook中导入.py文件
IPython Notebook使用起来简洁方便,但是有时候如果需要导入一个现有的.py文件,则需要注意选择导入的方法以达到不同的效果.目前遇到3种方法. (1) 将文件保存为.ipynb格式,直接拖 ...