GCC工具编译集

本文详细介绍了GCC编译工具集及其在C/C++程序编译过程中的四个阶段:预处理、编译、汇编和链接。通过示例程序展示了每个阶段的输出,并探讨了ELF文件的结构,包括节头、段和调试信息。同时,讲解了如何使用addr2line、objdump和readelf等工具对ELF文件进行反汇编和分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、GCC编译的工具集

二、GCC编译过程

2.1程序编译

2.2实际编译 

 三、ELF文件

1.ELF文件 

 2.反汇编ELF


一、GCC编译的工具集

GCC是编译工具,它可以将 C/C++语言编写的程序转换成为处理器能够执行的二进制代码。下表是部分GCC二进制程序的处理工具。

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

二、GCC编译过程

示例程序代码:

#include<stdio.h>
int main(void)
{
	printf("Hello World!\n");
	return 0;
}

2.1程序编译

输入命令:

 gcc test.c -o test

2.2实际编译 

 GCC的编译分为四个阶段,分别为预处理,编译,汇编和连接

编译阶段编译命令作用
预处理gcc -E test.c -o test.i编译器将源代码中包含头文件编译进来
编译gcc -S test.i -o test.s检查代码规范性并翻译成汇编语言
汇编gcc -c test.s -o test.o将.s文件转换为目标文件
链接gcc test.o -o test将目标文件转换为可执行文件

(1)预处理:

test.i部分代码:

(2) 编译:

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

test.s部分代码:

(3) 汇编:

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

(4)连接:

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

 三、ELF文件

1.ELF文件 

ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
ELF文件格式如下图,位于ELF Header和Section Header Table 之间的都是段(Section)。一个典型的ELF文件包含下面几个段:
.text:已编译程序的指令代码段。
.rodata:ro 代表 read only,即只读数据(譬如常数 const)。
.data:已初始化的 C 程序全局变量和静态局部变量。
.bss:未初始化的 C 程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试。

 

  • 使用readelf -S test查看test可执行文件各个section的信息

 

There are 34 section headers, starting at offset 0x2158:

节头:
  [号] 名称              类型             地址              偏移量
       大小              全体大小          旗标   链接   信息   对齐
  [ 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
  [ 3] .note.gnu.build-i NOTE             0000000000000274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000298  00000298
       000000000000001c  0000000000000000   A       5     0     8
 ……
  [31] .symtab           SYMTAB           0000000000000000  000017b8
       0000000000000660  0000000000000018          32    48     8
  [32] .strtab           STRTAB           0000000000000000  00001e18
       0000000000000202  0000000000000000           0     0     1
  [33] .shstrtab         STRTAB           0000000000000000  0000201a
       000000000000013e  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)

 2.反汇编ELF

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

objdump -D test

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   

……

000000000000063a <main>:
#include<stdio.h>
int main(void)
{
 63a:    55                       push   %rbp
 63b:    48 89 e5                 mov    %rsp,%rbp
    printf("Hello World!\n");
 63e:    48 8d 3d 9f 00 00 00     lea    0x9f(%rip),%rdi        # 6e4 <_IO_stdin_used+0x4>
 645:    e8 c6 fe ff ff           callq  510 <puts@plt>
    return 0;
 64a:    b8 00 00 00 00           mov    $0x0,%eax
}
 64f:    5d                       pop    %rbp
 650:    c3                       retq   
 651:    66 2e 0f 1f 84 00 00     nopw   %cs:0x0(%rax,%rax,1)
 658:    00 00 00 
 65b:    0f 1f 44 00 00           nopl   0x0(%rax,%rax,1)

0000000000000660 <__libc_csu_init>:
 660:    41 57                    push   %r15
 662:    41 56                    push   %r14
 664:    49 89 d7                 mov    %rdx,%r15
 667:    41 55                    push   %r13
 669:    41 54                    push   %r12
 66b:    4c 8d 25 46 07 20 00     lea    0x200746(%rip),%r12        # 200db8 <__frame_dummy_init_array_entry>
 672:    55                       push   %rbp
 673:    48 8d 2d 46 07 20 00     lea    0x200746(%rip),%rbp        # 200dc0 <__init_array_end>
 67a:    53                       push   %rbx
 67b:    41 89 fd                 mov    %edi,%r13d
 67e:    49 89 f6                 mov    %rsi,%r14
 681:    4c 29 e5                 sub    %r12,%rbp
 684:    48 83 ec 08              sub    $0x8,%rsp
 688:    48 c1 fd 03              sar    $0x3,%rbp
 68c:    e8 57 fe ff ff           callq  4e8 <_init>
 691:    48 85 ed                 test   %rbp,%rbp
 694:    74 20                    je     6b6 <__libc_csu_init+0x56>
 696:    31 db                    xor    %ebx,%ebx
 698:    0f 1f 84 00 00 00 00     nopl   0x0(%rax,%rax,1)
 69f:    00 
 6a0:    4c 89 fa                 mov    %r15,%rdx
 6a3:    4c 89 f6                 mov    %r14,%rsi
 6a6:    44 89 ef                 mov    %r13d,%edi
 6a9:    41 ff 14 dc              callq  *(%r12,%rbx,8)
 6ad:    48 83 c3 01              add    $0x1,%rbx
 6b1:    48 39 dd                 cmp    %rbx,%rbp
 6b4:    75 ea                    jne    6a0 <__libc_csu_init+0x40>
 6b6:    48 83 c4 08              add    $0x8,%rsp
 6ba:    5b                       pop    %rbx
 6bb:    5d                       pop    %rbp
 6bc:    41 5c                    pop    %r12
 6be:    41 5d                    pop    %r13
 6c0:    41 5e                    pop    %r14
 6c2:    41 5f                    pop    %r15
 6c4:    c3                       retq   
 6c5:    90                       nop
 6c6:    66 2e 0f 1f 84 00 00     nopw   %cs:0x0(%rax,%rax,1)
 6cd:    00 00 00 

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

 使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:
执行命令gcc -o hello -g hello.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   

……

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 <main>
 554:    ff 15 86 0a 20 00        callq  *0x200a86(%rip)        # 200fe0 <__libc_start_main@GLIBC_2.2.5>
 55a:    f4                       hlt    
 55b:    0f 1f 44 00 00           nopl   0x0(%rax,%rax,1)

……

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  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值