读书-程序员的自我修养-链接、封装与库(6: 第三章:目标文件里有什么(1)目标文件,objdump,file,size等命令)
1. 什么是目标文件?
1.1 目标文件
目标文件: 就是源代码编译之后未进行链接的那些中间文件(.obj和.o)。
目标文件从结构上说,他是已经编译后的可执行文件格式,只是还没有经过链接的过程。其中可能有些符号或者地址还没有被调整。
1.2 PE、ELF、COFF
PE、ELF: 现在PC下的可执行文件格式(Executable)主要是windows下的PE(Portable)和linux下的ELF(Executable Linkable Format)
COFF:(Common file format),COFF是Unix提出的并且使用的格式规范,后来微软基于COFF定制了PE;后面System V在COFF基础上引入了ELF格式。所以他们如此相似。
注: 其中动态链接库和静态链接库都是按照可执行文件格式存储的。
其中,静态链接库是把很多目标文件捆绑在一起形成一个文件,再加上一些索引。
可以把它理解为一个包含很多目标文件的文件包。
2. 目标文件是什么样?
2.1 simple.c 代码
root@ubuntu-admin-a1:/home# cat simple.c
#include<stdio.h>
int g_init_var = 100;
int g_uinit_var;
void func1(int i)
{
printf("%d\n",i);
}
int main()
{
static int iStaticVar = 101;
static int iStaticVar2;
int a = 1;
int b;
func1(iStaticVar + iStaticVar2 + a + b);
return 0;
}
2.2 simple.c 各个时期的文件类型,file 命令
gcc -E simple.c -o simple.i
gcc -S simple.i -o simple.s
gcc -c simple.s -o simple.o
gcc simple.c -o simple
file命令是用来检测并显示文件类型
root@ubuntu-admin-a1:/home# file simple.c
simple.c: C source, ASCII text
root@ubuntu-admin-a1:/home# file simple.i
simple.i: C source, ASCII text
root@ubuntu-admin-a1:/home# file simple.s
simple.s: assembler source, ASCII text
root@ubuntu-admin-a1:/home# file simple.o
simple.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
root@ubuntu-admin-a1:/home# file simple
simple: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=279476da281567f4e1fef5d790f133516d498bbd, not stripped
root@ubuntu-admin-a1:/home# ./simple
102
2.3 图解 simple.c 代码目标文件字段
总体来说,程序源代码被编译以后主要分成两种段:程序指令和程序数据。
代码段属于程序指令,而数据段和.bss段属于程序数据。
2.4 数据和指令分段的好处
- 程序被装载后,分别被映射到两个虚存区域;防止改写;
- 提高CPU缓存效率;
- 内存中只需要保存一份该程序部分;共享指令;
2.5 objdump -h simple.o
2.5.1 objdump命令
readelf 和 objdump 例子详解及区别
参考我的博客:
https://blog.csdn.net/lqy971966/article/details/106905237
- objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具
- 参数:-h
–section-headers
–headers
显示目标文件各个section的头部摘要信息。 - 参数:–d
–disassemble
从objfile中反汇编那些特定指令机器码的section。 - 参数: -s
–full-contents
显示指定section的完整内容。以十六进制打印出来 - -x
–all-headers
显示所可用的头信息,包括符号表、重定位入口。-x 等价于-a -f -h -r -t 同时指定。
2.5.2 objdump -h simple.o
root@ubuntu-admin-a1:/home# objdump -h simple.o
simple.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000057 0000000000000000 0000000000000000 00000040 2**0
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 00000035 0000000000000000 0000000000000000 000000a4 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000d9 2**0
CONTENTS, READONLY
6 .eh_frame 00000058 0000000000000000 0000000000000000 000000e0 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
root@ubuntu-admin-a1:/home#
由上可知,目标文件里面包含:
.text 代码段
.data 数据段
.bss 未初始化的数据段
.rodata 只读数据段
.comment 注释段
.note.GNU 堆栈提示段
2.5.3 simple.o的ELF结构图
2.5.4 size命令 simple.o //查看各个段的长度
size命令:显示一个目标文件或者链接库文件中的目标文件的各个段的大小
root@ubuntu-admin-a1:/home# size simple.o
text data bss dec hex filename
179 8 4 191 bf simple.o
root@ubuntu-admin-a1:/home#
2.5.5 objdump -s -d simple.o
root@ubuntu-admin-a1:/home# objdump -s -d simple.o
simple.o: file format elf64-x86-64
Contents of section .text:
0000 554889e5 4883ec10 897dfc8b 45fc89c6 UH..H....}..E...
0010 bf000000 00b80000 0000e800 00000090 ................
0020 c9c35548 89e54883 ec10c745 f8010000 ..UH..H....E....
0030 008b1500 0000008b 05000000 0001c28b ................
0040 45f801c2 8b45fc01 d089c7e8 00000000 E....E..........
0050 b8000000 00c9c3 .......
Contents of section .data:
0000 64000000 65000000 d...e...
Contents of section .rodata:
0000 25640a00 %d..
Contents of section .comment:
0000 00474343 3a202855 62756e74 7520352e .GCC: (Ubuntu 5.
0010 342e302d 36756275 6e747531 7e31362e 4.0-6ubuntu1~16.
0020 30342e34 2920352e 342e3020 32303136 04.4) 5.4.0 2016
0030 30363039 00 0609.
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 01781001 .........zR..x..
0010 1b0c0708 90010000 1c000000 1c000000 ................
0020 00000000 22000000 00410e10 8602430d ...."....A....C.
0030 065d0c07 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
15: b8 00 00 00 00 mov $0x0,%eax
1a: e8 00 00 00 00 callq 1f <func1+0x1f>
1f: 90 nop
20: c9 leaveq
21: c3 retq
0000000000000022 <main>:
22: 55 push %rbp
23: 48 89 e5 mov %rsp,%rbp
26: 48 83 ec 10 sub $0x10,%rsp
2a: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%rbp)
31: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 37 <main+0x15>
37: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 3d <main+0x1b>
3d: 01 c2 add %eax,%edx
3f: 8b 45 f8 mov -0x8(%rbp),%eax
42: 01 c2 add %eax,%edx
44: 8b 45 fc mov -0x4(%rbp),%eax
47: 01 d0 add %edx,%eax
49: 89 c7 mov %eax,%edi
4b: e8 00 00 00 00 callq 50 <main+0x2e>
50: b8 00 00 00 00 mov $0x0,%eax
55: c9 leaveq
56: c3 retq
root@ubuntu-admin-a1:/home#