《编译系统-自底向上研究方法》ELF头部 ,之前这篇文章讲解了 ELF 的头部,头部有几个段表的字段,当时没有仔细讲解。
1,e_shoff
,段表的指针,也就是段表在 main
文件的偏移值。
2,e_shensize
,段表中单个段的大小。
3,e_shnum
,段表中 段的数量。
再次用 xelfviewer
打开 main 文件,如下:
注意看上图用 红笔 圈出来的字段,这些都是 16 进制的。可以看到 e_shoff
的值是 0x1948 ,也就是 6472 ,所以 main 文件 从第6472 字节开始就是 段表的内容,因为一个段大小是 0x40 字节,所以 第 6472 ~ 6536 字节是第一个段的内容,第 6537 ~ 6660 字节是第二个段的内容,以此类推。一共有 e_shnum
(28)个段。
段其实是一个 Elf64_Shdr
结构体定义的,在在 /usr/include/elf.h
文件里面,如下:
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
Elf64_Xword sh_flags; /* Section flags */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Section size in bytes */
Elf64_Word sh_link; /* Link to another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
Elf64_Shdr
这个结构体就是 0x40 字节大小。
下面就 从 第 6472 字节开始分析 段表的各个段的内容。还是用 xelfviewer
,版本是0.04,直接点击左边的 Sections
选项即可,Sections 就是 段,如下图:
从上图可以看到,中间这个表格的列就是按照 Elf64_Shdr
结构体解析出来的。不过要注意一下 底部的 十六进制 ,我用红笔圈出来的,这个不是 Elf64_Shdr
结构体 对应的十六进制。而是 段 对应的 value,可以看到第二个段的 sh_addr
是 0x238 ,低下 的也是从 0x238 位置开始的内容。这个等下会详细讲解。
现在先来验证一个问题,之前说 段表是 从 main文件的 第 0x1948 字节 开始解析的,用 notepad++ 来看看是不是,如下图:
从上图可以看到,xelfviewer
跟 notepad++
两个软件的数据都能对得上,证明之前的说法没有问题。段表确实是 从0x1948 开始解析的。
段表的第一个段,通常是空,也就是全都是 0 ,不用管他。从第二个段开始分析,第二个段的 sh_name
字段是 1b
,这个 1b
是什么东西呢?实际上,这也是一个偏移值,通过偏移找到真正的字符串,而不是把字符串直接存在 sh_name
字段。
那这个 1b 是哪个地方的偏移呢?在 ELF 头部,之前有个字段没有讲,就是 e_shstrndx
字段,全称 Section header string table index
,翻译是 段字符串表的索引值,他的值是 0x1b ,也就是 27 ,这是一个下标值。之前说过 段表里面有 28个段,所以 字符串表 就是 最后一个段,如下图:
注意看上图的段,他的 sh_offset
是 0x1848 ,这个段的 value 是 从 main 文件的 第 0x1848 字节开始的。所以 第二个段的 sh_name
就是 0x1848 + 0x1b 等于 0x1863 的位置,直接用 notepad++ 查看这个位置的数据,如下:
可以看到,这个位置,就是 interp
字符串。字符串以 00 结尾的。xelfviewer
为了方便查看,倒数第二列的 Name
就是这样解析显示出来的。
讲解到这里,是时候画一张数据结构体,首先是 头部Elf64_Ehdr
指出 段表的开始位置,字符串段 的下标。然后段表里面包含各个段,段里还有一个 sh_offset
指针,指向真正的value位置。
本文只讲了 段结构体 Elf64_Shdr
的 sh_name
,sh_offset
,其他字段,读者自行百度搜索关键词,或者阅读 《程序员的自我修养》第3,4章节即可。
由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1,QQ:2338195090。