深入理解计算机系统(链接)—— 重定位pc相对引用 重定位绝对引用 GNU READELF工具分析ELF文件

一.用GNU READELF工具分析ELF文件

1. readelf

readelf命令是Linux下的分析ELF文件的命令,在分析ELF文件时非常方便

比较常见的几条:
linux> readelf -a test.o//显示全部信息
linux> readelf -s test.o//查看.o文件符号表信息
linux> readelf -S swap.o//查看具体“节”信息

接下来给出一段代码,并对这段代码的符号表symTable进行具体分析:

/*main.c*/
void swap();
int buf[2] = {1, 2};
int main() {
	swap(); 
	return 0;
}
/*swap.c*/
extern int buf [] ;
int *bufp0 = &buf[0] ; 
int *bufp1;
void swap() {
	int temp;
	bufp1 = &buf[1]; 
	temp =*bufp0; 
	*bufp0 = *bufp1; 
	*bufp1 = temp;
}

执行指令:

linux> gcc -c swap.c -o swap.o//生成可重定位目标文件
linux> gcc -c mian.c -o main.o//生成可重定位目标文件
linux> gcc -g swap.o main.o -o run//生成可执行目标文件
linux> readelf -s swap.o 
linux> readelf -s main.o

2. 以csapp书上一道题来分析符号表:

对于每个在 swap.o 中定义或引用的符号, 请指出它是否在模块 swap.o 中的 .symtab 节中有一个符号表条目。如果是,请指出定义该符号的 模块 (swap.o 或者 main.o)、符号类型(本地、全局或者外部)和它在模块中占据的节 (.text .data 或者 .bss)?
readelf -s swap.o 查看swap.o符号表:
在这里插入图片描述

  • buf,是swap.o.symTable的条目,extern 类型的符号,在main.o模块中定义!,我们看到一个关于全局符号 buf 定义的条目,它是从 .data 中偏移为 0 处开始的一个 8 字节的已初始化目标.
  • bufp0:是swap.o.symTable的条目,global类型符号,在swap.o中定义,我们看到一个关于全局符号 bufpO 定义的条目,它是从 .data 中偏移为 0 处开始的一个 4 字节的已初始化目标
  • bufp1:是swap.o.symTabl的条目,global类型的符号,在swap.o中定义,它是一个未初始化的 4 字节数据目标(要求 4 字节对齐),最终当 这个模块被链接时它将作为一个 .bss 目标分配
  • swap:是swap.o.symTable的条目,func类型的符号,在swap.o中定义,它是一个位于 .text 中偏移为零处的 39 字节的函数。
  • temp:不属于swap.o.symTable条目,int类型的符号,在swap.o中定义,局部变量位于栈中管理。
    注:symtab存放在程序中被定义和引用的函数和全局变量的信息。Tmp不是全局变量而是本地变量,没有符号表条目

再看一下main.o文件的符号表:
在这里插入图片描述

  • buf是已经初始化的全局变量,一个位于.data节中偏移位0的8字节目标。
  • main位于.text节中偏移为0的17字节函数
  • swap 略

二.查看可执行文件的elf

指令:readelf -a run

elf头
在这里插入图片描述
分析:第一行,对应e_ident[EI_NIDENT]。小端法实际表示内容为7f454c46010101000000000000000000,前四个字节为elf固定开头7f454c46(0x45,0x4c,0x46是’e’,‘l’,'f’对应的ascii编码),表示这是一个ELF对象。接下来的一个字节01表示是一个32位对象,接下来的一个字节01表示是小端法表示,再接下来的一个字节01表示文件头版本。剩下的默认都设置为0.

ELF头以一个16字节的序列开始,这个序列描述了生成这一目标文件的系统的字的大小和字节顺序。ELF头中其余的部分包含帮助连接器语法分析和解释目标文件的信息:ELF头的大小(52)、目标文件的类型(exec 可执行目标文件)、机器类型、节头部表(section header table)的文件偏移,以及节头部表中的条目大小和数量

节部头表:section header table
在这里插入图片描述
在这里插入图片描述

二.用objdump分析重定位过程

代码的重定位条目放在.rel_text;已初始化的数据重定位条目放在.rel_data.最后就是要用到这里面的重定位信息去修改.text .data节里对每个符号的引用。

先看swap.o文件的返回编列表,并显示出重定位条目;
指令:

objdump -D -r swap.o//小写的d好像只会显示出.text节
                  //-r  表示:显示出重定位条目

1. swap.o的.data节内容:

在这里插入图片描述
bufp0被初始化为一个全局数组的地址,需要被重定位
ADDR(buf)+*refptr=0x8049620

2. swap.o的.text节内容:发生了5个重定位

在这里插入图片描述
假设buf和bufp0的地址分别是0x8049620和0x8049628,&buf1为0x8049620+ 0x4=0x8049624,bufp1的地址就是链接合并后.bss节的首地址,假定为0x8049700。

  • bufp1=&buf[1]
6:	c7 05 00 00 00 00 04 	movl   $0x4,0x0
d:	00 00 00 
			8: R_386_32	bufp1//对应bufp1重定位
			c: R_386_32	buf//对应&bufp[1]重定位

1.bufp1、buf都是引用,movl指令源操作数,目的操作数都需要重定位
2.初始值为0x4:编译的时候根据引用buf的索引为1设定。
3.这里类型都为重定位绝对引用:
对于bufp1重定位:
假设连接器已经确定ADDR(r.symbol)=ADDR(bufp1)=0x8049700
*refptr=unsigned(ADDR(r.symbol)+*refptr)=0x8049700
对于&bufp[1]:
ADDR(buf)+*refptr=0x8049620+0x4=0x8040a024
注意最后要小端法!
4.还可以根据offset算出引用运行时存储器的地址,即节的地址+偏移

  • temp=*bufp0
 10:	a1 00 00 00 00       	mov    0x0,%eax
			11: R_386_32	bufp0

bufp0是引用,要重定位。
重定位结果:0x8049628+0x0=0x8049628

  • *bufp0=*bufp1
1a:a100000000           mov 0x0, %eax
                        1b: R_ 386 32 bufp0
1f:8b 15 00 00 00 00    mov 0x0 %edx
                        21:R_38632 .bss

bufp0、bufp1都是引用,需要重定位。
1b (bufp0) : 28 96 04 08
21 (bufp1) : 00 97 04 08

  • *bufp1=temp
29:a100000000      mov 0x0,%eax
                   2a: R_ _386_ 32 .bss

bufp1是引用,需要重定位
2a (bufp1) : 00 9704 08

最终可执行目标文件:(可以和我们之前分析的结果进行验证)
在这里插入图片描述

3.main.o中的text节(发生了重定位pc相对引用)

在这里插入图片描述
以深入理解计算机系统这本书上的数据举例:
假设连接器已经确定:
ADDR(s)=ADDR(.text)=0x80483b4
ADDR(symbol)=ADDR(swap)=0x80483c8

引用的运行时地址:
refaddr=ADDR(s)+r.offset=0x80483c8+0x7=0x80483bb

引用值从-4(0xfffffffc)修改成0x9:
*refptr=(unsigned)(ADDR(symbol)+*refptr-refaddr)=0x9

最后swap程序第一条指令的地址即为:
当前pc+*refptr=0x80483bf+0x09=0x80483c8

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值