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

8 篇文章 0 订阅

目标文件

目标文件的格式

目标文件在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.o
hello.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.o

SimpleSection.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
0 .text         00000056  0000000000000000  0000000000000000  00000040  2**2
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data         00000008  0000000000000000  0000000000000000  00000098  2**2
              CONTENTS, ALLOC, LOAD, DATA
2 .bss          00000004  0000000000000000  0000000000000000  000000a0  2**2
              ALLOC
3 .rodata       00000004  0000000000000000  0000000000000000  000000a0  2**0
              CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment      00000012  0000000000000000  0000000000000000  000000a4  2**0
              CONTENTS, READONLY
5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b6  2**0
              CONTENTS, READONLY
6 .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.o
text       data     bss     dec     hex filename
178       8       4     190      be SimpleSection.o

段的说明

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

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

$objdump -x -s -d SimpleSection.o
SimpleSection.o:     file format elf64-x86-64
SimpleSection.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
0 .text         00000056  0000000000000000  0000000000000000  00000040  2**2
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data         00000008  0000000000000000  0000000000000000  00000098  2**2
              CONTENTS, ALLOC, LOAD, DATA
2 .bss          00000004  0000000000000000  0000000000000000  000000a0  2**2
              ALLOC
3 .rodata       00000004  0000000000000000  0000000000000000  000000a0  2**0
              CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment      00000012  0000000000000000  0000000000000000  000000a4  2**0
              CONTENTS, READONLY
5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b6  2**0
              CONTENTS, READONLY
6 .eh_frame     00000058  0000000000000000  0000000000000000  000000b8  2**3
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 SimpleSection.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata    0000000000000000 .rodata
0000000000000004 l     O .data  0000000000000004 static_var.1713
0000000000000000 l     O .bss   0000000000000004 static_var2.1714
0000000000000000 l    d  .note.GNU-stack    0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame
0000000000000000 l    d  .comment   0000000000000000 .comment
0000000000000000 g     O .data  0000000000000004 global_init_var
0000000000000004       O *COM*  0000000000000004 global_uninit_var
0000000000000000 g     F .text  0000000000000021 func1
0000000000000000         *UND*  0000000000000000 printf
0000000000000021 g     F .text  0000000000000035 main

Contents 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  ...............E
0040 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   %rbp
1:  48 89 e5                mov    %rsp,%rbp
4:  48 83 ec 10             sub    $0x10,%rsp
8:  89 7d fc                mov    %edi,-0x4(%rbp)
b:  8b 45 fc                mov    -0x4(%rbp),%eax
e:  89 c6                   mov    %eax,%esi
10: bf 00 00 00 00          mov    $0x0,%edi
        11: R_X86_64_32 .rodata
15: b8 00 00 00 00          mov    $0x0,%eax
1a: e8 00 00 00 00          callq  1f <func1+0x1f>
        1b: R_X86_64_PC32   printf-0x4
1f: c9                      leaveq
20: c3                      retq

0000000000000021 <main>:
21: 55                      push   %rbp
22: 48 89 e5                mov    %rsp,%rbp
25: 48 83 ec 10             sub    $0x10,%rsp
29: 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   .data
36: 8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 3c <main+0x1b>
        38: R_X86_64_PC32   .bss-0x4
3c: 01 c2                   add    %eax,%edx
3e: 8b 45 fc                mov    -0x4(%rbp),%eax
41: 01 c2                   add    %eax,%edx
43: 8b 45 f8                mov    -0x8(%rbp),%eax
46: 01 d0                   add    %edx,%eax
48: 89 c7                   mov    %eax,%edi
4a: e8 00 00 00 00          callq  4f <main+0x2e>
        4b: R_X86_64_PC32   func1-0x4
4f: b8 00 00 00 00          mov    $0x0,%eax
54: c9                      leaveq
55: c3                      retq
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值