Gcc Compile C Prog
Gcc Compile C Prog
April 29, 2025
分析代码
os: Linux Mint 22.1
hello.c
#include <stdio.h>
int main(void){
printf("hello world");
}strace 追踪编译流程
strace -t -f -o hello.log -e trace=execve -s 2000 gcc -o hello hello.cAll execve() system calls during compilation, showing how GCC orchestrates the build process.
hello.log 内容
20029 13:48:52 execve("/usr/bin/gcc", ["gcc", "-o", "hello", "hello.c"], 0x7ffd60d08358 /* 65 vars */) = 0
20034 13:48:52 execve("/usr/libexec/gcc/x86_64-linux-gnu/13/cc1", ["/usr/libexec/gcc/x86_64-linux-gnu/13/cc1", "-quiet", "-imultiarch", "x86_64-linux-gnu", "hello.c", "-quiet", "-dumpbase", "hello.c", "-dumpbase-ext", ".c", "-mtune=generic", "-march=x86-64", "-fasynchronous-unwind-tables", "-fstack-protector-strong", "-Wformat", "-Wformat-security", "-fstack-clash-protection", "-fcf-protection", "-o", "/tmp/ccLfEVyN.s"], 0x7d14db0 /* 70 vars */) = 0
20034 13:48:53 +++ exited with 0 +++
20029 13:48:53 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20034, si_uid=1000, si_status=0, si_utime=3 /* 0.03 s */, si_stime=17 /* 0.17 s */} ---
20036 13:48:53 execve("/usr/local/sbin/as", ["as", "--64", "-o", "/tmp/ccGZrdFz.o", "/tmp/ccLfEVyN.s"], 0x7d14db0 /* 70 vars */) = -1 ENOENT (No such file or directory)
20036 13:48:53 execve("/usr/local/bin/as", ["as", "--64", "-o", "/tmp/ccGZrdFz.o", "/tmp/ccLfEVyN.s"], 0x7d14db0 /* 70 vars */) = -1 ENOENT (No such file or directory)
20036 13:48:53 execve("/usr/sbin/as", ["as", "--64", "-o", "/tmp/ccGZrdFz.o", "/tmp/ccLfEVyN.s"], 0x7d14db0 /* 70 vars */) = -1 ENOENT (No such file or directory)
20036 13:48:53 execve("/usr/bin/as", ["as", "--64", "-o", "/tmp/ccGZrdFz.o", "/tmp/ccLfEVyN.s"], 0x7d14db0 /* 70 vars */) = 0
20036 13:48:53 +++ exited with 0 +++
20029 13:48:53 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20036, si_uid=1000, si_status=0, si_utime=0, si_stime=1 /* 0.01 s */} ---
20037 13:48:53 execve("/usr/libexec/gcc/x86_64-linux-gnu/13/collect2", ["/usr/libexec/gcc/x86_64-linux-gnu/13/collect2", "-plugin", "/usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so", "-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper", "-plugin-opt=-fresolution=/tmp/ccKbYYb2.res", "-plugin-opt=-pass-through=-lgcc", "-plugin-opt=-pass-through=-lgcc_s", "-plugin-opt=-pass-through=-lc", "-plugin-opt=-pass-through=-lgcc", "-plugin-opt=-pass-through=-lgcc_s", "--build-id", "--eh-frame-hdr", "-m", "elf_x86_64", "--hash-style=gnu", "--as-needed", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", "-pie", "-z", "now", "-z", "relro", "-o", "hello", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o", "/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o", "-L/usr/lib/gcc/x86_64-linux-gnu/13", "-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu", "-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib", "-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/13/../../..", "/tmp/ccGZrdFz.o", "-lgcc", "--push-state", "--as-needed", "-lgcc_s", "--pop-state", "-lc", "-lgcc", "--push-state", "--as-needed", "-lgcc_s", "--pop-state", "/usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o"], 0x7d15df0 /* 72 vars */) = 0
20038 13:48:53 execve("/usr/bin/ld", ["/usr/bin/ld", "-plugin", "/usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so", "-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper", "-plugin-opt=-fresolution=/tmp/ccKbYYb2.res", "-plugin-opt=-pass-through=-lgcc", "-plugin-opt=-pass-through=-lgcc_s", "-plugin-opt=-pass-through=-lc", "-plugin-opt=-pass-through=-lgcc", "-plugin-opt=-pass-through=-lgcc_s", "--build-id", "--eh-frame-hdr", "-m", "elf_x86_64", "--hash-style=gnu", "--as-needed", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", "-pie", "-z", "now", "-z", "relro", "-o", "hello", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o", "/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o", "-L/usr/lib/gcc/x86_64-linux-gnu/13", "-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu", "-L/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib", "-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/13/../../..", "/tmp/ccGZrdFz.o", "-lgcc", "--push-state", "--as-needed", "-lgcc_s", "--pop-state", "-lc", "-lgcc", "--push-state", "--as-needed", "-lgcc_s", "--pop-state", "/usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o", "/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o"], 0x7ffd0bf6c850 /* 72 vars */) = 0
20038 13:48:54 +++ exited with 0 +++
20037 13:48:54 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20038, si_uid=1000, si_status=0, si_utime=4 /* 0.04 s */, si_stime=23 /* 0.23 s */} ---
20037 13:48:54 +++ exited with 0 +++
20029 13:48:54 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20037, si_uid=1000, si_status=0, si_utime=0, si_stime=3 /* 0.03 s */} ---
20029 13:48:54 +++ exited with 0 +++编译流程分析
Initial GCC Invocation
execve("/usr/bin/gcc", ["gcc", "-o", "hello", "hello.c"], ...)- Process ID:
20029 - Action: Invokes the GCC driver (
/usr/bin/gcc).
Compilation Phase
execve("/usr/libexec/gcc/x86_64-linux-gnu/13/cc1", ["/usr/libexec/gcc/x86_64-linux-gnu/13/cc1", ...], ...)- Process ID:
20034 - Role:
cc1is the GCC C compiler frontend.- Converts
hello.cto assembly code (/tmp/ccLfEVyN.s).
- Flags Passed:
Includes optimization settings (e.g.,-mtune=generic,-march=x86-64), security features (-fstack-protector-strong,-Wformat-security), and others.
Result:
Assembly file generated at /tmp/ccLfEVyN.s.
Assembly Phase
Attempts to locate the assembler (as):
execve("/usr/local/sbin/as", ...) = -1 ENOENT
execve("/usr/local/bin/as", ...) = -1 ENOENT
execve("/usr/sbin/as", ...) = -1 ENOENT
execve("/usr/bin/as", ...) = 0- Process ID:
20036 - Why Multiple Tries?:
GCC searches standard paths for the assembler. Succeeds with/usr/bin/as(GNU Assembler). - Action:
Assembles/tmp/ccLfEVyN.sinto an object file:/tmp/ccGZrdFz.o.
Linking Phase
execve("/usr/libexec/gcc/x86_64-linux-gnu/13/collect2", [...], ...)- Process ID:
20037 - Role:
- Wrapper for the linker (
ld). - Prepares metadata for C++ static constructors/destructors (not needed here since
hello.cis plain C). - Invokes the real linker (
/usr/bin/ld).
- Wrapper for the linker (
Internal Linker Call:
execve("/usr/bin/ld", [...], ...)- Process ID:
20038 - Key Flags:
-dynamic-linker /lib64/ld-linux-x86-64.so.2: Sets the dynamic loader.-pie: Creates a Position-Independent Executable (security feature).-z nowand-z relro: Enhance runtime security.
- Inputs Linked:
- CRT (C Runtime) files (
Scrt1.o,crti.o,crtbeginS.o,crtendS.o,crtn.o). - Object file:
/tmp/ccGZrdFz.o. - Standard libraries:
-lgcc,-lgcc_s,-lc(libc).
- CRT (C Runtime) files (
Result:
Final executable hello is created.
Success Indicators
- All
execve()calls return0(success). - Processes exit cleanly (
+++ exited with 0 +++). - No errors detected in the toolchain path or linking.
Security & Optimization Notes
- Stack Protection: Enabled via
-fstack-protector-strong. - Hardened Linking:
-z now: Immediate binding of symbols.-z relro: Read-only relocations after relocation.-pie: ASLR-friendly executable.
- Build ID: Embedded via
--build-idfor debugging/tracing.
Critical Paths
| Tool | Path | Purpose |
|---|---|---|
cc1 | /usr/libexec/gcc/x86_64-linux-gnu/13/cc1 | Compiles C to assembly |
as | /usr/bin/as | Assembles .s to .o |
collect2 | /usr/libexec/gcc/x86_64-linux-gnu/13/collect2 | Manages linker setup |
ld | /usr/bin/ld | Links objects into final binary |
Conclusion
The log confirms a standard GCC compilation pipeline:
- Preprocessing + Parsing: Handled by
cc1. - Assembly: Done by
as. - Linking: Orchestrated by
collect2→ld.
Last updated on