gcc编译和目标文件
gcc编译和目标文件
- 1 基本概念
- 1.1 链接过程类型
- 1.2 目标文件形式
- 2 Gcc编译过程示例
- 2.1 示例代码
- 2.2 预处理
- 2.2.1 main.i
- 2.2.2 add.i
- 2.3 编译
- 2.3.1 main.s
- 2.4 汇编和反汇编
- 2.4.1 main.o
- 2.4.2 add.o
- 2.5 链接
- 2.6 相关命令汇总
- 3 可执行文件分析
- 3.1 可执行ELF文件空间布局
- 3.2 可执行文件反编译
- 3.2.1 文件基本信息
- 3.2.2 程序头部表信息
- 3.2.3 段信息
- 3.2.4 符号表信息
- 3.2.5 反汇编信息
- 4 加载可执行目标文件
- 4.1 运行时内存映像
- 5 参考资料
1 基本概念
Gcc编译4阶段:预处理、编译、汇编、链接
预处理(cpp):处理头文件、宏定义、条件编译等;
编译(ccl):代码检查,生成.s汇编文件;
汇编(as):生成可重定位(全局、外部函数等符号)的.o目标文件;
链接过程(ld):把所有代码和数据组合到单个文件,这个文件可以被加载到内存中执行。
1.1 链接过程类型
编译期链接:针编译可执行文件过程时对静态库、可重定位目标文件的链接
加载期链接:针对动态库的运行时链接,在被加载器加载到内存执行时。
运行时链接:针对动态库,由应用程序来动态加载库文件,相关函数如:dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym。Java本地接口即通过运行时链接方式动态链接和加载使用C/C++编译生成的动态链接库。
1.2 目标文件形式
可重定位目标文件:编译、汇编后的.o目标文件,可重定位;
可执行目标文件:二进制可执行目标文件,静态链接后的bin文件
共享目标文件:动态链接库
2 Gcc编译过程示例
2.1 示例代码
三个文件
add.h文件内容:
int add(int a,int b);
add.c文件内容:
int add(int a,int b)
{
return a+b;
}
main.c文件内容:
#include “add.h”
int a = 1;
int b = 2;
int main()
{
int res=add(a,b);
}
2.2 预处理
2.2.1 main.i
gcc -E main.c -o main.i
生成对main.c预处理后的main.i文件
# 1 "main.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "main.c"# 1 "add.h" 1int add(int a,int b);# 2 "main.c" 2int a = 1;int b = 2;int main(){ int res=add(a,b);}
2.2.2 add.i
# 1 "add.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "add.c"int add(int a,int b){ return a+b;}
2.3 编译
2.3.1 main.s
cc1 -m32 main.i -o main.s
生成汇编文件main.s
备注:
1、 这里以32bit进行编译
2、 若提示命令找不到,原因是cc1所在目录不在$PATH环境变量中,可使用可使用绝对路径,如/usr/lib/gcc/x86_64-linux-gnu/4.8.4/cc1 -m32 main.i -o main.s
3、 cc1第3个字符是数字1,不是字母l
.file"main.i".globla.data.align 4.typea, @object.sizea, 4a:.long1.globlb.align 4.typeb, @object.sizeb, 4b:.long2.text.globlmain.typemain, @functionmain:.LFB0:.cfi_startprocpushq%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq%rsp, %rbp.cfi_def_cfa_register 6subq$16, %rspmovlb(%rip), %edxmovla(%rip), %eaxmovl%edx, %esimovl%eax, %edicalladdmovl%eax, -4(%rbp)leave.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.sizemain, .-main.ident"GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4".section.note.GNU-stack,"",@progbits2.3.2add.s.file"add.i".text.globladd.typeadd, @functionadd:.LFB0:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5movl12(%ebp), %eaxmovl8(%ebp), %edxaddl%edx, %eaxpopl%ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE0:.sizeadd, .-add.ident"GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4".section.note.GNU-stack,"",@progbits
2.4 汇编和反汇编
as --32 -o main.o main.s
生成可重定位目标文件main.o
2.4.1 main.o
此文件不好使用cat直接查看,会显示一堆乱码。
可使用objdump进行反汇编命令选项查看:
objdump -dx main.o
-d:反汇编
-x:显示所有header
命令结果显示如下:
main.o: file format elf32-i386main.oarchitecture: i386, flags 0x00000011:HAS_RELOC, HAS_SYMSstart address 0x00000000Sections:Idx Name Size VMA LMA File off Algn 0 .text 00000026 00000000 00000000 00000034 2**0 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000008 00000000 00000000 0000005c 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000000 00000000 00000000 00000064 2**0 ALLOC 3 .comment 0000002c 00000000 00000000 00000064 2**0 CONTENTS, READONLY 4 .note.GNU-stack 00000000 00000000 00000000 00000090 2**0 CONTENTS, READONLY 5 .eh_frame 00000038 00000000 00000000 00000090 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATASYMBOL TABLE:00000000 l df *ABS*00000000 main.i00000000 l d .text00000000 .text00000000 l d .data00000000 .data00000000 l d .bss00000000 .bss00000000 l d .note.GNU-stack00000000 .note.GNU-stack00000000 l d .eh_frame00000000 .eh_frame00000000 l d .comment00000000 .comment00000000 g O .data00000004 a00000004 g O .data00000004 b00000000 g F .text00000026 main00000000 *UND*00000000 addDisassembly of section .text:00000000 <main>: 0:55 push %ebp 1:89 e5 mov %esp,%ebp 3:83 e4 f0 and $0xfffffff0,%esp 6:83 ec 20 sub $0x20,%esp 9:8b 15 00 00 00 00 mov 0x0,%edxb: R_386_32b f:a1 00 00 00 00 mov 0x0,%eax10: R_386_32a 14:89 54 24 04 mov %edx,0x4(%esp) 18:89 04 24 mov %eax,(%esp) 1b:e8 fc ff ff ff call 1c <main+0x1c>1c: R_386_PC32add 20:89 44 24 1c mov %eax,0x1c(%esp) 24:c9 leave 25:c3 ret
2.4.2 add.o
main.o: file format elf32-i386main.oarchitecture: i386, flags 0x00000011:HAS_RELOC, HAS_SYMSstart address 0x00000000Sections:Idx Name Size VMA LMA File off Algn 0 .text 00000026 00000000 00000000 00000034 2**0 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000008 00000000 00000000 0000005c 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000000 00000000 00000000 00000064 2**0 ALLOC 3 .comment 0000002c 00000000 00000000 00000064 2**0 CONTENTS, READONLY 4 .note.GNU-stack 00000000 00000000 00000000 00000090 2**0 CONTENTS, READONLY 5 .eh_frame 00000038 00000000 00000000 00000090 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATASYMBOL TABLE:00000000 l df *ABS*00000000 main.i00000000 l d .text00000000 .text00000000 l d .data00000000 .data00000000 l d .bss00000000 .bss00000000 l d .note.GNU-stack00000000 .note.GNU-stack00000000 l d .eh_frame00000000 .eh_frame00000000 l d .comment00000000 .comment00000000 g O .data00000004 a00000004 g O .data00000004 b00000000 g F .text00000026 main00000000 *UND*00000000 addDisassembly of section .text:00000000 <main>: 0:55 push %ebp 1:89 e5 mov %esp,%ebp 3:83 e4 f0 and $0xfffffff0,%esp 6:83 ec 20 sub $0x20,%esp 9:8b 15 00 00 00 00 mov 0x0,%edxb: R_386_32b f:a1 00 00 00 00 mov 0x0,%eax10: R_386_32a 14:89 54 24 04 mov %edx,0x4(%esp) 18:89 04 24 mov %eax,(%esp) 1b:e8 fc ff ff ff call 1c <main+0x1c>1c: R_386_PC32add 20:89 44 24 1c mov %eax,0x1c(%esp) 24:c9 leave 25:c3 ret
2.5 链接
ld -m elf_i386 -o main main.o add.o
2.6 相关命令汇总
cpp main.c main.i
cc1 main.i -o main.s
as --32 -o main.o main.s
objdump -dx main.o >main.o.txt
cpp add.c add.i
/usr/lib/gcc/x86_64-linux-gnu/4.8.4/cc1 -m32 add.i -o add.s
as --32 -o add.o add.s
objdump -dx add.o >add.o.txt
链接:
ld -m elf_i386 -o main main.o add.o
备注:cc1命令使用的版本路径
/usr/lib/gcc/x86_64-linux-gnu/4.8.4/ cc1
3 可执行文件分析
3.1 可执行ELF文件空间布局
3.2 可执行文件反编译
objdump -dx main
3.2.1 文件基本信息
main: file format elf32-i386
main
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048094
3.2.2 程序头部表信息
Program Header:
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 212
filesz 0x00000120 memsz 0x00000120 flags r-x
LOAD off 0x00000120 vaddr 0x08049120 paddr 0x08049120 align 212
filesz 0x00000008 memsz 0x00000008 flags rw-
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
filesz 0x00000000 memsz 0x00000000 flags rw-
说明:
Off:目标文件中的偏移
Vadd/paddr:内存地址
Align:对齐要求
Filesz:目标文件中的段大小
Memsz:内存中的段大小
Flags:运行时访问权限
3.2.3 段信息
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000033 08048094 08048094 00000094 20
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 00000058 080480c8 080480c8 000000c8 22
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .data 00000008 08049120 08049120 00000120 22
CONTENTS, ALLOC, LOAD, DATA
3 .comment 0000002b 00000000 00000000 00000128 20
CONTENTS, READONLY
3.2.4 符号表信息
SYMBOL TABLE:
08048094 l d .text 00000000 .text
080480c8 l d .eh_frame 00000000 .eh_frame
08049120 l d .data 00000000 .data
00000000 l d .comment 00000000 .comment
00000000 l df ABS 00000000 main.i
00000000 l df ABS 00000000 add.i
00000000 l df ABS 00000000
08049124 g O .data 00000004 b
080480ba g F .text 0000000d add
00000000 UND 00000000 _start
08049128 g .data 00000000 __bss_start
08048094 g F .text 00000026 main
08049128 g .data 00000000 _edata
08049128 g .data 00000000 _end
08049120 g O .data 00000004 a
3.2.5 反汇编信息
Disassembly of section .text:
08048094 :
8048094: 55 push %ebp
8048095: 89 e5 mov %esp,%ebp
8048097: 83 e4 f0 and $0xfffffff0,%esp
804809a: 83 ec 20 sub $0x20,%esp
804809d: 8b 15 24 91 04 08 mov 0x8049124,%edx
80480a3: a1 20 91 04 08 mov 0x8049120,%eax
80480a8: 89 54 24 04 mov %edx,0x4(%esp)
80480ac: 89 04 24 mov %eax,(%esp)
80480af: e8 06 00 00 00 call 80480ba
80480b4: 89 44 24 1c mov %eax,0x1c(%esp)
80480b8: c9 leave
80480b9: c3 ret
080480ba :
80480ba: 55 push %ebp
80480bb: 89 e5 mov %esp,%ebp
80480bd: 8b 45 0c mov 0xc(%ebp),%eax
80480c0: 8b 55 08 mov 0x8(%ebp),%edx
80480c3: 01 d0 add %edx,%eax
80480c5: 5d pop %ebp
80480c6: c3 ret
4 加载可执行目标文件
4.1 运行时内存映像
5 参考资料
1、《深入理解计算机系统》,【美】Randal E.Bryant,David R.O’Hallaron
, 第3版,2019年3月,机械工业出版社,