计算机原理系列之四 ——– 可重定位文件详解

欢迎访问我的个人博客: luomuxiaoxiao.com



上篇文章我们从整体上介绍了从C文件到可执行文件的编译过程,并逐个分析了单步编译时生成的中间文件的类型。为了搞清楚编译和链接过程中主要做了哪些工作, 我们应该首先明白编译前后,链接前后文件内容的改变。根据上篇文章内容, 编译前的文件格式是汇编文件,编译后的文件是可重定位文件。汇编文件就是简单的文本文件,而可重定位文件是一个ELF格式的二进制文件。因此,本章我们将从ELF文件格式入手分析 可重定位文件的结构。

下面我们以C语言中经典的“hello, world”的产生的可重定位文件为例来说明。使用的环境如下:

  • ubuntu 64位操作系统
  • gcc作为编译工具(版本信息:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10))

一、生成中间文件

我们依然使用计算机原理系列之三 -------- 如何编译目标文件中的hello.c文件来研究,使用下列命令生成hello.o:

gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o

二、可重定位文件分析

2.1 解析文件头,说明文件构成

由于可重定位文件类型是ELF格式(关于ELF文件的知识,请阅读详解ELF文件),我们可以使用READELF命令查看其构成。

$ readelf -h hello.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          672 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10

其中,我们关注以下字段:

  1. Type: REL (Relocatable file) : 可以看出.o文件的类型为可重定位文件
  2. Number of program headers: 0:可以看出可重定位文件program header table的长度为0。这是因为program header table保存的是segment信息,而segment是为了给加载器提供可执行程序在加载时所需的信息的,又因为可重定位文件本身并不能直接执行,因此在可重定位文件里不需要program header table
  3. Entry point address: 0x0: 同上,由于可重定位文件不能直接执行,因此其入口地址为0(默认值);
  4. *** of section headers:***:从ELF文件起始地址偏移672个字节处是section header table的起始地址,section header table中共有13项,每项的大小为64 byte
  5. Size of this header: 64: ELF文件头大小为64 byte

2.2 分析ELF文件各部分

可重定位文件属于二进制文件。在linux机器上,可以使用hexdump命令来查看二进制文件的内容。

$ hexdump -C hello.o
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 3e 00 01 00 00 00  00 00 00 00 00 00 00 00  |..>.............|
00000020  00 00 00 00 00 00 00 00  a0 02 00 00 00 00 00 00  |................|
00000030  00 00 00 00 40 00 00 00  00 00 40 00 0d 00 0a 00  |....@.....@.....|
00000040  55 48 89 e5 bf 00 00 00  00 e8 00 00 00 00 b8 00  |UH..............|
00000050  00 00 00 5d c3 68 65 6c  6c 6f 2c 20 77 6f 72 6c  |...].hello, worl|

... snip ...

这实际上就是hello.o文件的实际内容。

注:

  • 最前面一列是hexdump命令添加的,并非ELF文件的内容。它是一个十六进制的数字,表示字节序号。例如,00000040 55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00,其中00000400x40,十进制为64。表示hello.o文件的第64个字节是‘55’
  • 最后一部分由两个‘|’包含的数字和字符也是hexdump命令添加的,它将其左侧的十六进制数字转化成了对应的ASCII字符,所有的控制字符表示为‘.’,所有的可显示字符表示为对应的字符或图形。
2.2.1 ELF header

根据ELF文件的结构,ELF文件最开始的部分是ELF header,它是一个64字节大小的结构体,也就是对应了hello.o的前64个字符,即从0000000 - 00000040的部分。前十六个字节应该是对应其magic number的部分。我们注意到,从0000000 - 0000000F正好就是使用readelf读出来的magic的值。剩下的部分只要结合struct ElfN_Ehdr的成员信息和hexdump命令输出的内容即可一一验证。

请点击此处继续阅读


想第一时间查看我的文章吗?请关注我的微信公众号号,搜索“落木萧萧技术论坛”或登陆我的个人博客:www.luomuxiaoxiao.com,更多精彩文章等你。

qrcode
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值