精华内容
下载资源
问答
  • 重定位文件详解

    2021-03-26 20:41:22
    重定位文件是一个ELF格式的二进制文件,这里从ELF文件格式入手分析可重定位文件的结构。 生成可重定位文件 使用代码如下 #include<stdio.h> int main() { printf("hello world\n"); return 0; } ...

    目录

    生成可重定位文件

    可重定位文件分析

    解析文件头

    分析ELF文件各部分

    ELF header

    section header table 及 sections


     

    可重定位文件是一个ELF格式的二进制文件,这里从ELF文件格式入手分析可重定位文件的结构。

    生成可重定位文件

    使用代码如下

    #include<stdio.h>
    
    int main()
    {
        printf("hello world\n");
        return 0;
    }

    生成文件指令

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

     

    可重定位文件分析

    解析文件头

    使用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:          792 (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:         14 
      Section header string table index: 13

    关注如下字段:

    Type: REL (Relocatable file)

    说明 .o 文件的类型为可重定位文件

    Number of program headers: 0

    可以看出可重定位文件的 program header table 的长度为 0 。因为 program header table 保存的是 segment 信息,而 segment 是为了给加载器提供可执行程序在加载时所需的信息的,又因为可重定位文件本身并不能直接执行,因此在可重定位文件里不需要 program header table 。

    Entry point address: 0x0

    由于可重定位文件不能直接执行,因此入口地址为 0(默认值)。

    Start of section headers :

    从ELF文件起始地址偏移 792 个字节处是 section header table 的起始地址,section header table 中有 14 项,每项的大小为 64 byte

    Size of section headers: 64 (bytes)

    ELF文件头大小为 64 byte。

     

    分析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  18 03 00 00 00 00 00 00  |................| 
    00000030  00 00 00 00 40 00 00 00  00 00 40 00 0e 00 0d 00  |....@.....@.....| 
    00000040  f3 0f 1e fa 55 48 89 e5  48 8d 3d 00 00 00 00 e8  |....UH..H.=.....| 
    00000050  00 00 00 00 b8 00 00 00  00 5d c3 68 65 6c 6c 6f  |.........].hello| 
    00000060  20 77 6f 72 6c 64 00 00  47 43 43 3a 20 28 55 62  | world..GCC: (Ub| 
    00000070  75 6e 74 75 20 39 2e 33  2e 30 2d 31 37 75 62 75  |untu 9.3.0-17ubu| 
    00000080  6e 74 75 31 7e 32 30 2e  30 34 29 20 39 2e 33 2e  |ntu1~20.04) 9.3.| 
    00000090  30 00 00 00 00 00 00 00  04 00 00 00 10 00 00 00  |0...............| 
    000000a0  05 00 00 00 47 4e 55 00  02 00 00 c0 04 00 00 00  |....GNU.........| 
    000000b0  03 00 00 00 00 00 00 00  14 00 00 00 00 00 00 00  |................| 
    000000c0  01 7a 52 00 01 78 10 01  1b 0c 07 08 90 01 00 00  |.zR..x..........| 
    000000d0  1c 00 00 00 1c 00 00 00  00 00 00 00 1b 00 00 00  |................| 
    000000e0  00 45 0e 10 86 02 43 0d  06 52 0c 07 08 00 00 00  |.E....C..R......| 
    000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000100  00 00 00 00 00 00 00 00  01 00 00 00 04 00 f1 ff  |................| 
    00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000120  00 00 00 00 03 00 01 00  00 00 00 00 00 00 00 00  |................| 
    00000130  00 00 00 00 00 00 00 00  00 00 00 00 03 00 03 00  |................| 
    00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000150  00 00 00 00 03 00 04 00  00 00 00 00 00 00 00 00  |................| 
    00000160  00 00 00 00 00 00 00 00  00 00 00 00 03 00 05 00  |................| 
    00000170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000180  00 00 00 00 03 00 07 00  00 00 00 00 00 00 00 00  |................| 
    00000190  00 00 00 00 00 00 00 00  00 00 00 00 03 00 08 00  |................| 
    000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000001b0  00 00 00 00 03 00 09 00  00 00 00 00 00 00 00 00  |................| 
    000001c0  00 00 00 00 00 00 00 00  00 00 00 00 03 00 06 00  |................| 
    000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000001e0  09 00 00 00 12 00 01 00  00 00 00 00 00 00 00 00  |................| 
    000001f0  1b 00 00 00 00 00 00 00  0e 00 00 00 10 00 00 00  |................| 
    00000200  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000210  24 00 00 00 10 00 00 00  00 00 00 00 00 00 00 00  |$...............| 
    00000220  00 00 00 00 00 00 00 00  00 68 65 6c 6c 6f 2e 63  |.........hello.c| 
    00000230  00 6d 61 69 6e 00 5f 47  4c 4f 42 41 4c 5f 4f 46  |.main._GLOBAL_OF| 
    00000240  46 53 45 54 5f 54 41 42  4c 45 5f 00 70 75 74 73  |FSET_TABLE_.puts| 
    00000250  00 00 00 00 00 00 00 00  0b 00 00 00 00 00 00 00  |................| 
    00000260  02 00 00 00 05 00 00 00  fc ff ff ff ff ff ff ff  |................| 
    00000270  10 00 00 00 00 00 00 00  04 00 00 00 0c 00 00 00  |................| 
    00000280  fc ff ff ff ff ff ff ff  20 00 00 00 00 00 00 00  |........ .......| 
    00000290  02 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000002a0  00 2e 73 79 6d 74 61 62  00 2e 73 74 72 74 61 62  |..symtab..strtab| 
    000002b0  00 2e 73 68 73 74 72 74  61 62 00 2e 72 65 6c 61  |..shstrtab..rela| 
    000002c0  2e 74 65 78 74 00 2e 64  61 74 61 00 2e 62 73 73  |.text..data..bss| 
    000002d0  00 2e 72 6f 64 61 74 61  00 2e 63 6f 6d 6d 65 6e  |..rodata..commen| 
    000002e0  74 00 2e 6e 6f 74 65 2e  47 4e 55 2d 73 74 61 63  |t..note.GNU-stac| 
    000002f0  6b 00 2e 6e 6f 74 65 2e  67 6e 75 2e 70 72 6f 70  |k..note.gnu.prop| 
    00000300  65 72 74 79 00 2e 72 65  6c 61 2e 65 68 5f 66 72  |erty..rela.eh_fr| 
    00000310  61 6d 65 00 00 00 00 00  00 00 00 00 00 00 00 00  |ame.............| 
    00000320  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    * 
    00000350  00 00 00 00 00 00 00 00  20 00 00 00 01 00 00 00  |........ .......| 
    00000360  06 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000370  40 00 00 00 00 00 00 00  1b 00 00 00 00 00 00 00  |@...............| 
    00000380  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000390  00 00 00 00 00 00 00 00  1b 00 00 00 04 00 00 00  |................| 
    000003a0  40 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |@...............| 
    000003b0  58 02 00 00 00 00 00 00  30 00 00 00 00 00 00 00  |X.......0.......| 
    000003c0  0b 00 00 00 01 00 00 00  08 00 00 00 00 00 00 00  |................| 
    000003d0  18 00 00 00 00 00 00 00  26 00 00 00 01 00 00 00  |........&.......| 
    000003e0  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000003f0  5b 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[...............| 
    00000400  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000410  00 00 00 00 00 00 00 00  2c 00 00 00 08 00 00 00  |........,.......| 
    00000420  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000430  5b 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |[...............| 
    00000440  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000450  00 00 00 00 00 00 00 00  31 00 00 00 01 00 00 00  |........1.......| 
    00000460  02 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000470  5b 00 00 00 00 00 00 00  0c 00 00 00 00 00 00 00  |[...............| 
    00000480  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000490  00 00 00 00 00 00 00 00  39 00 00 00 01 00 00 00  |........9.......| 
    000004a0  30 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |0...............| 
    000004b0  67 00 00 00 00 00 00 00  2b 00 00 00 00 00 00 00  |g.......+.......| 
    000004c0  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    000004d0  01 00 00 00 00 00 00 00  42 00 00 00 01 00 00 00  |........B.......| 
    000004e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000004f0  92 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000500  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000510  00 00 00 00 00 00 00 00  52 00 00 00 07 00 00 00  |........R.......| 
    00000520  02 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000530  98 00 00 00 00 00 00 00  20 00 00 00 00 00 00 00  |........ .......| 
    00000540  00 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00  |................| 
    00000550  00 00 00 00 00 00 00 00  6a 00 00 00 01 00 00 00  |........j.......| 
    00000560  02 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000570  b8 00 00 00 00 00 00 00  38 00 00 00 00 00 00 00  |........8.......| 
    00000580  00 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00  |................| 
    00000590  00 00 00 00 00 00 00 00  65 00 00 00 04 00 00 00  |........e.......| 
    000005a0  40 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |@...............| 
    000005b0  88 02 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................| 
    000005c0  0b 00 00 00 09 00 00 00  08 00 00 00 00 00 00 00  |................| 
    000005d0  18 00 00 00 00 00 00 00  01 00 00 00 02 00 00 00  |................| 
    000005e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    000005f0  f0 00 00 00 00 00 00 00  38 01 00 00 00 00 00 00  |........8.......| 
    00000600  0c 00 00 00 0a 00 00 00  08 00 00 00 00 00 00 00  |................| 
    00000610  18 00 00 00 00 00 00 00  09 00 00 00 03 00 00 00  |................| 
    00000620  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000630  28 02 00 00 00 00 00 00  29 00 00 00 00 00 00 00  |(.......).......| 
    00000640  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    00000650  00 00 00 00 00 00 00 00  11 00 00 00 03 00 00 00  |................| 
    00000660  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 
    00000670  a0 02 00 00 00 00 00 00  74 00 00 00 00 00 00 00  |........t.......| 
    00000680  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................| 
    * 
    00000698

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

    NOTE:

    1. 最前面一列是 hexdump 命令添加的,并非 ELF 文件的内容。它是一个十六进制的数字,表示字节序号。如 00000040 f3 0f 1e fa 55 48 89 e5 ,其中 00000040,即 0x40,十进制为64表示hello.o文件的第64个字节为 'f3'
    2. 最后一部分由两个 '|' 包含的数字和字符也是hexdump命令添加的,它将其左侧的十六进制数字转化成了对应的ASCII字符,所有的控制字符表示为 '.',所有的可显示字符表示为对应的字符或图形。

    ELF header

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

    section header table 及 sections

    由于不存在 program header table,ELF header 后就是 section。使用下述命令查看 section header table

    $ readelf -S hello.o 
    There are 14 section headers, starting at offset 0x318: 
     
    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] .rela.text        RELA             0000000000000000  00000258 
           0000000000000030  0000000000000018   I      11     1     8 
      [ 3] .data             PROGBITS         0000000000000000  0000005b 
           0000000000000000  0000000000000000  WA       0     0     1 
      [ 4] .bss              NOBITS           0000000000000000  0000005b 
           0000000000000000  0000000000000000  WA       0     0     1 
      [ 5] .rodata           PROGBITS         0000000000000000  0000005b 
           000000000000000c  0000000000000000   A       0     0     1 
      [ 6] .comment          PROGBITS         0000000000000000  00000067 
           000000000000002b  0000000000000001  MS       0     0     1 
      [ 7] .note.GNU-stack   PROGBITS         0000000000000000  00000092 
           0000000000000000  0000000000000000           0     0     1 
      [ 8] .note.gnu.propert NOTE             0000000000000000  00000098 
           0000000000000020  0000000000000000   A       0     0     8 
      [ 9] .eh_frame         PROGBITS         0000000000000000  000000b8 
           0000000000000038  0000000000000000   A       0     0     8 
      [10] .rela.eh_frame    RELA             0000000000000000  00000288 
           0000000000000018  0000000000000018   I      11     9     8 
      [11] .symtab           SYMTAB           0000000000000000  000000f0 
           0000000000000138  0000000000000018          12    10     8 
      [12] .strtab           STRTAB           0000000000000000  00000228 
           0000000000000029  0000000000000000           0     0     1 
      [13] .shstrtab         STRTAB           0000000000000000  000002a0 
           0000000000000074  0000000000000000           0     0     1 
    Key to Flags: 
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info), 
      L (link order), O (extra OS processing required), G (group), T (TLS), 
      C (compressed), x (unknown), o (OS specific), E (exclude), 
      l (large), p (processor specific)

    计算 section 的分布方法如下

    .text 偏移为0x40,即在ELF Header之后第一个 section,然后下一个是 0x40 + 0x1b = 0x5b

    找到为 .data,以后计算类似

    通过上面的方法,就可以推断出各个 section 的顺序。

    各个 section 的详细内容如下:

    • .text段保存了可执行代码经过汇编之后的内容;
    • .data和.bss并没有占据任何空间,原因是代码中并未定义局部变量或者全局变量;
    • .rodata的起始地址是0x5b,占据0xc个字节的空间,根据hexdump命令输出的信息,其内容应该是:c3 68 65 6c 6c 6f 20 77 6f 72 6c 64,根据ASCII表,其对应的字符为:h e l l o , w o r l d NULL。正好就是我们的C代码中唯一的一个需要保存到 .rodata 段的字符串常量”hello, world”;

     

    .commont的起始地址是0x67,大小为0x2b byte,将hexdump内容截取出来,并转化成ASCII字符为:GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0,可以看出正好就是我们在前面介绍开发环境的时候使用的GCC版本信息;

    • .strtab指的是string table,起始地址是0x228,大小为0x29 byte,将hexdump内容截取出来,并转化成ASCII字符为:hello.c .main._GLOBAL_OFFSET_TABLE_.puts,可见其中保存了原C文件中的文件名和函数名等信息;

    • .shstrtab指的是 section header string table,经过同上分析,其中保存了各个section的名字;
    • .symtab保存了符号表,其中包括了.strtab里面定义的三个符号;每个符号对应的符号表是一个Elf64_Symbol结构体。除了包含.strtab外,符号表中还包含了一些section的符号表条目,这些条目给链接的时候需要和其他可重定位文件或者库的对应的section合并时提供了必要的信息。在上述例子中,其.symtab的内容如下:
    $ readelf -s hello.o 
     
    Symbol table '.symtab' contains 13 entries: 
       Num:    Value          Size Type    Bind   Vis      Ndx Name 
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.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 SECTION LOCAL  DEFAULT    9 
         9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
        10: 0000000000000000    27 FUNC    GLOBAL DEFAULT    1 main 
        11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_ 
        12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts
    • .eh_frame:其内部存放了以DWARF格式保存的一些调试信息。
    • .rel.text:包含了代码段中引用的外部函数和全局变量的重定位条目。上述hello.o文件中我们得到它的.rel.text的内容包括:
    $ readelf -r hello.o 
     
    Relocation section '.rela.text' at offset 0x258 contains 2 entries: 
      Offset          Info           Type           Sym. Value    Sym. Name + Addend 
    00000000000b  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4 
    000000000010  000c00000004 R_X86_64_PLT32    0000000000000000 puts - 4
    • .rela.eh_frame:这个section同.rel.text一样属于重定位信息的section,只不过它包含的是eh_frame的重定位信息,内容如下
    $ readelf -r hello.o 
     
    Relocation section '.rela.text' at offset 0x258 contains 2 entries: 
      Offset          Info           Type           Sym. Value    Sym. Name + Addend 
    00000000000b  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4 
    000000000010  000c00000004 R_X86_64_PLT32    0000000000000000 puts - 4 
     
    Relocation section '.rela.eh_frame' at offset 0x288 contains 1 entry: 
      Offset          Info           Type           Sym. Value    Sym. Name + Addend 
    000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0

     

    展开全文
  • gcc的结果输出是后缀名不相关的,只与输入参数有关 为了构造可执行文件,连接器必须完成两个主要任务: 符号解析(symbol resolution),重定位(relocation) 目标文件有三种形式: •可重定位目标文件。包含二进制...

    1.gcc组成

    gcc是一组编译工具的总称,包括:C编译器、C++编译器、源码预处理程序和库文件。

    2.gcc编译

    1.生成一个程序

    7dbb2301e6beee5ab278a51510f937bc.png

    gcc hello.c -o hello 把hello.c编译成一个可执行程序

    如果gcc hello.c不指定输出名,生成一个a.out文件。

    可以通过./hello或者./a.out来运行程序

    2.gcc编译步骤(包括预处理preprocessor,编译compiler,汇编assemble,链接linker)

    预处理:gcc -E hello.c -o hello.i      完成对代码的预处理

    处理源文件中以“#”开头的预编译指令,包括:

    – 处理所有条件预编译指令,如“#if”,“#ifdef”, “#endif”等

    – 插入头文件到“#include”处,可以递归方式进行处理

    – 删除所有的注释“//”和“/* */”

    – 添加行号和文件名标识,以便编译时编译器产生调试用的行号信息

    – 保留所有#pragma编译指令(编译器需要用)

    • 经过预编译处理后,得到的是预处理文件(如,hello.i) ,

    它还是一个可读的文本文件 ,但不包含任何宏定义

    编译: gcc -S hello.i -o hello.s     gcc –S hello.c –o hello.s 将源代码编译成汇编代码

    • 编译过程就是将预处理后得到的预处理文件(如 hello.i)

    进行 词法分析、语法分析、语义分析、优化后,生成汇编代码文

    • 经过编译后,得到的汇编代码文件(如 hello.s)还是可读的文 本文件,CPU无法理解和执行它

    gcc命令实际上是具体程序(如ccp、cc1、as等)的包装命令,

    用户通过gcc命令来使用具体的预处理程序ccp、编译程序cc1和汇编程序as等

    汇编:gcc -c hello.s -o hello.o ,  gcc -c hello.c -o hello.o ,  as hello.s -o hello.o

    (as是一个汇编程序)将汇编代码转换成可重定位目标文件(二进制)

    • 汇编程序(汇编器)用来将汇编语言源程序转换为机器指令序列 (机器语言程序)

    • 汇编指令和机器指令一一对应,前者是后者的符号表示,它们都 属于机器级指令,

    所构成的程序称为机器级代码

    • 汇编结果是一个可重定位目标文件(如,hello.o),其中包含 的是

    不可读的二进制代码,必须用相应的工具软件来查看其内容

    链接:gcc hello.o -o hello

    将目标代码和所需要的库链成一个完整的应用程序。

    gcc的结果输出是后缀名不相关的,只与输入参数有关

    为了构造可执行文件,连接器必须完成两个主要任务:

    符号解析(symbol resolution),重定位(relocation)

    目标文件有三种形式:

    •可重定位目标文件。包含二进制代码和数据,其形式可以在编译时与其他可重定位

    目标文件合并起来,创建一个可执行目标文件。

    •可执行目标文件。包括二进制代码和数据,其形式可以被直接复制到内存并执行。

    •共享目标文件。一种特殊类型的可重定位目标文件,可以在加载或者运行

    时被动态的加载进内存并链接。

    3.使用多个源码的项目

    比如有两个源程序main.c和sum.c

    使用gcc编译器并链接生成可执行程序p:gcc -O2 -g -o p main.c sum.c     ./p

    -O2:2级优化

    -g:生成调试信息

    -o:目标文件名

    de0e80db99c934068ab0969a0ba65576.png

    链接过程的本质(以main.c和swap.c为例)

    main.c                          swap.c

    int buf[2] = {1, 2};                extern int buf[];

    void swap();                       int *bufp0 = &buf[0];

    int main()static int *bufp1;

    { swap();void swap() {

    return 0; }int temp;bufp1 = &buf[1];temp = *bufp0;*bufp0 = *bufp1;*bufp1 = temp; }

    3ae68b18ae057a05c0aa7132bad2966d.png

    关于ELF格式文件符号表解析及readelf命令使用

    1.读取ELF文件头   readelf -h main.c

    da8602fcbd3255b55fa4427a7e1f15a0.png

    在 readelf 的输出中:

    第 1 行,ELF Header: 指名 ELF 文件头开始。

    第 2 行,Magic 魔数,用来指名该文件是一个 ELF 目标文件。第一个字节 7F 是个固定的数;后面的 3 个字节正是 E, L, F 三个字母的 ASCII 形式。

    第 3 行,CLASS 表示文件类型,这里是 64位的 ELF 格式。

    第 4 行,Data 表示文件中的数据是按照什么格式组织(大端或小端)的,不同处理器平台数据组织格式可能就不同,如x86平台为小端存储格式。

    第 5 行,当前 ELF 文件头版本号,这里版本号为 1 。

    第 6 行,OS/ABI ,指出操作系统类型,ABI 是 Application Binary Interface 的缩写。

    第 7 行,ABI 版本号,当前为 0 。

    第 8 行,Type 表示文件类型。ELF 文件有 3 种类型,一种是如上所示的 Relocatable file 可重定位目标文件,一种是可执行文件(Executable),另外一种是共享库(Shared Library) 。

    第 9 行,机器平台类型。

    第 10 行,当前目标文件的版本号。

    第 11 行,程序的虚拟地址入口点。

    第 12 行,与 11 行同理,这个目标文件没有 Program Headers。

    第 13 行,sections 头开始处,这里 856 是十进制.。

    第 14 行,是一个与处理器相关联的标志。

    第 15 行,ELF 文件头的字节数。

    第 16 行,因为这个不是可执行程序,故此处大小为 0。

    第 17 行,同理于第 16 行。

    第 18 行,sections header 的大小,这里每个 section 头大小为 64个字节。

    第 19 行,一共有多少个 section 头,这里是 13个。

    第 20 行,section 头字符串表索引号,从 Section Headers 输出部分可以看到其内容的偏移在 0xa0 处,从此处开始到0xcf 结束保存着各个 sections 的名字,如 .data,.text,.bss等。

    2.读取节头表    readelf -S main.o

    可重定位目标文件

    ELF头

    .text

    .rodata

    .data

    .bss

    .symtab

    .rel.text

    .rel.data

    .debug

    .line

    .strtab

    节头部表

    ELF 头

    包括16字节标识信息、文件类型 (.o, exec, .so)、机器类型(如 IA-32)、 节头表的偏移、节头表的表项大小以及 表项个数.text 节编译后的代码部分

    .rodata 节只读数据,如 printf 格式串、switch 跳转表等

    .data 节已初始化的全局变量

    .bss 节未初始化全局变量,仅是占位符,不占 据任何实际磁盘空间。区分初始化和非 初始化是为了空间效率

    .symtab 节存放函数和全局变量 (符号表)信息 , 它不包括局部变量

    .rel.text 节.text节的重定位信息,用于重新修改代 码段的指令中的地址信息

    .rel.data 节.data节的重定位信息,用于对被模块使 用或定义的全局变量进行重定位的信息

    .debug 节调试用符号表 (gcc -g)

    strtab 节包含symtab和debug节中符号及节名

    Section header table(节头表)每个节的节名、偏移和大小

    以下以main.o为例子解释

    4fb9f0821990ca27b23fe5774b5a626c.png

    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)

    可重定位目标文件中,每个可装入节的起始地址总是0

    6714b1337ffcdcdb259d7f75f3b59e5f.png

    3.符号表机制    readelf -s main.o

    cb92ad9978e65c2a0fd77215b18d4ad5.png

    可以看出全局变量,静态全局变量,静态局部变量,

    全局函数名都会出现在符号表中,而局部变量不会被保存在符号表中。

    展开全文
  • 几个常用的数量单位进程的运行原理——指令逻辑地址vs物理地址进程运行的基本原理装入模块装入内存装入的三种方式绝对装入静态重定位动态重定位链接的三种方式知识回顾与重要考点 前言 此篇文章是我在B站学习时所做...

    前言

    此篇文章是我在B站学习时所做的笔记,大部分图片都是课件老师的PPT,方便复习用。此篇文章仅供学习参考。


    提示:以下是本篇文章正文内容

    知识总览

    在这里插入图片描述

    什么是内存?有何作用?

    内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被CPU处理
    在这里插入图片描述

    在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序的数据需要同时放到内存中。

    几个常用的数量单位

    1B= 1字节= 0.5个字
    210= 1K(千)
    220=1M(兆,百万)
    230= 1G(十亿,千兆)

    :一台手机/电脑有4GB内存,是什么意思?
    :是指该内存中可以存放4*230个字节。如果是按字节编址的话,也就是有4*230 = 232个“小房间”

    注:有的题目会告诉我们内存的大小,让我们确定地址长度应该是多少(即要多少个二进制位才能表示相应数目的存储单元)
    如:这么多“小房间”,需要232个地址才能一一标识,所以地址需要用32个二进制位来表示(0~232-1)

    进程的运行原理——指令

    在这里插入图片描述
    解说
    我们用高级语言写的这些代码经过编译之后,会形成与它的对等的一系列的机器指令,这些指令使用机器语言二进制来写的,可以被CPU识别,那么CPU会根据我们的这些指令做出一系列的事情,用来完成我们指定的这个操作。假设我们的变量x是存放在这个地址(01001111)对应的内存单元里吧,当然这个地址是用二进制数表示的,那么一般来说像变量这些数据都是存放在所谓的数据段里,而指令是存放在程序段里,还记得程序段和数据段的概念吗?咱们在进程那个章节学过,每个进程在逻辑上有三个部分组成,程序段,数据段,还有PCB(也就是进程控制块),那么CPU会根据进程的程序段里的这些指令来执行一系列的操作,他会依次执行这些指令,比如说此时执行到了指令1,也就是一个数据传送指令,CPU首先会根据这个指令前面的这几位(00101100)来判断此时这个指令到底是让她干些什么事情,这几位(00101100)叫做操作码,这个操作码就是指明让CPU进行数据的传送,后面的这两组数据其实就是两个参数,就是让CPU把内存单元为(01001111)的数据取出来,放到地址为(00000011)的寄存器当中,所以CPU根据这条指令会把x的值传送到寄存器10(外边的10)。那接下来,会执行第二条指令,是让CPU执行加法操作,就是把00000011的寄存器当中的数据+1,于是寄存器中的内容变成11,接下来执行完第二条指令后,执行第三条指令,第三条指令同样是数据传送指令,不过和刚才的传送方向相反,这次是让CPU把00000011地址的寄存器当中的数据传送到内存的01001111地址当中,所以CPU会把寄存器11的数据传送回变量x存放的地方,这样变量x就实现了x=x+1这样的操作。

    总之,每个指令都会有一个操作码告诉CPU此时它要做的是什么事情,并且不同的指令可能会对应一系列参数,那么CPU会根据这些参数和指令的操作码来执行最后具体的操作,CPU会根据地址参数来决定到底要去内存的哪个地方去存/取数据。

    • 可见,我们写的代码要翻译成CPU能识别的指令。这些指令会告诉CPU应该去内存的哪个地址存/取数据,这个数据应该做什么样的处理。在这个例子中,指令中直接给出了变量x的实际存放地址(物理地址)。但实际在生成机器指令的时候并不知道该进程的数据会被放到什么位置。所以编译生成的指令中一般是使用逻辑地址(相对地址)

    逻辑地址vs物理地址

    宿舍四个人一起出去旅行,四个人的学号尾号分别是0、1、2、3。
    住酒店时酒店给你们安排了4个房号相连的房间。四个人按学号递增次序入住房间。比如0、1、2、3号同学分别入住了5、6、7、8号房间。
    四个人的编号0、1、2、3其实是一个“相对位置”,而各自入住的房间号是一个“绝对位置”。只要知道0号同学住的是房号为N的房间,那么M号同学的房号一定是N+M。
    也就是说,只要知道各个同学的“相对位置”和“起始房号”,就一定可以算出所有同学的“绝对位置”
    在这里插入图片描述

    相对地址又称逻辑地址绝对地址又称物理地址

    进程运行的基本原理

    在这里插入图片描述

    • 编译:由编译程序将用户源代码编译成若干个目标模块(编译就是把高级语言翻译为机器语言)
    • 链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块
    • 装入(装载):由装入程序将装入模块装入内存运行

    装入模块装入内存

    在这里插入图片描述
    在这里插入图片描述

    装入的三种方式

    1、绝对装入

    在这里插入图片描述
    使用绝对装入的方式的话,我们需要保证在编译的时候就能知道这个装入模块最后会被放入什么位置,并且装入程序也需要遵照之前的约定,把装入模块放入之前约定的位置去。

    绝对装入只适用于单道程序环境
    灵活性低,因为在单道程序下,内存当中同一时刻只会有一个程序正在运行,所以每个程序要从什么位置开始存放,那我们可以刚开始就约定好,那在程序当中使用的绝对地址可以在编译或汇编的时候给出,也可以由程序员直接赋予,一般来说都是在编译的时候才会产生最终的这个绝对地址

    2、静态重定位

    静态重定位:又称可重定位装入。编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对地址进行“重定位”,将逻辑地址变换为物理地址(地址变换是在装入时一次完成的)。

    补充:装入程序负责把所有指令当中涉及到的地址都进行+100的操作,这样就完成了从逻辑地址到物理地址的转变,所以采用静态重定位这种方式使逻辑地址到物理地址的转变是由装入程序负责进行的。
    在这里插入图片描述

    静态重定位,必须分配作业要求的全部内存空间,在运行期间就不能再移动

    3、动态重定位

    动态重定位:又称动态运行时装入。编译、链接后的装入模块的地址都是从O开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址。这种方式需要一个重定位寄存器的支持。
    在这里插入图片描述

    采用动态重定位时允许程序在内存中发生移动

    链接的三种方式

    1. 静态链接:在程序运行之前先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。
      在这里插入图片描述
    2. 装入时动态链接:将各目标模块装入内存时,边装入边链接的链接方式。
      在这里插入图片描述
    3. 运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享。在这里插入图片描述

    知识回顾与重要考点

    在这里插入图片描述

    展开全文
  • 操作系统---页式地址重定位

    千次阅读 2021-05-06 17:41:38
    页式地址重定位 要求: 一、实验目的: 1、 用高级语言编写和调试模拟实现页式地址重定位。 2、 加深理解页式地址重定位技术在多道程序设计中的作用和意义。 二、实验原理: 当进程在CPU上运行时,如指令中涉及逻辑...

    页式地址重定位

    要求:

    一、实验目的:
    1、 用高级语言编写和调试模拟实现页式地址重定位。
    2、 加深理解页式地址重定位技术在多道程序设计中的作用和意义。
    二、实验原理:
    当进程在CPU上运行时,如指令中涉及逻辑地址时,操作系统自动根据页长得到页号和页内偏移,把页内偏移拷贝到物理地址寄存器,再根据页号,查页表,得到该页在内存中的块号,把块号左移页长的位数,写到物理地址寄存器。
    三、实验内容:
    1、 设计页表结构
    2、 设计地址重定位算法
    3、 有良好的人机对话界面

    
    #include<bits/stdc++.h>
    using namespace std;
    #define pagesize  4096
    #define pagetablelength  64
    /*系统页表*/
    const int pagetable[pagetablelength]={0,42,25,15,45,31,44,43,
                                   41,28,1,30,12,24,6,32,
                                   14,27,13,46,7,33,10,22,
                                   40,2,51,11,39,23,49,50,
                                   26,16,29,4,47,17,3,48,
                                   52,36,58,35,57,34,21,63,
                                   5,37,18,8,62,56,20,54,
                                   60,19,38,9,61,55,59,53};
    
    int main()
    {
        int logicaladdress=0;
        int pagenum=0;
        int w=0;
        cout<<"系统页号对应块号情况(页号——>块号):\n";
        for(int i=0;i<64;i++)
        {        
            cout<<setw(2)<<i<<"-->"<<setw(2)<<pagetable[i]<<"  ";
            if(i%8==7)
                cout<<endl;
        }
        cout<<endl<<"请输入逻辑地址(十进制):\n";
        cin>>logicaladdress;
    
        /*公式:
            物理地址=页号对应的页块*页面大小+页内偏移
            页内偏移=逻辑地址-页面大小*页面数*/
    
    
        pagenum=logicaladdress/pagesize;            //页面数
    
        w=logicaladdress-pagenum*pagesize;            //页面偏移
    
        if((logicaladdress/pagesize)>pagetablelength)
        {
            cout<<"本次访问的地址已超出进程的地址空间,系统将产生越界中断!\n";
            return 0;
        }
        cout<<"对应的物理地址为(十进制):\n"<<pagetable[pagenum]*pagesize+w<<endl;
        
        system("pause");
        return 0;
    }
    

    对应截图如下:
    在这里插入图片描述

    公式:
    物理地址=页号对应的页块页面大小+页内偏移
    页内偏移=逻辑地址-页面大小
    页面数

    展开全文
  • Relocatable object file(可重定位的对象文件). Contains binary code and data in a form that can be combined with other relocatable object files at compile time to create an executable object file. ...
  • 随着技术的进步和社会的发展,GPS定位需求成井喷式的增长。汽车逐渐成为普通大众最主要的代步工具;别说城市了,现在连农村的街道上,也被汽车赌的水泄不通,可见汽车的普及率之高。随之而来的是汽车的防盗和知晓...
  • 3、VINS回环检测与重定位、四自由度位姿图优化 3.1 第一部分:回环检测与重定位 3.1.1 回环检测(只对关键帧) 3.1.2 回环候选帧之间的特征匹配 3.1.3 紧耦合重定位 3.2 第二部分:全局位姿图优化 3.3 代码...
  • 重定位表可以理解為編譯器給鏈接器提供的信息,它是由多個重定位項組成的數組,其中每一個重定位的基本屬性有:被修正地址在節數據中的偏移,用於提供地址的符號索引,重定位類型(絕對定位、相對定位等)。...
  • 显著性目标检测和视觉重定位

    千次阅读 2021-01-08 17:56:14
    论文:https://arxiv.org/pdf/2008.07064.pdf 代码:https://github.com/ShuhanChen/PGAR_ECCV20 出处:ECCV2020 视觉重定位 一、GN-Net: The Gauss-Newton Loss for Multi-Weather Relocalization 直接SLAM方法在...
  • S3C2440之代码重定位

    2021-01-30 15:52:45
    一、段的概念重定位引入 S3C2440的CPU可以直接给SDRAM发送命令、给Nor Flash发送命令、给4K的片上SRAM发送命令,但是不能直接给Nand Flsh发送命令(有Nand Flash控制器) nor启动时,CPU认为0地址在Nor Flash上;...
  • 重定位1.概念2.程序中含有什么3.谁来做重定位4.重定位和清除BSS段4.1. 重定位4.2.清除BSS段5.重定位的本质 1.概念 重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程。这句话的意思就是:使逻辑...
  • 重定位必须知道的几个概念什么是代码重定位?什么是位置无关码什么是运行地址为什么要代码重定位?nand flash启动的情况nor flash启动的情况两种方式的重定位代码重定位例如执行如下几条汇编指令 必须知道的几个概念...
  • 本次主要讲解ORBSLAM2中的基于重定位的跟踪,这种方式只有在跟踪丢失的时候会去使用,但是代码量确实三种跟踪方式中最复杂的,其中涉及到了多次试图找到符合要求的重定位关键帧,对应的函数为Relocalization,其中...
  • v55.xx 鸿蒙内核源码分析(重定位篇) | 与国际接轨的对外部发言人 | 51 .c .h .o 本篇是以下篇的延续,建议先看 v54.xx 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 51 .c .h .o v53.xx 鸿蒙...
  • slam四讲各章内容概述

    千次阅读 2021-11-22 15:16:14
    slam四讲各章内容概述
  • 重定位目标文件中有可重定位节.rel.text和.rel.data,而在可执行目标文件中则没有 D. 可重定位目标文件中有初始化程序段.init节,而在可执行目标文件中则没有 正确答案:D你没选择任何选项 10单选(0.5分) 以下...
  • 快换类型的工具应用很多,在项目中一台机器人可能既要进行取放工作,还要进行焊接工作,需要在焊枪和爪手直接切换,在PS软件中我们将使用Mount和...选择Atc打开重定位对话框,然后选择Atc的Atc_base坐标和机器人的...
  • Contrib扩展模块中文版教程 在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二多章...
  • java定位线上问题

    2021-03-12 21:40:29
    根据 这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及 是否死锁等等......A、//int a,b,c B、/** int a,b ,c */ C、{int a,b,c} */ D、/* int a,b String a */ 30、Java 目前支持图象文件...
  • ios wifi定位 开发

    2020-12-19 07:38:53
    ios wifi定位 开发ios wifi定位 开发赵无恤皱起了眉:“我担心的是国人,曲阜国人才是中坚,季氏实际上已经垮了,...”ios wifi定位 开发漆万被分配到了剑盾卒,他的卒长正是那位甲幕面的武士。此人名为穆夏,是...
  • 报错信息:selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <spanxxxx>xxxx</span> is not clickable at point (148, 10)....
  • 点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达随着传感技术、智能技术和计算技术等的不断提高,智能移动机器人一定能够在生产和生活中扮演人的角色。那么移动机器人定位技术...
  • 一、编译器驱动程序二、静态链接三、目标文件四、可重定位目标文件五、符号和符号表六、符号解析6.1 链接器如何解析多重定义的全局符号6.2 与静态库链接6.3 链接器如何使用静态库来解析引用七、重定位八、可执行目标...
  • 前端之定位

    2021-10-08 21:55:42
    定位,关键则在于一个"位"上面。 二、为什么要学习定位 如果要实现某个东西能够随便在一个盒子里自由随意移动、或压着某个元素、或超出某个盒子等等,这一类用标准流或者浮动,实现会比较复杂或者难以实现,此时我们...
  • 蓝牙定位总结

    千次阅读 2021-09-07 10:34:43
    这些定位服务分为两个高级类别,即邻近解决方案和定位系统。 近距离解决方案包括兴趣点(PoI)信息解决方案,例如在博物馆中发现的解决方案,这些解决方案可为用户提供有关房间内文物的信息。该类别还包括物品查找...
  • 点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达 本文转自|新机器视觉虚拟现实中用到的五种定位追踪技术虚拟现实在仿真环境中当使用者进行位置移动时,计...
  • 文章目录10-对象的实例化、内存布局与访问定位一、对象的实例化创建对象的方法创建对象的步骤二、对象的内存布局对象头(Header)实例数据对象填充图示三、对象的访问定位图示对象访问方式句柄访问直接指针(HotSpot...
  • 想在短视频平台上引流、卖货,第一步就是要先找准定位,再去拍垂直类视频,通过精准定位的优质内容吸引粉丝关注,实现引流变现。 但是,很多人对抖音账号定位是什么意思都不知道,更不用说怎么定位、抖音账号定位...
  • 如何在Excel表中快速定位并提取指定行列交叉单元格的内容。该怎么去操作的呢?今天,学习啦小编就教大家在Excel2010表格中返回行列交叉所在单元格内容的操作方法。Excel2010表格中返回行列交叉所在单元格内容的操作...
  • 最网最全bug定位套路,遇见bug再也不慌了

    千次阅读 多人点赞 2021-03-26 15:23:43
    最网最全bug定位套路,遇见bug再也不慌了

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 82,159
精华内容 32,863
关键字:

十重定位