[笔记二]探究编译与链接之目标文件

来源:互联网 发布:淘宝零销量能买吗 编辑:程序博客网 时间:2024/06/14 06:10

目标文件

目标文件的格式

目标文件在Linux下面以ELF格式存储,ELF文件标准里面把系统中采用ELF格式的文件归为以下4类:

ELF文件类型 说明 实例 可重定位文件(Relocatable File) 这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归为这一类 Linux的.o文件 可执行文件(Executable File) 这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,它们一般都没有扩展名 比如/bin/bash文件 共享目标文件(Shared Object File) 这种文件包含了代码和数据,可以在以下两种情况下使用,一种是链接器可以使用这种文件跟其它的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态链接器可以将几个这样的共享目标文件与可执行文件结合,作为进程印像的一部分来运行 Linux的.so 核心转储文件(Core Dump File) 当进程意外终止时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转储到核心转储文件 Linux下的core dump

在Linux下我们查看文件格式的方式可以如此:

$file hello.ohello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped$file /bin/bash/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped$file /lib/ld-2.12.so/lib/ld-2.12.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

目标文件的构成

程序源代码编译后的机器指令经常被放在代码段(Code Section)里,代码段常见的名字有“.text”或“.code”;全局变量和局部静态变量数据经常放在数据段(Data Section),数据段的一般名字都叫“.data”。

    真正了不起的程序员对自己的程序的每一个字节都了如指掌。                                                -共勉之

实例解析

示例代码如下(SimpleSection.c)

int printf(const char *format, ...);//__attribute__((section("Demon"))) int global_init_var = 84;int global_init_var = 84;int global_uninit_var;void func1(int i){    printf("%d\n",i);}int main(void){    static int static_var = 85;    static int static_var2;    int a = 1;    int b;    func1(static_var + static_var2 + a + b);    return 0;}

编译获取.o文件:

$gcc -c SimpleSection.c

我们来看看该目标文件(SimpleSection.o)内部的结构:

$objdump -h SimpleSection.oSimpleSection.o:     file format elf64-x86-64Sections:Idx Name          Size      VMA               LMA               File off  Algn0 .text         00000056  0000000000000000  0000000000000000  00000040  2**2              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data         00000008  0000000000000000  0000000000000000  00000098  2**2              CONTENTS, ALLOC, LOAD, DATA2 .bss          00000004  0000000000000000  0000000000000000  000000a0  2**2              ALLOC3 .rodata       00000004  0000000000000000  0000000000000000  000000a0  2**0              CONTENTS, ALLOC, LOAD, READONLY, DATA4 .comment      00000012  0000000000000000  0000000000000000  000000a4  2**0              CONTENTS, READONLY5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b6  2**0              CONTENTS, READONLY6 .eh_frame     00000058  0000000000000000  0000000000000000  000000b8  2**3              CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

这样来看的话,目标文件不只之前提到的代码段和数据段,还有存放未初始化变量的BSS段、只读数据段(.rodata)、注释信息段(.comment)和堆栈提示段(.note.GNU-stack)。

Size代表段的大小,File off 代表段所在的位置;

每个段的第二行中的“CONTENTS”、“ALLOC”等表示段的各种属性,比较重要的是“CONTENTS”表示该段在文件中存在,对比上面目标文件的结构,你会发现.bss段没有CONTENTS属性,即.bss段并不会在文件中存在。


有一个专门的命令“size”用来查看ELF文件的代码段、数据段和BSS段的长度(dec表示三个段长度和的十进制,hex表示长度和的十六进制)

$size SimpleSection.otext       data     bss     dec     hex filename178       8       4     190      be SimpleSection.o

段的说明

段名 说明 .text 存放代码片段 .date 存放初始化了的全局静态变量和局部静态变量 .rodata 存放的是只读变量,比如const修饰的变量 .bss 存放未初始化的全局变量和局部静态变量 … …

来查看下目标文件SimpleSection.o的段信息:

$objdump -x -s -d SimpleSection.oSimpleSection.o:     file format elf64-x86-64SimpleSection.oarchitecture: i386:x86-64, flags 0x00000011:HAS_RELOC, HAS_SYMSstart address 0x0000000000000000Sections:Idx Name          Size      VMA               LMA               File off  Algn0 .text         00000056  0000000000000000  0000000000000000  00000040  2**2              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data         00000008  0000000000000000  0000000000000000  00000098  2**2              CONTENTS, ALLOC, LOAD, DATA2 .bss          00000004  0000000000000000  0000000000000000  000000a0  2**2              ALLOC3 .rodata       00000004  0000000000000000  0000000000000000  000000a0  2**0              CONTENTS, ALLOC, LOAD, READONLY, DATA4 .comment      00000012  0000000000000000  0000000000000000  000000a4  2**0              CONTENTS, READONLY5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b6  2**0              CONTENTS, READONLY6 .eh_frame     00000058  0000000000000000  0000000000000000  000000b8  2**3              CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATASYMBOL TABLE:0000000000000000 l    df *ABS*  0000000000000000 SimpleSection.c0000000000000000 l    d  .text  0000000000000000 .text0000000000000000 l    d  .data  0000000000000000 .data0000000000000000 l    d  .bss   0000000000000000 .bss0000000000000000 l    d  .rodata    0000000000000000 .rodata0000000000000004 l     O .data  0000000000000004 static_var.17130000000000000000 l     O .bss   0000000000000004 static_var2.17140000000000000000 l    d  .note.GNU-stack    0000000000000000 .note.GNU-stack0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame0000000000000000 l    d  .comment   0000000000000000 .comment0000000000000000 g     O .data  0000000000000004 global_init_var0000000000000004       O *COM*  0000000000000004 global_uninit_var0000000000000000 g     F .text  0000000000000021 func10000000000000000         *UND*  0000000000000000 printf0000000000000021 g     F .text  0000000000000035 mainContents of section .text:0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...0010 bf000000 00b80000 0000e800 000000c9  ................0020 c3554889 e54883ec 10c745fc 01000000  .UH..H....E.....0030 8b150000 00008b05 00000000 01c28b45  ...............E0040 fc01c28b 45f801d0 89c7e800 000000b8  ....E...........0050 00000000 c9c3                        ......Contents of section .data:0000 54000000 55000000                    T...U...Contents of section .rodata:0000 25640a00                             %d..Contents of section .comment:0000 00474343 3a202847 4e552920 342e372e  .GCC: (GNU) 4.7.0010 3300                                 3.Contents of section .eh_frame:0000 14000000 00000000 017a5200 01781001  .........zR..x..0010 1b0c0708 90010000 1c000000 1c000000  ................0020 00000000 21000000 00410e10 8602430d  ....!....A....C.0030 065c0c07 08000000 1c000000 3c000000  .\..........<...0040 00000000 35000000 00410e10 8602430d  ....5....A....C.0050 06700c07 08000000                    .p......Disassembly of section .text:0000000000000000 <func1>:0:  55                      push   %rbp1:  48 89 e5                mov    %rsp,%rbp4:  48 83 ec 10             sub    $0x10,%rsp8:  89 7d fc                mov    %edi,-0x4(%rbp)b:  8b 45 fc                mov    -0x4(%rbp),%eaxe:  89 c6                   mov    %eax,%esi10: bf 00 00 00 00          mov    $0x0,%edi        11: R_X86_64_32 .rodata15: b8 00 00 00 00          mov    $0x0,%eax1a: e8 00 00 00 00          callq  1f <func1+0x1f>        1b: R_X86_64_PC32   printf-0x41f: c9                      leaveq20: c3                      retq0000000000000021 <main>:21: 55                      push   %rbp22: 48 89 e5                mov    %rsp,%rbp25: 48 83 ec 10             sub    $0x10,%rsp29: c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)30: 8b 15 00 00 00 00       mov    0x0(%rip),%edx        # 36 <main+0x15>        32: R_X86_64_PC32   .data36: 8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 3c <main+0x1b>        38: R_X86_64_PC32   .bss-0x43c: 01 c2                   add    %eax,%edx3e: 8b 45 fc                mov    -0x4(%rbp),%eax41: 01 c2                   add    %eax,%edx43: 8b 45 f8                mov    -0x8(%rbp),%eax46: 01 d0                   add    %edx,%eax48: 89 c7                   mov    %eax,%edi4a: e8 00 00 00 00          callq  4f <main+0x2e>        4b: R_X86_64_PC32   func1-0x44f: b8 00 00 00 00          mov    $0x0,%eax54: c9                      leaveq55: c3                      retq
0 0
原创粉丝点击