详解重定位目标文件

详解重定位目标文件_第1张图片
ELF重定位文件格式图.png

图解

  • ELF文件头
    开头16个字节描述了生成该文件的字的大小,以及字节序;
    剩余部分包含的信息可支持链接器解析和解释该目标文件,比如文件头的大小、目标文件的类型(重定位、可执行、共享)、机器类型(比如x86-64)、节头表的文件偏移量、节头表大小和条目数量等
  • .text
    保存的是被编译程序的机器码;
  • .rodata节
    保存的是只读数据,比如printf语句中的格式化字符串,及switch语句使用的jump tables等;
  • .data
    保存的是已初始化的全局变量和静态C变量;
    不保存局部C变量,因为局部C变量由运行时栈维护;
  • .bss
    保存的是未初始化的静态变量及初始化为0的全局变量和静态变量;
    .COMMON伪节里保存的是未初始化的全局变量;
    不保存局部C变量,因为局部C变量由运行时栈维护;
    .bss节不占据目标文件的空间,因为没必要;
  • .symtab
    保存的是有关在程序中定义和引用的函数或者全局变量的信息;
    每个重定位目标文件都有符号表,即.symtab节;
    跟编译器的符号表不一样,.symtab符号表不包含局部变量信息;
  • .rel.text
    保存的是.text节中需要被修正的位置信息;
    任何调用外部函数或者引用全局变量的指令都需要被修正;
    调用外部函数的指令需要重定位;
    引用全局变量的指令需要重定位;
    调用局部函数的指令不需要重定位;
    在可执行目标文件中不存在重定位信息;
  • .rel.data
    保存的是该文件引用或者定义的的全局变量的重定位信息;
    任何初始化值是某个全局变量地址的全局变量需要重定位;
    任何在外部定义的函数需要重定位;
  • .debug
  • .line
  • strtab
    保存的是在.symtab节、.debugsection header节中的Name字段中的字符串; 以null`结尾;
  • section header table
    在目标文件中的每个节都有一个节头表条目;
    节头表条目描述的是节的位置和大小信息;

示例

示例1 以SimpleSection.c为例进行说明

##############SimpleSection.c##################
int printf(const char* format, ...);

int global_init_var = 84;
int global_uninit_var;

void func1(int i) 
{
    printf("%d\n", i);
}

int main()
{
    static int static_var = 85;
    static int static_var2;
    int a = 1;
    int b;

    func1(static_var + static_var2 + a + b);
    return a;
}

#生成SimpleSection.o
gcc -Og -c SimpleSection.c

readelf -h SimpleSection.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:          944 (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: 12

readelf -S SimpleSection.o
There are 13 section headers, starting at offset 0x3b0:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000034  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  000002d0
       0000000000000048  0000000000000018   I      10     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000074
       0000000000000004  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  00000078
       0000000000000000  0000000000000000  WA       0     0     1
  [ 5] .rodata.str1.1    PROGBITS         0000000000000000  00000078
       0000000000000004  0000000000000001 AMS       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  0000007c
       000000000000002c  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000a8
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000a8
       0000000000000048  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  00000318
       0000000000000030  0000000000000018   I      10     8     8
  [10] .symtab           SYMTAB           0000000000000000  000000f0
       0000000000000180  0000000000000018          11    10     8
  [11] .strtab           STRTAB           0000000000000000  00000270
       0000000000000060  0000000000000000           0     0     1
  [12] .shstrtab         STRTAB           0000000000000000  00000348
       0000000000000068  0000000000000000           0     0     1
readelf -s SimpleSection.o

Symbol table '.symtab' contains 16 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS SimpleSection.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
     8: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    5 .LC0
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
    10: 0000000000000000    28 FUNC    GLOBAL DEFAULT    1 func1
    11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
    13: 000000000000001c    24 FUNC    GLOBAL DEFAULT    1 main
    14: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM global_uninit_var
    15: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var

#SimpleSection.o中的重定位记录
objdump -r SimpleSection.o

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000009 R_X86_64_PC32     .LC0-0x0000000000000004
0000000000000013 R_X86_64_PLT32    printf-0x0000000000000004
0000000000000026 R_X86_64_PC32     func1-0x0000000000000004

示例2 以main.csum.c为例进行说明

############main.c###############
int sum(int *a, int n);

int array[2] = {1, 2};

int main()
{
    int val = sum(array, 2);
    return val;
}
############sum.c###############
int sum(int *a, int n)
{
    int i, s = 0;

    for(int i = 0; i < n; i++){
        s += a[i];
    }
    return s;
}
在sum.o文件中没有的节:.data节、.rela.text节、.rela.data节;
在main.o文件中,由于main.c中调用了sum函数,所以需要重定位,即有.rela.text节;
#生成重定位文件
gcc -Og -c main.c sum.c

#查看sum.o的文件头
readelf -h sum.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:          528 (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:         11
  Section header string table index: 10

#查看main.o的文件头
readelf -h main.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:          704 (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:         12
  Section header string table index: 11
#查看sum.o的节头表
readelf -S sum.o
There are 11 section headers, starting at offset 0x210:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000001b  0000000000000000  AX       0     0     1
  [ 2] .data             PROGBITS         0000000000000000  0000005b
       0000000000000000  0000000000000000  WA       0     0     1
  [ 3] .bss              NOBITS           0000000000000000  0000005b
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .comment          PROGBITS         0000000000000000  0000005b
       000000000000002c  0000000000000001  MS       0     0     1
  [ 5] .note.GNU-stack   PROGBITS         0000000000000000  00000087
       0000000000000000  0000000000000000           0     0     1
  [ 6] .eh_frame         PROGBITS         0000000000000000  00000088
       0000000000000030  0000000000000000   A       0     0     8
  [ 7] .rela.eh_frame    RELA             0000000000000000  000001a0
       0000000000000018  0000000000000018   I       8     6     8
  [ 8] .symtab           SYMTAB           0000000000000000  000000b8
       00000000000000d8  0000000000000018           9     8     8
  [ 9] .strtab           STRTAB           0000000000000000  00000190
       000000000000000b  0000000000000000           0     0     1
  [10] .shstrtab         STRTAB           0000000000000000  000001b8
       0000000000000054  0000000000000000           0     0     1
#查看main.o的节头表
There are 12 section headers, starting at offset 0x2c0:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000001a  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  00000218
       0000000000000030  0000000000000018   I       9     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000060
       0000000000000008  0000000000000000  WA       0     0     8
  [ 4] .bss              NOBITS           0000000000000000  00000068
       0000000000000000  0000000000000000  WA       0     0     1
  [ 5] .comment          PROGBITS         0000000000000000  00000068
       000000000000002c  0000000000000001  MS       0     0     1
  [ 6] .note.GNU-stack   PROGBITS         0000000000000000  00000094
       0000000000000000  0000000000000000           0     0     1
  [ 7] .eh_frame         PROGBITS         0000000000000000  00000098
       0000000000000030  0000000000000000   A       0     0     8
  [ 8] .rela.eh_frame    RELA             0000000000000000  00000248
       0000000000000018  0000000000000018   I       9     7     8
  [ 9] .symtab           SYMTAB           0000000000000000  000000c8
       0000000000000120  0000000000000018          10     8     8
  [10] .strtab           STRTAB           0000000000000000  000001e8
       000000000000002d  0000000000000000           0     0     1
  [11] .shstrtab         STRTAB           0000000000000000  00000260
       0000000000000059  0000000000000000           0
#查看sum.o的代码节
objdump -j .text -S sum.o

sum.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 :
   0:   ba 00 00 00 00          mov    $0x0,%edx
   5:   b8 00 00 00 00          mov    $0x0,%eax
   a:   eb 09                   jmp    15 
   c:   48 63 ca                movslq %edx,%rcx
   f:   03 04 8f                add    (%rdi,%rcx,4),%eax
  12:   83 c2 01                add    $0x1,%edx
  15:   39 f2                   cmp    %esi,%edx
  17:   7c f3                   jl     c 
  19:   f3 c3                   repz retq
#查看main.o的代码节
objdump -j .text -S main.o

Disassembly of section .text:

0000000000000000 
: 0: 48 83 ec 08 sub $0x8,%rsp 4: be 02 00 00 00 mov $0x2,%esi 9: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 10 10: e8 00 00 00 00 callq 15 15: 48 83 c4 08 add $0x8,%rsp 19: c3 retq #`sum.o`没有数据节 #查看`main.o`的数据节 objdump -j .data -S main.o Disassembly of section .data: 0000000000000000 : 0: 01 00 00 00 02 00 00 00 #查看main.o中的`rela.text`节 objdump -r main.o RELOCATION RECORDS FOR [.text]: OFFSET TYPE VALUE 000000000000000c R_X86_64_PC32 array-0x0000000000000004 0000000000000011 R_X86_64_PLT32 sum-0x0000000000000004 #查看sum.o中的`rela.text`节 objdump -r sum.o sum.o: file format elf64-x86-64 RELOCATION RECORDS FOR [.eh_frame]: OFFSET TYPE VALUE 0000000000000020 R_X86_64_PC32 .text readelf -x .strtab main.o Hex dump of section '.strtab': 0x00000000 006d6169 6e2e6300 6d61696e 00617272 .main.c.main.arr 0x00000010 6179005f 474c4f42 414c5f4f 46465345 ay._GLOBAL_OFFSE 0x00000020 545f5441 424c455f 0073756d 00 T_TABLE_.sum. readelf -x .shstrtab main.o Hex dump of section '.shstrtab': 0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab 0x00000010 002e7368 73747274 6162002e 72656c61 ..shstrtab..rela 0x00000020 2e746578 74002e64 61746100 2e627373 .text..data..bss 0x00000030 002e636f 6d6d656e 74002e6e 6f74652e ..comment..note. 0x00000040 474e552d 73746163 6b002e72 656c612e GNU-stack..rela. 0x00000050 65685f66 72616d65 00 eh_frame.

你可能感兴趣的:(详解重定位目标文件)