GCC、G++

mian.c

int main() {
  return 0;
}

编译:gcc main.c && ./a.out,给 gcc 加上 -verbose 可以看到更多信息

GCC 编译过程:https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html

# 预处理(Preprocessing)
gcc -E main.c -o main.i
# 编译(Compilation)
gcc -S main.i -o main.s
# 汇编(Assemble)。.s 只能包含纯粹的汇编代码,.S 可以使用预处理命令(#开头)
gcc -c main.s -o main.o
# 链接(Linking)
# ld main.o -o main
gcc main.o -o main

 

查看 gcc 编译调用了那些命令:https://man7.org/linux/man-pages/man1/strace.1.html

sudo apt install -y strace

# strace -f gcc main.c &| vim -
# 用 strace 跟踪 gcc,并将信息输出到 vim
vim -c ':r! strace -f gcc main.c'
# 留下包含 execve 的行
:%! grep execve
# 一行显示,不换行
:set nowrap
# 去除包含 ENOENT 的行
:%! grep -v ENOENT
# 去除包含 resumed 的行
:%! grep -v resumed
# 把 , 换成 \r(换行)
:%s /, /\r /g
# 去掉所有行尾空格和 tab
:%s /\s\+$/ /g

过滤后的结果中可看到 gcc(源码 .c 到预处理 .i) 还调用了其它程序:cc1(预处理 .i 到汇编 .s)、as(汇编 .s 到机器码 .o)、collect2(多个机器码 .o 到可执行 .out)、ld(可执行 .out 与 libc 等库链接)

execve("/usr/bin/gcc"
 ["gcc"
 "main.c"]
 0x7ffe4b6efd70 /* 28 vars */) = 0
execve("/usr/lib/gcc/x86_64-linux-gnu/12/cc1"
 ["/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-quiet"
 "-imultiarch"
 "x86_64-linux-gnu"
 "main.c"
 "-quiet"
 "-dumpdir"
 "a-"
 "-dumpbase"
 "main.c"
 "-dumpbase-ext"
 ".c"
 "-mtune=generic"
 "-march=x86-64"
 "-fasynchronous-unwind-tables"
 "-o"
 "/tmp/ccxzcfJ7.s"]
 0x18704a0 /* 33 vars */ <unfinished ...>
execve("/usr/bin/as"
 ["as"
 "--64"
 "-o"
 "/tmp/ccPVAv5P.o"
 "/tmp/ccxzcfJ7.s"]
 0x18704a0 /* 33 vars */ <unfinished ...>
execve("/usr/lib/gcc/x86_64-linux-gnu/12/collect2"
 ["/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-plugin"
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-plugin-opt=/usr/lib/gcc/x86_64-"...
 "-plugin-opt=-fresolution=/tmp/cc"...
 "-plugin-opt=-pass-through=-lgcc"
 "-plugin-opt=-pass-through=-lgcc_"...
 "-plugin-opt=-pass-through=-lc"
 "-plugin-opt=-pass-through=-lgcc"
 "-plugin-opt=-pass-through=-lgcc_"...
 "--build-id"
 "--eh-frame-hdr"
 "-m"
 "elf_x86_64"
 "--hash-style=gnu"
 "--as-needed"
 "-dynamic-linker"
 "/lib64/ld-linux-x86-64.so.2"
 "-pie"
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/lib/x86_64-linux-gnu"
 "-L/lib/../lib"
 "-L/usr/lib/x86_64-linux-gnu"
 "-L/usr/lib/../lib"
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "/tmp/ccPVAv5P.o"
 "-lgcc"
 ...]
 0x1870900 /* 35 vars */ <unfinished ...>
execve("/usr/bin/ld"
 ["/usr/bin/ld"
 "-plugin"
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-plugin-opt=/usr/lib/gcc/x86_64-"...
 "-plugin-opt=-fresolution=/tmp/cc"...
 "-plugin-opt=-pass-through=-lgcc"
 "-plugin-opt=-pass-through=-lgcc_"...
 "-plugin-opt=-pass-through=-lc"
 "-plugin-opt=-pass-through=-lgcc"
 "-plugin-opt=-pass-through=-lgcc_"...
 "--build-id"
 "--eh-frame-hdr"
 "-m"
 "elf_x86_64"
 "--hash-style=gnu"
 "--as-needed"
 "-dynamic-linker"
 "/lib64/ld-linux-x86-64.so.2"
 "-pie"
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "/usr/lib/gcc/x86_64-linux-gnu/12"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "-L/lib/x86_64-linux-gnu"
 "-L/lib/../lib"
 "-L/usr/lib/x86_64-linux-gnu"
 "-L/usr/lib/../lib"
 "-L/usr/lib/gcc/x86_64-linux-gnu/"...
 "/tmp/ccPVAv5P.o"
 "-lgcc"
 ...]
 0x7ffe8c224bd0 /* 35 vars */ <unfinished ...>
View Code

 

可执行文件格式:ABIPE/COFF(Windows)、ELF(Linux)、MACH-O(Mac)

 

binutils:https://www.gnu.org/software/binutils

sudo apt -y install binutils

# 查看文件信息
readelf -a a.out
sudo apt -y install file && file a.out

# 查看数据段大小
size a.out

# 查看字符串
strings a.out

# 反编译
objdump -d a.out

# 删除调式符号
strip a.out

# 列出目标文件中的符号和地址
nm a.out
# 将地址转换为文件名和行号
addr2line -e a.out 0000000000001129

# 复制
objcopy -S --set-section-flags .bss=alloc,contents -O binary a.elf a.bin

 

参数

# 保存中间文件
-save-temps=obj

# 生成调试符号
-ggdb

 


https://gcc.gnu.org

https://www.gnu.org/software/gnu-c-manual

posted @ 2019-06-22 11:24  江湖小小白  阅读(806)  评论(0编辑  收藏  举报