• 程序运行之目标文件(一)


    我们在写程序的时候,windows下通过vs等编译软件,linux通过gcc命令得到程序的可执行文件。在这个过程中,其实大致经历了4个过程。预编译 编译 汇编 链接

    预编译:主要处理那些源代码文件中的以”#”开头的预编译指令,比如”#include”“#define”等。

    编译:就是把预处理完的文件进行一系列词法分析,语法分析,语义分析以及优化后生成相应的汇编代码文件

    汇编:就是将汇编代码转变成机器可以执行的指令。

    链接:一个工程里面包含很多.c的文件。我们最终工程得到的是.out文件。但是这个是将所有涉及到的文件都链接起来才得到的。这个就是链接的功能。

    我们用一个最常见的代码来看下这几个过程

    #include <stdio.h>

    int main(void){

    printf("hello world");

    return 0;

    }

    gcc main.c -o main.i生成预编译文件。通过file main.i可以查看到文件的格式是ELF。这个后面会详细介绍。

    root@zhf-maple:/home/zhf/c_prj# file main.i

    main.i: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a19f9545eefb261b7ec7d27cf12702c3881c5ea7, not stripped

    objdump -i main.i可以看到具体的内容。

    通过gcc main.c -o main.s生成编译文件.objdump -S 可以查看具体的汇编代码

    root@zhf-maple:/home/zhf/c_prj# objdump -S main.s

    main.s:     文件格式 elf64-x86-64

    Disassembly of section .init:

    00000000000004f0 <_init>:

     4f0: 48 83 ec 08           sub    $0x8,%rsp

     4f4: 48 8b 05 ed 0a 20 00  mov    0x200aed(%rip),%rax        # 200fe8 <__gmon_start__>

     4fb: 48 85 c0              test   %rax,%rax

     4fe: 74 02                 je     502 <_init+0x12>

     500: ff d0                 callq  *%rax

     502: 48 83 c4 08           add    $0x8,%rsp

     506: c3                    retq   

    Disassembly of section .plt:

    0000000000000510 <.plt>:

     510: ff 35 aa 0a 20 00     pushq  0x200aaa(%rip)        # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x8>

     516: ff 25 ac 0a 20 00     jmpq   *0x200aac(%rip)        # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x10>

     51c: 0f 1f 40 00           nopl   0x0(%rax)

    0000000000000520 <printf@plt>:

     520: ff 25 aa 0a 20 00     jmpq   *0x200aaa(%rip)        # 200fd0 <printf@GLIBC_2.2.5>

     526: 68 00 00 00 00        pushq  $0x0

     52b: e9 e0 ff ff ff        jmpq   510 <.plt>

    Disassembly of section .plt.got:

    0000000000000530 <__cxa_finalize@plt>:

     530: ff 25 c2 0a 20 00     jmpq   *0x200ac2(%rip)        # 200ff8 <__cxa_finalize@GLIBC_2.2.5>

     536: 66 90                 xchg   %ax,%ax

    Disassembly of section .text:

    0000000000000540 <_start>:

     540: 31 ed                 xor    %ebp,%ebp

     542: 49 89 d1              mov    %rdx,%r9

     545: 5e                    pop    %rsi

     546: 48 89 e2              mov    %rsp,%rdx

     549: 48 83 e4 f0           and    $0xfffffffffffffff0,%rsp

     54d: 50                    push   %rax

     54e: 54                    push   %rsp

     54f: 4c 8d 05 8a 01 00 00  lea    0x18a(%rip),%r8        # 6e0 <__libc_csu_fini>

     556: 48 8d 0d 13 01 00 00  lea    0x113(%rip),%rcx        # 670 <__libc_csu_init>

     55d: 48 8d 3d e6 00 00 00  lea    0xe6(%rip),%rdi        # 64a <main>

     564: ff 15 76 0a 20 00     callq  *0x200a76(%rip)        # 200fe0 <__libc_start_main@GLIBC_2.2.5>

     56a: f4                    hlt    

     56b: 0f 1f 44 00 00        nopl   0x0(%rax,%rax,1)

    0000000000000570 <deregister_tm_clones>:

     570: 48 8d 3d 99 0a 20 00  lea    0x200a99(%rip),%rdi        # 201010 <__TMC_END__>

     577: 55                    push   %rbp

     578: 48 8d 05 91 0a 20 00  lea    0x200a91(%rip),%rax        # 201010 <__TMC_END__>

     57f: 48 39 f8              cmp    %rdi,%rax

     582: 48 89 e5              mov    %rsp,%rbp

     585: 74 19                 je     5a0 <deregister_tm_clones+0x30>

     587: 48 8b 05 4a 0a 20 00  mov    0x200a4a(%rip),%rax        # 200fd8 <_ITM_deregisterTMCloneTable>

     58e: 48 85 c0              test   %rax,%rax

     591: 74 0d                 je     5a0 <deregister_tm_clones+0x30>

     593: 5d                    pop    %rbp

     594: ff e0                 jmpq   *%rax

     596: 66 2e 0f 1f 84 00 00  nopw   %cs:0x0(%rax,%rax,1)

     59d: 00 00 00 

     5a0: 5d                    pop    %rbp

     5a1: c3                    retq   

     5a2: 0f 1f 40 00           nopl   0x0(%rax)

     5a6: 66 2e 0f 1f 84 00 00  nopw   %cs:0x0(%rax,%rax,1)

     5ad: 00 00 00 

    00000000000005b0 <register_tm_clones>:

     5b0: 48 8d 3d 59 0a 20 00  lea    0x200a59(%rip),%rdi        # 201010 <__TMC_END__>

     5b7: 48 8d 35 52 0a 20 00  lea    0x200a52(%rip),%rsi        # 201010 <__TMC_END__>

     5be: 55                    push   %rbp

     5bf: 48 29 fe              sub    %rdi,%rsi

     5c2: 48 89 e5              mov    %rsp,%rbp

     5c5: 48 c1 fe 03           sar    $0x3,%rsi

     5c9: 48 89 f0              mov    %rsi,%rax

     5cc: 48 c1 e8 3f           shr    $0x3f,%rax

     5d0: 48 01 c6              add    %rax,%rsi

     5d3: 48 d1 fe              sar    %rsi

     5d6: 74 18                 je     5f0 <register_tm_clones+0x40>

     5d8: 48 8b 05 11 0a 20 00  mov    0x200a11(%rip),%rax        # 200ff0 <_ITM_registerTMCloneTable>

     5df: 48 85 c0              test   %rax,%rax

     5e2: 74 0c                 je     5f0 <register_tm_clones+0x40>

     5e4: 5d                    pop    %rbp

     5e5: ff e0                 jmpq   *%rax

     5e7: 66 0f 1f 84 00 00 00  nopw   0x0(%rax,%rax,1)

     5ee: 00 00 

     5f0: 5d                    pop    %rbp

     5f1: c3                    retq   

     5f2: 0f 1f 40 00           nopl   0x0(%rax)

     5f6: 66 2e 0f 1f 84 00 00  nopw   %cs:0x0(%rax,%rax,1)

     5fd: 00 00 00 

    0000000000000600 <__do_global_dtors_aux>:

     600: 80 3d 09 0a 20 00 00  cmpb   $0x0,0x200a09(%rip)        # 201010 <__TMC_END__>

     607: 75 2f                 jne    638 <__do_global_dtors_aux+0x38>

     609: 48 83 3d e7 09 20 00  cmpq   $0x0,0x2009e7(%rip)        # 200ff8 <__cxa_finalize@GLIBC_2.2.5>

     610: 00 

     611: 55                    push   %rbp

     612: 48 89 e5              mov    %rsp,%rbp

     615: 74 0c                 je     623 <__do_global_dtors_aux+0x23>

     617: 48 8b 3d ea 09 20 00  mov    0x2009ea(%rip),%rdi        # 201008 <__dso_handle>

     61e: e8 0d ff ff ff        callq  530 <__cxa_finalize@plt>

     623: e8 48 ff ff ff        callq  570 <deregister_tm_clones>

     628: c6 05 e1 09 20 00 01  movb   $0x1,0x2009e1(%rip)        # 201010 <__TMC_END__>

     62f: 5d                    pop    %rbp

     630: c3                    retq   

     631: 0f 1f 80 00 00 00 00  nopl   0x0(%rax)

     638: f3 c3                 repz retq 

     63a: 66 0f 1f 44 00 00     nopw   0x0(%rax,%rax,1)

    0000000000000640 <frame_dummy>:

     640: 55                    push   %rbp

     641: 48 89 e5              mov    %rsp,%rbp

     644: 5d                    pop    %rbp

     645: e9 66 ff ff ff        jmpq   5b0 <register_tm_clones>

    000000000000064a <main>:

     64a: 55                    push   %rbp

     64b: 48 89 e5              mov    %rsp,%rbp

     64e: 48 8d 3d 9f 00 00 00  lea    0x9f(%rip),%rdi        # 6f4 <_IO_stdin_used+0x4>

     655: b8 00 00 00 00        mov    $0x0,%eax

     65a: e8 c1 fe ff ff        callq  520 <printf@plt>

     65f: b8 00 00 00 00        mov    $0x0,%eax

     664: 5d                    pop    %rbp

     665: c3                    retq   

     666: 66 2e 0f 1f 84 00 00  nopw   %cs:0x0(%rax,%rax,1)

     66d: 00 00 00 

    0000000000000670 <__libc_csu_init>:

     670: 41 57                 push   %r15

     672: 41 56                 push   %r14

     674: 41 89 ff              mov    %edi,%r15d

     677: 41 55                 push   %r13

     679: 41 54                 push   %r12

     67b: 4c 8d 25 36 07 20 00  lea    0x200736(%rip),%r12        # 200db8 <__frame_dummy_init_array_entry>

     682: 55                    push   %rbp

     683: 48 8d 2d 36 07 20 00  lea    0x200736(%rip),%rbp        # 200dc0 <__init_array_end>

     68a: 53                    push   %rbx

     68b: 49 89 f6              mov    %rsi,%r14

     68e: 49 89 d5              mov    %rdx,%r13

     691: 4c 29 e5              sub    %r12,%rbp

     694: 48 83 ec 08           sub    $0x8,%rsp

     698: 48 c1 fd 03           sar    $0x3,%rbp

     69c: e8 4f fe ff ff        callq  4f0 <_init>

     6a1: 48 85 ed              test   %rbp,%rbp

     6a4: 74 20                 je     6c6 <__libc_csu_init+0x56>

     6a6: 31 db                 xor    %ebx,%ebx

     6a8: 0f 1f 84 00 00 00 00  nopl   0x0(%rax,%rax,1)

     6af: 00 

     6b0: 4c 89 ea              mov    %r13,%rdx

     6b3: 4c 89 f6              mov    %r14,%rsi

     6b6: 44 89 ff              mov    %r15d,%edi

     6b9: 41 ff 14 dc           callq  *(%r12,%rbx,8)

     6bd: 48 83 c3 01           add    $0x1,%rbx

     6c1: 48 39 dd              cmp    %rbx,%rbp

     6c4: 75 ea                 jne    6b0 <__libc_csu_init+0x40>

     6c6: 48 83 c4 08           add    $0x8,%rsp

     6ca: 5b                    pop    %rbx

     6cb: 5d                    pop    %rbp

     6cc: 41 5c                 pop    %r12

     6ce: 41 5d                 pop    %r13

     6d0: 41 5e                 pop    %r14

     6d2: 41 5f                 pop    %r15

     6d4: c3                    retq   

     6d5: 90                    nop

     6d6: 66 2e 0f 1f 84 00 00  nopw   %cs:0x0(%rax,%rax,1)

     6dd: 00 00 00 

    00000000000006e0 <__libc_csu_fini>:

     6e0: f3 c3                 repz retq 

    Disassembly of section .fini:

    00000000000006e4 <_fini>:

     6e4: 48 83 ec 08           sub    $0x8,%rsp

     6e8: 48 83 c4 08           add    $0x8,%rsp

     6ec: c3                    retq   

    .o文件的格式如下。分为.text/.data/.bss/.comment/.note.GNU-stack/.eh_frame 5个段。

    root@zhf-maple:/home/zhf/c_prj# objdump -h main.o

    main.o:     文件格式 elf64-x86-64

    节:

    Idx Name          Size      VMA               LMA               File off  Algn

      0 .text         00000015  0000000000000000  0000000000000000  00000040  2**0

                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE

      1 .data         00000000  0000000000000000  0000000000000000  00000055  2**0

                      CONTENTS, ALLOC, LOAD, DATA

      2 .bss          00000000  0000000000000000  0000000000000000  00000055  2**0

                      ALLOC

      3 .comment      00000024  0000000000000000  0000000000000000  00000055  2**0

                      CONTENTS, READONLY

      4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  00000079  2**0

                      CONTENTS, READONLY

      5 .eh_frame     00000038  0000000000000000  0000000000000000  00000080  2**3

                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

    .o文件又称为目标文件。在linux下目标文件的格式为ELFELF格式的文件可以归纳为下面4

    ELF文件类型

    说明

    实例

    可重定位文件(Relocatable File)

    包含代码和数据,可以被用来链接成可执行文件或共享目标文件

    .o文件

    可执行文件

    包含了可以直接执行的程序,代表就是ELF可执行文件

    比如/bin/bash文件windowsexe文件

    共享目标文件

    包含代码和数据,2种情况下使用

    链接器可以使用这种文件跟其他的可重定位文件和共享文件链接产生新的目标文件

    动态链接将几个这种共享目标文件与可执行文件结合,做和进程映射的一部分来运行

    linux.so

    windowsdll

    核心转储文件

    当进程意外终止时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转储到核心文件

    linux下的core dump

    通过file命令查看相应的文件格式

    root@zhf-maple:/home/zhf/c_prj# file main.o

    main.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

    前面在用objdum -h main.o的时候看到了有

    text/.data/.bss/.comment/.note.GNU-stack/.eh_frame 5个段。那么这些段的意义是什么呢。代码段最常见的就是.text.data。 作用如下

    一般c语言编译后的执行语句都编译成机器代码,保存在.text

    已初始化的全局变量和局部静态变量都保存在.data

    未初始化的全局变量和局部静态变量放在.bss段里面

    ELF文件分别由4部分组成:1 ELF头,程序头表,section节头表。如下图。

    通过readelf -a main.o命令来看到具体的信息。比如在ELF头中描述了文件属性,入口地址,程序头地址,操作系统等。

    ELF 头:

      Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 

      类别:                              ELF64

      数据:                              2 补码,小端序 (little endian)

      版本:                              1 (current)

      OS/ABI:                            UNIX - System V

      ABI 版本:                          0

      类型:                              DYN (共享目标文件)

      系统架构:                          Advanced Micro Devices X86-64

      版本:                              0x1

      入口点地址:               0x540

      程序头起点:          64 (bytes into file)

      Start of section headers:          6592 (bytes into file)

      标志:             0x0

      本头的大小:       64 (字节)

      程序头大小:       56 (字节)

      Number of program headers:         9

      节头大小:         64 (字节)

      节头数量:         29

      字符串表索引节头: 28

    节头中能看到对应的sectioni信息

    节头:

      [名称              类型             地址              偏移量

           大小              全体大小          旗标   链接   信息   对齐

      [ 0]                   NULL             0000000000000000  00000000

           0000000000000000  0000000000000000           0     0     0

      [ 1] .interp           PROGBITS         0000000000000238  00000238

           000000000000001c  0000000000000000   A       0     0     1

      [ 2] .note.ABI-tag     NOTE             0000000000000254  00000254

           0000000000000020  0000000000000000   A       0     0     4

      [ 3] .note.gnu.build-i NOTE             0000000000000274  00000274

           0000000000000024  0000000000000000   A       0     0     4

      [ 4] .gnu.hash         GNU_HASH         0000000000000298  00000298

           000000000000001c  0000000000000000   A       5     0     8

      [ 5] .dynsym           DYNSYM           00000000000002b8  000002b8

           00000000000000a8  0000000000000018   A       6     1     8

      [ 6] .dynstr           STRTAB           0000000000000360  00000360

           0000000000000084  0000000000000000   A       0     0     1

      [ 7] .gnu.version      VERSYM           00000000000003e4  000003e4

           000000000000000e  0000000000000002   A       5     0     2

      [ 8] .gnu.version_r    VERNEED          00000000000003f8  000003f8

           0000000000000020  0000000000000000   A       6     1     8

      [ 9] .rela.dyn         RELA             0000000000000418  00000418

           00000000000000c0  0000000000000018   A       5     0     8

      [10] .rela.plt         RELA             00000000000004d8  000004d8

           0000000000000018  0000000000000018  AI       5    22     8

      [11] .init             PROGBITS         00000000000004f0  000004f0

           0000000000000017  0000000000000000  AX       0     0     4

      [12] .plt              PROGBITS         0000000000000510  00000510

           0000000000000020  0000000000000010  AX       0     0     16

      [13] .plt.got          PROGBITS         0000000000000530  00000530

           0000000000000008  0000000000000008  AX       0     0     8

      [14] .text             PROGBITS         0000000000000540  00000540

           00000000000001a2  0000000000000000  AX       0     0     16

      [15] .fini             PROGBITS         00000000000006e4  000006e4

           0000000000000009  0000000000000000  AX       0     0     4

      [16] .rodata           PROGBITS         00000000000006f0  000006f0

           0000000000000010  0000000000000000   A       0     0     4

      [17] .eh_frame_hdr     PROGBITS         0000000000000700  00000700

           000000000000003c  0000000000000000   A       0     0     4

      [18] .eh_frame         PROGBITS         0000000000000740  00000740

           0000000000000108  0000000000000000   A       0     0     8

      [19] .init_array       INIT_ARRAY       0000000000200db8  00000db8

           0000000000000008  0000000000000008  WA       0     0     8

      [20] .fini_array       FINI_ARRAY       0000000000200dc0  00000dc0

           0000000000000008  0000000000000008  WA       0     0     8

      [21] .dynamic          DYNAMIC          0000000000200dc8  00000dc8

           00000000000001f0  0000000000000010  WA       6     0     8

      [22] .got              PROGBITS         0000000000200fb8  00000fb8

           0000000000000048  0000000000000008  WA       0     0     8

      [23] .data             PROGBITS         0000000000201000  00001000

           0000000000000014  0000000000000000  WA       0     0     8

      [24] .bss              NOBITS           0000000000201014  00001014

           0000000000000014  0000000000000000  WA       0     0     4

      [25] .comment          PROGBITS         0000000000000000  00001014

           0000000000000023  0000000000000001  MS       0     0     1

      [26] .symtab           SYMTAB           0000000000000000  00001038

           0000000000000648  0000000000000018          27    45     8

      [27] .strtab           STRTAB           0000000000000000  00001680

           0000000000000240  0000000000000000           0     0     1

      [28] .shstrtab         STRTAB           0000000000000000  000018c0

           00000000000000fe  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)

    下一章将继续挖掘目标文件的具体内容。

  • 相关阅读:
    MYSQL编码转换的问题latin1转utf8
    Java中的局部内部类
    Java中的抽象类和接口
    Java中的构造方法
    使用Java打印杨辉三角
    Java中的数组越界问题
    Java虚拟机中的内存分配
    关于iOS10 Xcode8真机测试项目出现的问题 "code signing is required for product type 'xxxxx' in SDK 'iOS 10.0"..
    Java语言的学习
    关于导航栏设置状态栏样式问题
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9026839.html
Copyright © 2020-2023  润新知