加载器、链接器、动态链接器概念

动态链接器:

共享库(shared library)是致力于解决静态库缺陷的一个现代创新产物。共享库是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。这个过程称为动态链接(dynamic linking),是由一个叫做动态链接器(dynamic linker)的程序来执行的。

链接器:

将多个可重定位目标文件生成可执行目标文件的过程称为链接,完成此功能的部件称为链接器(ld)

加载器

加载器(loader)将可执行目标文件中的代码和数据从磁盘复制到内存中,然后通过跳转到程序的第一条指令或入口点来运行该程序。这个将程序复制到内存并运行的过程叫做加载。

修改一个二进制文件的动态链接器方法:

patchelf --set-interpreter /path/to/new/dynamic/linker your_program

readelf -h a.out输出ELF header的信息:

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:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x41cc40
  Start of program headers:          64 (bytes into file)
  Start of section headers:          82900248 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  # program header的大小是56字节
  Size of program headers:           56 (bytes)
  # 9个program header
  Number of program headers:         9
  # section header的大小是64字节
  Size of section headers:           64 (bytes)
  # 42个section header
  Number of section headers:         42
  Section header string table index: 39

readelf -W -S a.out输出section header的信息:

There are 42 section headers, starting at offset 0x4f0f518:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000400238 000238 00001c 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            0000000000400254 000254 000020 00   A  0   0  4
  [ 3] .note.gnu.build-id NOTE            0000000000400274 000274 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0000000000400298 000298 001574 00   A  5   0  8
  [ 5] .dynsym           DYNSYM          0000000000401810 001810 007080 18   A  6   1  8
  [ 6] .dynstr           STRTAB          0000000000408890 008890 00ab28 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          00000000004133b8 0133b8 000960 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         0000000000413d18 013d18 0001f0 00   A  6  11  8
  [ 9] .rela.dyn         RELA            0000000000413f08 013f08 004350 18   A  5   0  8
  [10] .rela.plt         RELA            0000000000418258 018258 002c40 18   A  5  12  8
  [11] .init             PROGBITS        000000000041ae98 01ae98 000018 00  AX  0   0  4
  [12] .plt              PROGBITS        000000000041aeb0 01aeb0 001d90 10  AX  0   0  4
  [13] .text             PROGBITS        000000000041cc40 01cc40 6f6418 00  AX  0   0 16
  [14] .fini             PROGBITS        0000000000b13058 713058 00000e 00  AX  0   0  4
  [15] .rodata           PROGBITS        0000000000b13080 713080 3d2a47 00   A  0   0 32
  [16] .eh_frame_hdr     PROGBITS        0000000000ee5ac8 ae5ac8 02a6ac 00   A  0   0  4
  [17] .eh_frame         PROGBITS        0000000000f10178 b10178 0c054c 00   A  0   0  8
  [18] .gcc_except_table PROGBITS        0000000000fd06c4 bd06c4 040b90 00   A  0   0  4
  [19] .tdata            PROGBITS        0000000001211260 c11260 004020 00 WAT  0   0 16
  [20] .tbss             NOBITS          0000000001215280 c15280 3ed340 00 WAT  0   0 16
  [21] .ctors            PROGBITS        0000000001215280 c15280 000878 00  WA  0   0  8
  [22] .dtors            PROGBITS        0000000001215af8 c15af8 000018 00  WA  0   0  8
  [23] .jcr              PROGBITS        0000000001215b10 c15b10 000008 00  WA  0   0  8
  [24] .data.rel.ro      PROGBITS        0000000001215b20 c15b20 03fbc8 00  WA  0   0 32
  [25] .dynamic          DYNAMIC         00000000012556e8 c556e8 000230 10  WA  6   0  8
  [26] .got              PROGBITS        0000000001255918 c55918 001618 08  WA  0   0  8
  [27] .got.plt          PROGBITS        0000000001256f30 c56f30 000ed8 08  WA  0   0  8
  [28] .data             PROGBITS        0000000001257e20 c57e20 012090 00  WA  0   0 32
  [29] .bss              NOBITS          000000000126a000 c69eb0 d1f378 00  WA  0   0 512
  [30] .comment          PROGBITS        0000000000000000 c69eb0 00002d 01  MS  0   0  1
  [31] .debug_aranges    PROGBITS        0000000000000000 c69edd 10b000 00      0   0  1
  [32] .debug_pubnames   PROGBITS        0000000000000000 d74edd 5c5559 00      0   0  1
  [33] .debug_info       PROGBITS        0000000000000000 133a436 3196bee 00      0   0  1
  [34] .debug_abbrev     PROGBITS        0000000000000000 44d1024 0f823a 00      0   0  1
  [35] .debug_line       PROGBITS        0000000000000000 45c925e 34c2d0 00      0   0  1
  [36] .debug_str        PROGBITS        0000000000000000 491552e 3ccbc5 01  MS  0   0  1
  [37] .debug_pubtypes   PROGBITS        0000000000000000 4ce20f3 0ecf79 00      0   0  1
  [38] .debug_ranges     PROGBITS        0000000000000000 4dcf06c 140310 00      0   0  1
  [39] .shstrtab         STRTAB          0000000000000000 4f0f37c 000198 00      0   0  1
  [40] .symtab           SYMTAB          0000000000000000 4f0ff98 7c0938 18     41 312397  8
  [41] .strtab           STRTAB          0000000000000000 56d08d0 3433eb 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

# 后面缩写的ES Flg Lk Inf Al每一列的含义:
# ES == sh_entsize, Lk == sh_link, Inf == sh_info and Al == sh_addalign.

readelf -W -l a.out输出program header的信息:

Elf file type is EXEC (Executable file)
Entry point 0x41cc40
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8
  INTERP         0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0xc11254 0xc11254 R E 0x200000
  LOAD           0xc11260 0x0000000001211260 0x0000000001211260 0x058c50 0xd78118 RW  0x200000
  DYNAMIC        0xc556e8 0x00000000012556e8 0x00000000012556e8 0x000230 0x000230 RW  0x8
  NOTE           0x000254 0x0000000000400254 0x0000000000400254 0x000044 0x000044 R   0x4
  TLS            0xc11260 0x0000000001211260 0x0000000001211260 0x004020 0x3f1360 R   0x10
  GNU_EH_FRAME   0xae5ac8 0x0000000000ee5ac8 0x0000000000ee5ac8 0x02a6ac 0x02a6ac R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table 
   03     .tdata .ctors .dtors .jcr .data.rel.ro .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .tdata .tbss 
   07     .eh_frame_hdr 
   08     

查看具体哪个section内容的16进制显示以及它的ascii字符串显示:

# 查看.interp的内容
readelf -W -x .strtab a.out
Hex dump of section '.interp':
  0x00400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-
  0x00400248 7838362d 36342e73 6f2e3200          x86-64.so.2.

参考链接:

  1. 深入浅出ELF https://zhuanlan.zhihu.com/p/254882216
  2. 程序的本质之二ELF文件的文件头、section header和program header https://blog.csdn.net/npy_lp/article/details/102604380
  3. readelf -l输出section header每一列的含义 https://stackoverflow.com/a/15870451/2873403
posted @ 2023-07-19 15:35  bug批发零售  阅读(616)  评论(0)    收藏  举报