iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
1
Security

逆向工程 – 從入門到放棄系列 第 12

Day12 - Hello world 的誕生 - 實戰篇

昨天我們討論到程式的編譯過程,今天就來將理論化為實際。透過手把手教學,我會使用 C 語言講解程式碼是如何一步步變成電腦能理解的語言。

首先,我們回顧這張圖:


Reference

不難發現,圖片中的流程:透過 gcc -E 進行預處理 -> gcc -S 進行編譯 -> gcc -c 進行組譯 -> ld 進行連結。
今天我們就是要重跑這個流程。 Start!

首先,開啟 terminal 將以下程式碼存到 helloworld.c 的程式

#include<stdio.h>

void main(){
    printf("Hello, world!\n");
}

預處理

首先,介紹使用的編譯軟體:GCC

根據 Wiki

GNU編譯器套裝(英語:GNU Compiler Collection,縮寫為GCC),指一套程式語言編譯器,以GPL及LGPL授權條款所發行的自由軟體,也是GNU計劃的關鍵部分,也是GNU工具鏈的主要組成部份之一。

接著在 terminal 中,下指令:

gcc -E helloworld.c

得到的結果如下:
(節錄部分程式碼),可以看到系統把 #include<stdio.h> 展開了

...
...
...
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 858 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 873 "/usr/include/stdio.h" 3 4

# 2 "helloworld.c" 2


# 3 "helloworld.c"
void main(){
 printf("Hello, world!\n");
}

編譯

在 terminal 中,下指令

gcc -S helloworld.c

得到的一個 helloworld.s

接著在 terminal 中,下指令,確認一下它的檔案形式

file helloworld.s

得到結果:

是一個組合語言檔
在 terminal 中,下指令,看看裡面長什麼樣子

cat helloworld.s

得到結果:
組合語言檔的分段:包括 .txt 、 .rodata

        .file   "helloworld.c"
        .text
        .section        .rodata
.LC0:
        .string "Hello, world!\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        leaq    .LC0(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        nop
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long    1f - 0f
        .long    4f - 1f
        .long    5
0:
        .string  "GNU"
1:
        .align 8
        .long    0xc0000002
        .long    3f - 2f
2:
        .long    0x3
3:
        .align 8
4:

組譯

在 terminal 中,下指令

gcc -c helloworld.s

得到的一個helloworld.o

接著在 terminal 中,下指令,確認一下它的檔案形式

file helloworld.o

是一個目的檔
在 terminal 中,下指令,看看裡面長什麼樣子

cat helloworld.o

得到結果:

連結

首先我們先編譯,再使用 ldd 看跟該程式有關的函式庫
在 terminal 中,下指令

gcc -o helloworld helloworld.c
ldd helloworld

可以看到 Helloworld 用到以下這些函式庫

載入

執行該程式,程式載入記憶體

./helloworld

結論

這就是 Helloworld 的誕生,明天接著說 Helloworld 被呼叫的時候,會經過哪些奇幻旅程


上一篇
Day11 - 如何生出 Hello world 小孩 - 理論篇
下一篇
Day13 - Hello world 的奇妙冒險
系列文
逆向工程 – 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言