---
title: 'gcc compiling'
---
[不錯的資料](https://ithelp.ithome.com.tw/articles/10257387)
[toc]
你在幹麻阿?
====
阿!我就只是想要簡單的看看 `gcc hello.c` 編譯中在幹麻而已 :face_with_head_bandage:
編譯組成部份:
===
為什麼用`gcc hello.c`指令打下去,一個elf的執行檔a.out就噗通的跑出來了?
研究了一下, 主要分成4個步驟:
- **Preprocessor**
- **Compiler**
- **Assembler**
- **Linker**
### Preprocessor
預編譯 基本上就是擴張, 把macro, #include header都展開來
### Compiler
轉成 組合語言 asambly
### Assembler
轉成 機械碼 machine code, 很多1很多0的那種東西
### Linker
把obj未知的函數實體地址連接上 動態或靜態函式庫
和

___
做個實驗看看
===
```c=
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello Linux\n");
return 0;
}
```
### 預編譯: 生成一個`hello.i`的intermedia中間檔案
拿我的hello.c來做實驗看看
```bash
$ cpp -o hello.i hello.c
$ file hello.i
hello.i: C source, ASCII text
```
> cpp是gcc中的預編譯器組件
> 也可以用gcc來調用: gcc -E -P hello.c -o hello.i
> -E 只做預編譯
> -P 不生成行號
### 編譯: 生成一個'hello.s'的組合語言檔案
```bash
$ gcc -S -o hello.s hello.i
$ file hello.s
hello.s: assembler source, ASCII text
```
### 組合語言編譯器:生成一個'hello.obj'檔 不具有執行能力
```bash
$ as -o hello.obj hello.s
$ file hello.obj
hello.obj: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
```
### 連結器: 生成了一個a.out 但是出現了一個奇怪的警告
* 執行起來 會報錯
```bash
$ ld hello.obj -lc
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020
$ ./a.out
bash: ./a.out: No such file or directory
```
### 解決ld的錯誤
經過了一番閱讀 是關於c runtime所出現的問題; 於是加上這些東西 就可以愉快的執行了
```bash
$ ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 hello.obj /usr/lib64/Scrt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/crtbeginS.o -lc /usr/lib64/gcc/x86_64-pc-linux-gnu/11.1.0/crtendS.o /usr/lib64/crtn.o
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 4.4.0, not stripped
$ ./a.out
Hello linux
```
:::info
下面有更多的補充 **crt*是什麼東西?** [crt還有排列順序的呦](http://dev.gentoo.org/~vapier/crt.txt) :smiley:
:::
環境&執行流程
=====================================================
不知道為什麼就嘆了口氣... 冏
程式跑不跑得起來 還要看環境的呢?(仰望著天空)
在[你所不知道的 C 語言] [編譯器和最佳化原理篇](https://hackmd.io/@sysprog/c-prog/%2Fs%2FHy72937Me)有很詳細的解說

看完之後就知道 環境是要配置的~
所以過程有...如圖(冏)
還有說到MSVC有不同的組態:單/多線程, 靜態/動態, 包含Dedug/釋出班本的 CRT
要了解更多的MSVC的看這個:[MSVC與CRT的恩怨情仇](https://www.cnblogs.com/shijingjing07/p/5509640.html)
### crt是什麼東西?
C runtime/執行階段程式庫
用來調用`main`函數 和 處理程序終止的代碼 和 佈置/劃分?函數
[**the misc libc/gcc crt files**](http://dev.gentoo.org/~vapier/crt.txt)
:::info
The crt files contain the runtime - that's the code that calls your `main` function, handles program termination, and some instructions on how to lay out functions.
Ref: [What is the role of crt* files in linking?](https://stackoverflow.com/questions/7776821/what-is-the-role-of-crt-files-in-linking)
:::
### ld-linux.so是什麼東西?
32位 /lib/ld-linux.so.2
64位 /lib64/ld-linux-x86-64._so_.2
動態加載器:功能是 尋找和加載 程式所需要的共享庫, 準備程序 運行程序
查看文件的指令
=========================================
**file**: 查看檔案的類別(type)
```bash
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 4.4.0, not stripped
```
**nm**: 列出符號表
```bash
$ nm a.out
0000000000400340 r __abi_tag
0000000000404030 B __bss_start
0000000000404030 b completed.0
w __cxa_finalize@GLIBC_2.2.5
0000000000404020 D __data_start
0000000000404020 W data_start
00000000004010a0 t deregister_tm_clones
0000000000401110 t __do_global_dtors_aux
0000000000403df0 d __do_global_dtors_aux_fini_array_entry
0000000000404028 D __dso_handle
0000000000403df8 d _DYNAMIC
0000000000404030 D _edata
0000000000404038 B _end
00000000004011e8 T _fini
0000000000401160 t frame_dummy
0000000000403de8 d __frame_dummy_init_array_entry
00000000004020e4 r __FRAME_END__
0000000000404000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000401000 T _init
0000000000403df0 d __init_array_end
0000000000403de8 d __init_array_start
000000000040200c R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000004011e0 T __libc_csu_fini
0000000000401170 T __libc_csu_init
U __libc_start_main@GLIBC_2.2.5
0000000000401040 T main
U puts@GLIBC_2.2.5
00000000004010d0 t register_tm_clones
0000000000401070 T _start
0000000000404030 D __TMC_END__
```
**ldd** 命令檢視他依賴庫
```bash
$ ldd a.out
linux-vdso.so.1 (0x00007ffc5f1bc000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fb7614bb000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fb7616ac000)
```
:::info
The programs **ld.so** and **ld-linux.so*** find and load the shared libraries needed by a program, prepare the program to run, and then run it.
Ref: [man ld-linux.so(8)](https://linux.die.net/man/8/ld-linux.so)
:::
----------------------------------------------------
Reference:
[GCC and Make](https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html#zz-1.10)
[編譯器和最佳化原理篇](https://hackmd.io/s/Hy72937Me)
[在x86-64位機器上不用gcc直接ld:ld: warning: cannot find entry symbol _start; defaulting to 00000000004002c8
](https://www.twblogs.net/a/5b8874712b71775d1cdc8107)
[Bottomupcs](https://www.bottomupcs.com/)
###### tags: `Linux`