C程序中各个段的含义

首先应该知道几个查看段信息的指令:
readelf -S file 查看各个段的名称,地址,大小等信息
objdump -s file 查看各个段的二进制和字符格式内容
hexdump -C file 查看整个二进制文件的二进制和字符格式内容
(1).text 程序的正文段,一般为本文件中的函数指令
(2).data 程序的数据段,一般静态变量和初始化的全局变量定义在此
(3).bss 也是程序的数据段,一般包括未初始化的全局变量
(4).interp 此程序在加载时所需要使用的动态连接器的位置

Contents of section .interp:
 400200 2f6c6962 36342f6c 642d6c69 6e75782d  /lib64/ld-linux-
 400210 7838362d 36342e73 6f2e3200           x86-64.so.2. 

说明当前程序需要加载时,使用到/lib64/ld-linux-x86-64.so.2这个动态链接器
(5).rodata 只读数据,比如说C++中的const变量,字符串常量,比如说程序中有这么一段:

printf("in main.c a=%d\n", a);
printf("in main.c &a=%p\n", &a);

对应.rodata的内容:

Contents of section .rodata:
 4007a0 01000200 696e206d 61696e2e 6320613d  ....in main.c a=
 4007b0 25640a00 696e206d 61696e2e 63202661  %d..in main.c &a
 4007c0 3d25700a 00                          =%p..  

(6).symtab 符号表信息(readelf -s file),可以看出各个符号的地址
(7).strtab 字符串表信息,一般和符号表中符号对应的字符串对应
(8).rela.text 一般中间对象文件会有这个段,因为text段引用了其他外部函数
(9).got 用于动态链接,保存代码段中引用动态链接库中数据的地址,一般在运行时确定
(10).got.plt 类似于.got,保存代码段中引用动态链接库中函数的地址,一般在运行时确定
(11).plt 用于动态链接时的延迟绑定,运行时,当遇到动态链接库中的函数或数据时,会跳到这个段内,用于解析地址
(12).rela.dyn 用于查看.got段和数据段(一般是.bss)需要修正的符号
(13).rela.plt 用于查看需要修正.got.plt中的数据
针对(12)(13)举个例子:
有两个文件a.c b.c,a.c编译成动态链接库,b.c为主程序:

//a.c
int a = 2;
void foo(void)
{
    a++;
    return;
}
//b.c
#include <stdio.h>
extern int a;
extern void foo(void);
int main(void)
{
    a = a+1;
    foo();
    return 0;
}

按上面的要求进行编译,分别查看a.so和b的。rela.dyn和rela.plt内容

$ readelf -r a.so
Relocation section '.rela.dyn' at offset 0x3e0 contains 9 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000002008b0  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
0000002008b8  000800000006 R_X86_64_GLOB_DAT 0000000000200900 a + 0
$ readelf -r b
Relocation section '.rela.dyn' at offset 0x4b0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600a00  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600a40  000800000005 R_X86_64_COPY     0000000000600a40 a + 0

Relocation section '.rela.plt' at offset 0x4e0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600a20  000400000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000600a28  000600000007 R_X86_64_JUMP_SLO 0000000000000000 foo + 0

从上面的信息可以看出,对于a.so变量a位于.got段,对于b来说,变量a也需要重定向,位于.bss段,在.rela.dyn中说明此符号需要重定位,并且b引用了foo这个动态链接库函数,在.rela.plt中给出信息需要在.got.plt中重定位。
(14).dynsym段,类似于.symtab,也是一个符号表,但是这个符号表只记录与动态链接有关的符号
(15).dynstr段,类似于.strtab,记录动态链接符号的字符串表
(16).hash段,由于动态链接的时候需要快速查找,因此使用了一个哈希表,用来记录符号的地址。
(17).dynamic 是和记录动态链接属性的一些信息,比如说:动态链接重定位表的位置,.got的位置,.got.plt的位置等。

猜你喜欢

转载自blog.csdn.net/whoami_I/article/details/82685748
今日推荐