mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 03:01:15 +07:00
fix 1.5.1
This commit is contained in:
parent
e580953d01
commit
c84ccf50a6
@ -31,6 +31,17 @@ hello world
|
||||
```text
|
||||
$gcc -E hello.c -o hello.i
|
||||
```
|
||||
```
|
||||
# 1 "hello.c"
|
||||
# 1 "<built-in>"
|
||||
# 1 "<command-line>"
|
||||
......
|
||||
extern int printf (const char *__restrict __format, ...);
|
||||
......
|
||||
main() {
|
||||
printf("hello, world\n");
|
||||
}
|
||||
```
|
||||
|
||||
预编译过程主要处理源代码中以 “#” 开始的预编译指令:
|
||||
- 将所有的 “#define” 删除,并且展开所有的宏定义。
|
||||
@ -44,6 +55,35 @@ $gcc -E hello.c -o hello.i
|
||||
```text
|
||||
$gcc -S hello.c -o hello.s
|
||||
```
|
||||
```
|
||||
.file "hello.c"
|
||||
.section .rodata
|
||||
.LC0:
|
||||
.string "hello, world"
|
||||
.text
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
.LFB0:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
leaq .LC0(%rip), %rdi
|
||||
call puts@PLT
|
||||
movl $0, %eax
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size main, .-main
|
||||
.ident "GCC: (GNU) 7.2.0"
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
```
|
||||
|
||||
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。
|
||||
|
||||
#### 汇编
|
||||
@ -52,10 +92,61 @@ $gcc -c hello.s -o hello.o
|
||||
或者
|
||||
$gcc -c hello.c -o hello.o
|
||||
```
|
||||
```
|
||||
$ objdump -sd hello.o
|
||||
|
||||
hello.o: file format elf64-x86-64
|
||||
|
||||
Contents of section .text:
|
||||
0000 554889e5 488d3d00 000000e8 00000000 UH..H.=.........
|
||||
0010 b8000000 005dc3 .....].
|
||||
Contents of section .rodata:
|
||||
0000 68656c6c 6f2c2077 6f726c64 00 hello, world.
|
||||
Contents of section .comment:
|
||||
0000 00474343 3a202847 4e552920 372e322e .GCC: (GNU) 7.2.
|
||||
0010 3000 0.
|
||||
Contents of section .eh_frame:
|
||||
0000 14000000 00000000 017a5200 01781001 .........zR..x..
|
||||
0010 1b0c0708 90010000 1c000000 1c000000 ................
|
||||
0020 00000000 17000000 00410e10 8602430d .........A....C.
|
||||
0030 06520c07 08000000 .R......
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0000000000000000 <main>:
|
||||
0: 55 push %rbp
|
||||
1: 48 89 e5 mov %rsp,%rbp
|
||||
4: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # b <main+0xb>
|
||||
b: e8 00 00 00 00 callq 10 <main+0x10>
|
||||
10: b8 00 00 00 00 mov $0x0,%eax
|
||||
15: 5d pop %rbp
|
||||
16: c3 retq
|
||||
```
|
||||
|
||||
汇编器将汇编代码转变成机器可以执行的指令。
|
||||
|
||||
#### 链接
|
||||
目标文件需要链接一大堆文件才能得到最终的可执行文件。链接过程主要包括地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定向(Relocation)等。
|
||||
```
|
||||
$ gcc hello.o -o hello
|
||||
```
|
||||
```
|
||||
$ objdump -d -j .text hello
|
||||
......
|
||||
000000000000064a <main>:
|
||||
64a: 55 push %rbp
|
||||
64b: 48 89 e5 mov %rsp,%rbp
|
||||
64e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6f4 <_IO_stdin_used+0x4>
|
||||
655: e8 d6 fe ff ff callq 530 <puts@plt>
|
||||
65a: b8 00 00 00 00 mov $0x0,%eax
|
||||
65f: 5d pop %rbp
|
||||
660: c3 retq
|
||||
661: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
|
||||
668: 00 00 00
|
||||
66b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
|
||||
......
|
||||
```
|
||||
|
||||
目标文件需要链接一大堆文件才能得到最终的可执行文件(上面只展示了链接后的 main 函数,可以和 hello.o 中的 main 函数作对比)。链接过程主要包括地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定向(Relocation)等。
|
||||
|
||||
#### gcc 技巧
|
||||
通常在编译后只会生成一个可执行文件,而中间过程生成的 `.i`、`.s`、`.o` 文件都不会被保存。我们可以使用参数 `-save-temps` 永久保存这些临时的中间文件。
|
||||
@ -70,6 +161,21 @@ a.out hello.c hello.i hello.o hello.s
|
||||
$ file a.out
|
||||
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=533aa4ca46d513b1276d14657ec41298cafd98b1, not stripped
|
||||
```
|
||||
|
||||
使用参数 `--verbose` 可以输出 gcc 详细的工作流程。
|
||||
```
|
||||
$ gcc hello.c -static --verbose
|
||||
```
|
||||
东西很多,我们主要关注下面几条信息:
|
||||
```
|
||||
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -version -o /tmp/ccj1jUMo.s
|
||||
|
||||
as -v --64 -o /tmp/ccAmXrfa.o /tmp/ccj1jUMo.s
|
||||
|
||||
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1l5oJV.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --build-id --hash-style=gnu -m elf_x86_64 -static /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtbeginT.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../.. /tmp/ccAmXrfa.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib/crtn.o
|
||||
```
|
||||
三条指令分别是 `cc1`、`as` 和 `collect2`,cc1 是 gcc 的编译器,将 `.c` 文件编译为 `.s` 文件,as 是汇编器命令,将 `.s` 文件汇编成 `.o` 文件,collect2 是链接器命令,它是对命令 ld 的封装。静态链接时,gcc 将 C 语言运行时库的 5 个重要目标文件 `crt1.o`、`crti.o`、`crtbeginT.o`、`crtend.o`、`crtn.o` 和 `-lgcc`、`-lgcc_eh`、`-lc` 表示的 3 个静态库链接到可执行文件中。
|
||||
|
||||
更多的内容我们会在 1.5.3 中专门对 ELF 文件进行讲解。
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user