不錯的資料

你在幹麻阿?

阿!我就只是想要簡單的看看 gcc hello.c 編譯中在幹麻而已

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

編譯組成部份:

為什麼用gcc hello.c指令打下去,一個elf的執行檔a.out就噗通的跑出來了?
研究了一下, 主要分成4個步驟:

  • Preprocessor
  • Compiler
  • Assembler
  • Linker

Preprocessor

預編譯 基本上就是擴張, 把macro, #include header都展開來

Compiler

轉成 組合語言 asambly

Assembler

轉成 機械碼 machine code, 很多1很多0的那種東西

Linker

把obj未知的函數實體地址連接上 動態或靜態函式庫

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


做個實驗看看

#include <stdio.h> int main(int argc, char *argv[]) { printf("hello Linux\n"); return 0; }

預編譯: 生成一個hello.i的intermedia中間檔案

拿我的hello.c來做實驗看看

$ 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'的組合語言檔案

$ gcc -S -o hello.s hello.i 
$ file hello.s
hello.s: assembler source, ASCII text

組合語言編譯器:生成一個'hello.obj'檔 不具有執行能力

$ 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 但是出現了一個奇怪的警告

  • 執行起來 會報錯
$ 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所出現的問題; 於是加上這些東西 就可以愉快的執行了

$ 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

下面有更多的補充 crt*是什麼東西? crt還有排列順序的呦

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

環境&執行流程

不知道為什麼就嘆了口氣

程式跑不跑得起來 還要看環境的呢?(仰望著天空)

在[你所不知道的 C 語言] 編譯器和最佳化原理篇有很詳細的解說

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

看完之後就知道 環境是要配置的~

所以過程有如圖(冏)

還有說到MSVC有不同的組態:單/多線程, 靜態/動態, 包含Dedug/釋出班本的 CRT

要了解更多的MSVC的看這個:MSVC與CRT的恩怨情仇

crt是什麼東西?

C runtime/執行階段程式庫
用來調用main函數 和 處理程序終止的代碼 和 佈置/劃分?函數

the misc libc/gcc crt files

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?

ld-linux.so是什麼東西?

32位 /lib/ld-linux.so.2
64位 /lib64/ld-linux-x86-64.so.2
動態加載器:功能是 尋找和加載 程式所需要的共享庫, 準備程序 運行程序

查看文件的指令

file: 查看檔案的類別(type)

$ 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: 列出符號表

$ 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 命令檢視他依賴庫

$ 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)

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)


Reference:

GCC and Make

編譯器和最佳化原理篇

在x86-64位機器上不用gcc直接ld:ld: warning: cannot find entry symbol _start; defaulting to 00000000004002c8

Bottomupcs

tags: Linux