GCC编译工具集

GCC不是一个人在战斗,GCC背后其实有一堆战友。

 

目录

一、GCC的合作伙伴 

二、GCC编译具体过程

2.1 简单编译

2.2 实际编译 

①预处理 

 ②编译为汇编代码

 ③汇编

 ④连接

三、分析ELF文件

3.1 ELF文件的段

 3.2 反汇编ELF


一、GCC的合作伙伴 

以下介绍部分gcc二进制程序处理工具

 工具            作用
addr2line 用来将程序地址转换成其所对应的程序源文件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置
as 主要用于汇编
ld 主要用于链接
ar  主要用于创建静态库
ldd 可以用于查看一个可执行程序依赖的共享库
objcopy 将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或者将.elf 转换成.bin 等
objdump 主要的作用是反汇编
readelf 显示有关ELF文件的信息
size 列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等

二、GCC编译具体过程

示例程序如下

#include
int main(void)
{
	printf("Hello World!\n");
	return 0;
}

2.1 简单编译

 gcc test.c -o test

GCC编译工具集_第1张图片

2.2 实际编译 

实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。

①预处理 

 执行命令gcc -E test.c -o test.i 或gcc -E test.c,生成test.i文件

test.i部分代码:

GCC编译工具集_第2张图片

 ②编译为汇编代码

执行命令gcc -S test.i -o test.s,生成test.s文件

test.s部分代码:

GCC编译工具集_第3张图片

 ③汇编

 执行命令gcc -c test.s -o test.o,生成test.o文件

 ④连接

执行命令gcc test.o -o test,生成test可执行文件

GCC编译工具集_第4张图片

 

三、分析ELF文件

3.1 ELF文件的段

ELF文件格式如下图,位于ELF Header和Section Header Table 之间的都是段(Section)。一个典型的ELF文件包含下面几个段:

·text:已编译程序的指令代码段。
·rodata:ro 代表 read only,即只读数据(譬如常数 const)。
·data:已初始化的 C 程序全局变量和静态局部变量。
·bss:未初始化的 C 程序全局变量和静态局部变量。
·debug:调试符号表,调试器用此段的信息帮助调试。
GCC编译工具集_第5张图片

可以使用readelf -S test查看test可执行文件各个section的信息如下:

There are 29 section headers, starting at offset 0x1928:

节头:
  [号] 名称              类型             地址              偏移量
       大小              全体大小          旗标   链接   信息   对齐
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000000254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  ······
  [ 6] .dynstr           STRTAB           0000000000000360  00000360
       0000000000000082  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           00000000000003e2  000003e2
       000000000000000e  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          00000000000003f0  000003f0
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000000410  00000410
       00000000000000c0  0000000000000018   A       5     0     8
  ······
  [13] .plt.got          PROGBITS         0000000000000520  00000520
       0000000000000008  0000000000000008  AX       0     0     8
  [14] .text             PROGBITS         0000000000000530  00000530
       00000000000001a2  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         00000000000006d4  000006d4
       0000000000000009  0000000000000000  AX       0     0     4
  
  ······
  [22] .got              PROGBITS         0000000000200fb8  00000fb8
       0000000000000048  0000000000000008  WA       0     0     8
  [23] .data             PROGBITS         0000000000201000  00001000
       0000000000000010  0000000000000000  WA       0     0     8
  ······
  [26] .symtab           SYMTAB           0000000000000000  00001040
       00000000000005e8  0000000000000018          27    43     8
  [27] .strtab           STRTAB           0000000000000000  00001628
       0000000000000202  0000000000000000           0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  0000182a
       00000000000000fe  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

 3.2 反汇编ELF

由于ELF文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF文件包含的指令和数据,需要使用反汇编的方法。

使用objdump -D test对其进行反汇编如下:

test:     文件格式 elf64-x86-64


Disassembly of section .interp:

0000000000000238 <.interp>:
 238:	2f                   	(bad)  
 239:	6c                   	insb   (%dx),%es:(%rdi)
 23a:	69 62 36 34 2f 6c 64 	imul   $0x646c2f34,0x36(%rdx),%esp
 241:	2d 6c 69 6e 75       	sub    $0x756e696c,%eax
 246:	78 2d                	js     275 <_init-0x273>
 248:	78 38                	js     282 <_init-0x266>
 24a:	36 2d 36 34 2e 73    	ss sub $0x732e3436,%eax
 250:	6f                   	outsl  %ds:(%rsi),(%dx)
 251:	2e 32 00             	xor    %cs:(%rax),%al
······

Disassembly of section .comment:

0000000000000000 <.comment>:
   0:	47                   	rex.RXB
   1:	43                   	rex.XB
   2:	43 3a 20             	rex.XB cmp (%r8),%spl
   5:	28 55 62             	sub    %dl,0x62(%rbp)
   8:	75 6e                	jne    78 <_init-0x470>
   a:	74 75                	je     81 <_init-0x467>
   c:	20 37                	and    %dh,(%rdi)
   e:	2e 35 2e 30 2d 33    	cs xor $0x332d302e,%eax
  14:	75 62                	jne    78 <_init-0x470>
  16:	75 6e                	jne    86 <_init-0x462>
  18:	74 75                	je     8f <_init-0x459>
  1a:	31 7e 31             	xor    %edi,0x31(%rsi)
  1d:	38 2e                	cmp    %ch,(%rsi)
  1f:	30 34 29             	xor    %dh,(%rcx,%rbp,1)
  22:	20 37                	and    %dh,(%rdi)
  24:	2e                   	cs
  25:	35                   	.byte 0x35
  26:	2e 30 00             	xor    %al,%cs:(%rax)

使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:

执行命令gcc -o test -g test.c再执行objdump -S test

得到如下结果:

test:     文件格式 elf64-x86-64


Disassembly of section .init:

00000000000004e8 <_init>:
 4e8:	48 83 ec 08          	sub    $0x8,%rsp
 4ec:	48 8b 05 f5 0a 20 00 	mov    0x200af5(%rip),%rax        # 200fe8 <__gmon_start__>
 4f3:	48 85 c0             	test   %rax,%rax
 4f6:	74 02                	je     4fa <_init+0x12>
 4f8:	ff d0                	callq  *%rax
 4fa:	48 83 c4 08          	add    $0x8,%rsp
 4fe:	c3                   	retq   

······
xchg   %ax,%ax

Disassembly of section .text:

0000000000000530 <_start>:
 530:	31 ed                	xor    %ebp,%ebp
 532:	49 89 d1             	mov    %rdx,%r9
 535:	5e                   	pop    %rsi
 536:	48 89 e2             	mov    %rsp,%rdx
 539:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
 53d:	50                   	push   %rax
 53e:	54                   	push   %rsp
 53f:	4c 8d 05 8a 01 00 00 	lea    0x18a(%rip),%r8        # 6d0 <__libc_csu_fini>
 546:	48 8d 0d 13 01 00 00 	lea    0x113(%rip),%rcx        # 660 <__libc_csu_init>
 54d:	48 8d 3d e6 00 00 00 	lea    0xe6(%rip),%rdi        # 63a 
······ 00000000000006d0 <__libc_csu_fini>: 6d0: f3 c3 repz retq Disassembly of section .fini: 00000000000006d4 <_fini>: 6d4: 48 83 ec 08 sub $0x8,%rsp 6d8: 48 83 c4 08 add $0x8,%rsp 6dc: c3 retq

 

你可能感兴趣的:(c++,ubuntu,linux)