Linux 程序编译过程的来龙去脉( 三 )

86_64-linux-gnu/libc.so.6 (0x00007fadcdd82000)/lib64/ld-linux-x86-64.so.2 (0x00007fadce14c000)

  • 如果使用命令“gcc -static hello.c -o hello”则会使用静态库进行链接,生成的ELF可执行文件的大小(使用Binutils的size命令查看)和链接的动态库(使用Binutils的ldd命令查看)如下所示
    $ gcc -static hello.c -o hello$ size hello //使用size查看大小text data bss dec hex filename823726 7284 6360 837370 cc6fa hello //可以看出text的代码尺寸变得极大$ ldd hellonot a dynamic executable //说明没有链接动态库
  • 链接器链接后生成的最终文件为ELF格式可执行文件,一个ELF可执行文件通常被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss等段 。
    分析ELF文件
    1.ELF文件的段
    ELF文件格式如下所示,位于ELF Header和Section Header Table之间的都是段(Section) 。一个典型的ELF文件包含下面几个段:
    • .text:已编译程序的指令代码段 。
    • .rodata:ro代表read only,即只读数据(譬如常数const) 。
    • .data:已初始化的C程序全局变量和静态局部变量 。
    • .bss:未初始化的C程序全局变量和静态局部变量 。
    • .debug:调试符号表,调试器用此段的信息帮助调试 。

    Linux 程序编译过程的来龙去脉

    文章插图
    可以使用readelf -S查看其各个section的信息如下
    $ readelf -S helloThere are 31 section headers, starting at offset 0x19d8:Section Headers:[Nr] Name Type Address OffsetSize EntSize Flags Link Info Align[ 0] 0000000000000000 000000000000000000000000 0000000000000000 0 0 0……[11] .init PROGBITS 00000000004003c8 000003c8000000000000001a 0000000000000000 AX 0 0 4……[14] .text PROGBITS 0000000000400430 000004300000000000000182 0000000000000000 AX 0 0 16[15] .fini PROGBITS 00000000004005b4 000005b4……2.反汇编ELF
    由于ELF文件无法被当做普通文本文件打开,如果希望直接查看一个ELF文件包含的指令和数据,需要使用反汇编的方法 。
    使用objdump -D对其进行反汇编如下
    $ objdump -D hello……0000000000400526 <main>: // main标签的PC地址//PC地址:指令编码 指令的汇编格式400526: 55 push %rbp400527: 48 89 e5 mov %rsp,%rbp40052a: bf c4 05 40 00 mov $0x4005c4,%edi40052f: e8 cc fe ff ff callq 400400 <puts@plt>400534: b8 00 00 00 00 mov $0x0,%eax400539: 5d pop %rbp40053a: c3 retq40053b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)……使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:
    $ gcc -o hello -g hello.c //要加上-g选项$ objdump -S hello……0000000000400526 <main>:#include <stdio.h>intmain(void){400526: 55 push %rbp400527: 48 89 e5 mov %rsp,%rbpprintf("Hello World!" "n");40052a: bf c4 05 40 00 mov $0x4005c4,%edi40052f: e8 cc fe ff ff callq 400400 <puts@plt>return 0;400534: b8 00 00 00 00 mov $0x0,%eax}400539: 5d pop %rbp40053a: c3 retq40053b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)……轻轻一扫 欢迎关注~

    【Linux 程序编译过程的来龙去脉】


    推荐阅读