《程序员的自我修养》读书笔记3——使用KEIL研究ELF文件的重定位
空间和地址分配
仍然采用上一节的代码。看生成的代码段。3个中间目标文件的代码段:
fromelf -v a.o========================================================================** Section #1Name : i.mainType : SHT_PROGBITS (0x00000001)Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)Addr : 0x00000000File Offset : 52 (0x34)Size : 24 bytes (0x18)Link : SHN_UNDEFInfo : 0Alignment : 4Entry Size : 0====================================
fromelf -v b.o========================================================================** Section #1Name : i.swapType : SHT_PROGBITS (0x00000001)Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)Addr : 0x00000000File Offset : 52 (0x34)Size : 22 bytes (0x16)Link : SHN_UNDEFInfo : 0Alignment : 2Entry Size : 0====================================
fromelf -v startup_stm32f10x_xl.o====================================** Section #3Name : RESETType : SHT_PROGBITS (0x00000001)Flags : SHF_ALLOC (0x00000002)Addr : 0x00000000File Offset : 52 (0x34)Size : 304 bytes (0x130)Link : SHN_UNDEFInfo : 0Alignment : 4Entry Size : 0========================================================================** Section #5Name : .textType : SHT_PROGBITS (0x00000001)Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)Addr : 0x00000000File Offset : 924 (0x39c)Size : 56 bytes (0x38)Link : SHN_UNDEFInfo : 0Alignment : 4Entry Size : 0====================================
可以看到,目标文件中的代码段地址都是0。
链接后生成的axf文件:
fromelf -v STM32F103_study.axf========================================================================** Section #1Name : ER_IROM1Type : SHT_PROGBITS (0x00000001)Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006)Addr : 0x08000000File Offset : 52 (0x34)Size : 720 bytes (0x2d0)Link : SHN_UNDEFInfo : 0Alignment : 4Entry Size : 0====================================
已经分配了实际的地址:0x08000000
重定位表
由于a.c文件中引用了shared全局变量和外部函数swap(),在链接过程中需要对其重定位。
看a.o的重定位表:
在文件偏移0x02F0处,共16个字节。
共2个表项,每个重定位表项占用8个字节:
/* Relocation table entry without addend (in section of type SHT_REL). */typedef struct
{Elf32_Addr r_offset; /* Address */Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
前面4个字节为重定位符号在段中的偏移地址。后面4个字节为信息项。
r_info中包含重定位类型和需要重定位的符号在符号表中的索引值。
举例来说,一个跟函数重定位相关的重定位项中的r_info会给出该函数符号在符号表中的索引值。如果索引值是STN_UNDEF(0),证明符号是未定义的,那么重定位过程中将使用0作为该符号的符号数值(st_value)。
重定位类型是处理器相关的一种属性。
可以使用宏ELF32_R_SYM(或者ELF64_R_SYM)和宏ELF32_R_TYPE(或者ELF64_R_TYPE)分别得到需要重定位的符号的符号表索引值以及重定位类型。
#define ELF32_R_SYM(val) ((val) >> 8) //得到符号表的索引
#define ELF32_R_TYPE(val) ((val) & 0xff) //得到type
#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
低8位(1个字节)为类型,高24位为符号索引。
对照a.o文件,第1个重定位表项的地址为0x0000000A,类型为10(0x0A),索引为10(0x0A);
第2个重定位表项的地址为0x00000014,类型为2,索引为9.
fromelf -r a.o** Section #6 '.reli.main' (SHT_REL)Size : 16 bytes (alignment 4)Symbol table #5 '.symtab'2 relocations applied to section #1 'i.main'# Offset Relocation Type Wrt Symbol Defined in========================================================================0 0x0000000a 10 R_ARM_THM_CALL 10 swap Ref1 0x00000014 2 R_ARM_ABS32 9 shared Ref
对照a.o中的汇编看看这两个位置的内容:
fromelf -c a.o========================================================================** Section #1 'i.main' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]Size : 24 bytes (alignment 4)Address: 0x00000000$ti.mainmain0x00000000: b508 .. PUSH {r3,lr}0x00000002: 2064 d MOVS r0,#0x640x00000004: 9000 .. STR r0,[sp,#0]0x00000006: 4903 .I LDR r1,[pc,#12] ; [shared = 0x14] = 00x00000008: 4668 hF MOV r0,sp0x0000000a: f7fffffe .... BL swap0x0000000e: 2000 . MOVS r0,#00x00000010: bd08 .. POP {r3,pc}$d0x00000012: 0000 .. DCW 00x00000014: 00000000 .... DCD 0 ; shared
从中可以看出,0x0000000A为调用swap函数,函数地址偏移量暂时为-1。0x00000014处为shared的地址,暂时为0.
地址更新与代码修正
和链接后的axf文件对比一下,BL swap的二进制代码由F7FFFFFE变成了F805F000;shared变量的地址也由00000000变成了0x20000000。
如果在b.c文件中,shared变量前面再加一个变量,比如:int x = 2,则变量x会占用0x20000000的位置,shared变量的地址会变成0x20000004.再来看看axf文件,确实变了:
《程序员的自我修养》读书笔记3——使用KEIL研究ELF文件的重定位相关推荐
- 程序员的自我修养读书笔记-1
前序:作为一个马上就要工作的非科班本科生,前段时间为了找工作,有针对性的学习了一些编程语言,数据结构,网络方面的知识,学的非常浅,非常杂乱,存粹是为了应对找工作.现在空下来了,想着以后应该就是走程序员 ...
- 程序员的自我修养 - 读书笔记文字版
第1部分 简介 第1章 温故而知新 程序在运行的时候先通过分段(segmentation)的方式将虚拟地址空间与真实的物理内存地址空间进行一一的映射,但是这种方式每次换入换出的是整个程序,导致IO变大 ...
- 程序员的自我修养——读书笔记
第一部分:温故而知新 第一章:介绍基本的背景知识--操作系统.线程.硬件 1.关于C语言中的hello world这些问题你都清楚吗? 2.计算机硬件设备的三个核心部件: 1>中央处理器CPU ...
- 程序员的自我修养阅读笔记
编译和链接 将编译和链接合并到一起的过程称为构建(Build). 从源文件生成最终可执行目标文件共有4个步骤: 预处理(Prepressing) 编译(Compilation) 汇编(Assembly ...
- 程序员的自我修养——学习笔记1
文章目录 计算机硬件 早期计算机 发展 SMP和多核 计算机软件 操作系统和设备驱动的作用 文件系统 存储设备 未使用内存管理时 解决思路:地址空间 分段 分页 线程进程 参考资料 计算机硬件 计算机 ...
- 程序员的自我修养学习笔记——第五章
PE: Portable Executable COFF: Common Object File Format 跟ELF一样,PE中也允许程序员将变量后函数放到自定义段.在GCC中使用"__ ...
- 《程序员的自我修养》笔记
第1章 引言 说明:①本书中将计算机的范围限定于PC机,更具体的讲是采用x86指令集的32位CPU的个人计算机. 1.1 CPU与外围部件的连接方式 计算机最核心的三个硬件设备是:CPU.内存.I/O ...
- 【读书笔记】程序员的自我修养总结(七)
[读书笔记]程序员的自我修养总结(七) 标签: [编程开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:这是程序员的自我修养一书的读书总结,随着阅 ...
- 【读书笔记】程序员的自我修养总结(一)
程序员的自我修养总结(一) 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:这是程序员的自我修养一书的读书总结,随着阅读的推进,逐步增加内容. 1. 关 ...
最新文章
- Nature官方劝退读博:全球七成博士对前途迷茫,36%自认有过心理疾病
- 服务器硬件及RAID配置
- 你在使用Gmail,Wallop,MSN Spaces,Three Degrees吗?
- sharepoint 弹出框
- 燕山大学数字通信计算机仿真代码,燕山大学数字通信计算机仿真课程设计模板.doc...
- 【Flink】kafka INVALID_PRODUCER_EPO send data to Kafka old epoch newer producer same transactionalId
- poj2431java_POJ 2431 Expedition
- 语音 识别_语音识别_qq语音识别 - 云+社区 - 腾讯云
- 洛谷OJ:P3811 【模板】乘法逆元(线性递推求逆元)
- Linux在线词典项目,实现注册,登陆,查询单词以及查询历史记录,退出查询等功能,(涉及网络编程,进程线程,文件io,sqlite)
- 40位40岁以下投资人
- c语言地铁系统设计,城市地铁报站系统设计.doc
- Qt的简单应用:五子棋游戏
- Ubuntu安装Nixnote,解决印象笔记(国服/中国区)登录不能显示输入密码的问题
- BASE64Encoded() 方法报错说方法未定义
- HFDS 内部工作机制
- R6034问题的解决
- 时间复杂度简述及例题
- Python就业行情和前景分析之一
- Typescript 笔记