--- 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未知的函數實體地址連接上 動態或靜態函式庫 和 ![](https://static.javatpoint.com/cpages/images/compilation-process-in-c3.png) ___ 做個實驗看看 === ```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)有很詳細的解說 ![](https://i.imgur.com/WshjXbc.png) 看完之後就知道 環境是要配置的~ 所以過程有...如圖(冏) 還有說到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`