1. 程式人生 > >《Linux核心原理與分析》第八週作業

《Linux核心原理與分析》第八週作業

課本:第七章 可執行程式工作原理

  • ELF目標檔案格式
    • 目標檔案:編譯器生成的檔案。
    • 目標檔案的格式:out格式、COFF格式、PE(windows)格式、ELF(Linux)格式。
    • ELF(Executable and Linkable Format)即可執行和可連結的格式,是一個目標檔案格式的標準。ELF格式的檔案用於儲存Linux程式。
    • ELF檔案的3鍾型別:可重定位檔案、可執行檔案、共享目標檔案。
      • 可重定位檔案:這種一般是中間檔案,還需要繼續處理。由彙編器和編譯器建立,一個原始碼檔案會生成一個可重定位檔案。檔案中儲存著程式碼和適當的資料,用來和其他的目標檔案一起來建立一個可執行檔案、靜態庫檔案或者共享目標檔案(即動態庫檔案)。如Linux下.c檔案都會生成一個同名的.o檔案,這就是可重定位目標檔案。
      • 可執行檔案:一般由多個可重定位檔案結合生成,是完成了所有重定位工作和符號解析(除了執行時解析的共享庫符號)的檔案,檔案中儲存著一個用來執行的程式。
      • 共享目標檔案:共享庫,是指可以被可執行檔案或其他庫檔案使用的目標檔案,例如標準C的庫檔案libc.so。可以簡單理解為沒有主函式main的“可執行”檔案,只有一堆函式可供其他可執行檔案呼叫。Linux下共享庫字尾為.so檔案,代表shard object。
    • ELF檔案作用:ELF檔案參與程式的連結和程式的執行。
      • 如果用於編譯和連結(可重定位檔案),編譯器和連結器將把ELF檔案看作節的集合,所有節由節頭表描述,程式頭表可選。
      • 如果用於載入執行(可執行檔案),載入器將把ELF檔案看作程式頭表描述的段的集合,一個段可能包含多個節和節頭表可選。
      • 如果是共享檔案,則兩者都含有。
    • ELF格式
      • 主體是各種節,還有描述這些節屬性的資訊(Program header table和Section header table),以及ELF檔案的整體描述資訊(ELF header)。整體如下圖所示:
      • ELF Header
      • Section Header
      • Program Header
    • 對ELF進行研究的相關操作指令
      • man elf:詳細格式定義。
      • readelf:用於顯示一個或多個elf格式的目標檔案的資訊,後面可以使用多個引數,如-a、-h、-S、-l等。
      • objdump:顯示二進位制檔案資訊,有-f、-h、-r等一系列引數。
      • hexdump:用十六進位制的數字來顯示elf的內容。
  • 程式編譯
    • 預處理:gcc -E hello.c -o hello.i
    • 編譯:gcc -S hello.i -o hello.s -m32
    • 彙編:gcc -c hello.s -o hello.o -m32
    • 連結:gcc hello.o -o hello -m32 -static
  • 連結與庫
    • 連結
      • 從過程上講:符號解析、重定位。
      • 根據連結時機:靜態連結、動態連結。
  • 程式裝載
    • exec函式:sys_execve()系統呼叫
    • 呼叫關係:sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()
    • fork與execve的區別和聯絡
      • 都是比較特殊的系統呼叫
      • fork在陷入核心態後有兩次返回,第一次返回到原來父程序的位置繼續向下執行,第二次是在子程序返回,這次會返回到ret_from_fork,之後正常返回使用者態。
      • execve在執行時陷入核心態,在核心中呼叫execve載入的可執行檔案把當前程序的可執行程式給覆蓋了,當其返回時,返回的已經不是原來的那個可執行程式了,而是新的程式,返回的是新的可執行程式執行的起點,即main函式的大致位置(一般地址為0x8048xxx,由編譯器設定)
  • 核心支援多格式是在執行execve時,它載入了檔案的頭部,來判斷檔案是什麼格式,在連結串列中尋找能夠解析這種檔案格式的核心模組
  • 兩種載入方法
    • 靜態庫:直接執行可執行程式的入口
    • 動態庫:由ld來動態連結這個程式,再把控制權移交給可執行程式的入口

      實驗:Linux核心如何裝載和啟動一個可執行程式

      問題與總結