| 1.2.6 核心映像連結檔
從 vmlinux 的生成描述,得知要生成 vmlinux 必須先取得 vmlinux-lds。
vmlinux-lds 的介入時機是執行規則 rule_vmlinux__ 的 cmd_vmlinux__ 的時候。
cmd_vmlinux__ 使用 vmlinux-lds 連結 $(vmlinux-init)、$(vmlinux-main)、以及 vmlinux.o 中不包含 vmlinux-init、vmlinux-main、vmlinux-lds 的區段資料,生成 vmlinux。
此時所生成的 vmlinux 就是一個 ELF 格式的可執行檔,執行檔的入口點由 vmlinux-lds 定義。
核心映像連結檔 vmlinux-lds 是 vmlinux 的連結描述檔,檔案位置是 linux/arch/x86/kernel/vmlinux.lds。
| 行號 | 說明 |
| 01 | 設定輸出檔的格式,第一參數是內定格式,第二參數是 big endian 格式,第三參數是 little endian 格式,而他們都是 elf32-i386。 |
| 02 | 設定機器架構為 I386。 |
| 03 | 設定輸出檔的入口點為 phys_startup_32,入口點是第一個被執行的指令所在的位址。沒有指定入口點時,會使用標籤 start 或位址 0 代替。 |
| 行號 | 說明 |
| 02 | 設定程式表 PROGRAM TABLE,共有三個程式表 text、data、note。 |
| 02 | 程式 text,FLAGS(5) 表示此程式檔頭的 p_type 為 PT_SHLIB。定義在 elf_format.pdf,表示不確定的內容??。 |
| 03 | 程式 data,FLAGS(6) 表示此 program header 的 p_type 為 PT_PHDR。定義在 elf_format.pdf,表示是 PHDRS 自己的體積??。 |
| 04 | 程式 note,FLAGS(6) 表示此 program header 的 p_type 為 PT_NULL。定義在 elf_format.pdf,表示可以忽略而不載入。 |
| 行號 | 說明 |
| 01 | 宣告區段,SECTIONS 定義在 ELF_FORMAT.PDF P36。 |
| 03 | 這個算式的結果是 0xC1000000。0xC0000000 表示這個 ELF 可執行檔是執行於虛擬記憶體 3GB~4GB 之間,也就是說核心可用的記憶體空間小於 1GB。 |
| 04 | startup_32 是從 0xC0000000 開始算起,而我們要的是從 0 算起的位址偏移值 phys_startup_32。
phys_startup_32 會編入 setup.bin 的 hdr code32_start 欄位 ? 不會填入,會直接設定為 0x100000。至於為什麼有 0x100000 空出來 的原因是為了 kernel crash 時的 kernel recovery 程式使用。 |
| 05 | 宣告程式區域 text,其位址開始於 ADDR(.text) - 0xC0000000,.text 原本是一個從 0xC0000000 開始算起的程式位址。ADDR(.text)表示取 .text 的虛擬記憶體位址(VMA)。 |
| 06 | PROGRAM .head.text 宣告在 linux/include/linux/init.h,所有以 __HEAD 宣告的組合語言函式都會放在這個程式段落。 |
| 07 | 對齊 4KB 的邊界,這可能是有助於頁配置或頁釋放。 |
| 08 | 這部分筆者尚不解,應該是放 .text..page_aligned 的資料。 |
| 09 | 對齊八位元組的邊界,這可能是有助於頁配置或頁釋放。 |
| 10 | 宣告連結變數 _stext,表示這是此段區域的起始點。 |
| 11 | 先對齊八位元組,再將程式群放到此區域,包括 PROGRAM .text.hot、.text、.ref.text、.devinit.text、.devexit.text、.cpuinit.text、.cpuexit.text、.text.unlikely。 |
| 12 | 先對齊八位元組,再將程式群放到此區域,包括 PROGRAM .sched.text。 |
| 13 | 先對齊八位元組,再將程式群放到此區域,包括 PROGRAM .spinlock.text。 |
| 14 | 先對齊八位元組,再將程式群放到此區域,包括 PROGRAM .kprobes.text。 |
| 15 | 先對齊八位元組,再將程式群放到此區域,包括 PROGRAM .entry.text。 |
| 16 | 將程式 .fixup 的內容放在此。 |
| 17 | 將程式 .gnu.warning 的內容放在此。 |
| 18 | 宣告連結變數 _etext,表示這是此程式區域的結束點。 |
| 19 | 程式區域 text 結束,把區域內的空白的空間填入0x9090。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .notes,其位址開始於 ADDR(.notes) - 0xC0000000,.notes 原本是一個從 0xC0000000 開始算起的程式位址。ADDR(.notes)表示取 .notes 的虛擬記憶體位址(VMA)。 |
| 02 | 對齊十六位元組的記憶體邊界。 |
| 03 | 宣告程式區域 __ex_table,其位址開始於 ADDR(__ex_table) - 0xC0000000,__ex_table 原本是一個從 0xC0000000 開始算起的程式位址。ADDR(__ex_table)表示取 .notes 的虛擬記憶體位址(VMA)。 |
| 04 | 對齊 4KB 的邊界,這可能是有助於頁配置或頁釋放。 |
| 行號 | 說明 |
| 01 | 對齊 4KB 的邊界,這可能是有助於頁配置或頁釋放。 |
| 02 | 宣告程式區域 .rodata,其位址開始於 ADDR(.rodata) - 0xC0000000,.rodata 原本是一個從 0xC0000000 開始算起的程式位址。ADDR(.rodata)表示取 .notes 的虛擬記憶體位址(VMA)。 |
| 03 | 放入三個 PROGRAM 的內容,包括.rodata、.rodata.*、__vermagic。 |
| 04 | 對齊八位元組的邊界。 |
| 05 | 放入 PROGRAM __tracepoints_ptrs 的內容。 |
| 06 | 接著再放入 PROGRAM __markers_strings、__tracepoints_strings 的內容。 |
| 行號 | 說明 |
| 02 | 宣告程式區域 .rodata1,並放入 PROGRAM .rodata1 的內容。 |
| 04 | 對齊八位元組的邊界。 |
| 02 | 宣告程式區域 __bug_table,並放入 PROGRAM __bug_table 的內容。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .pci_fixup,此區域將包含下列的程式內容。 |
| 02 | 放入PROGRAM .pci_fixup_early。 |
| 03 | 放入PROGRAM .pci_fixup_header。 |
| 04 | 放入PROGRAM .pci_fixup_final。 |
| 05 | 放入PROGRAM .pci_fixup_enable。 |
| 06 | 放入PROGRAM .pci_fixup_resume。 |
| 07 | 放入PROGRAM .pci_fixup_resume_early。 |
| 08 | 放入PROGRAM .pci_fixup_suspend。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .builtin_fw,包含 PROGRAM .builtin_fw。 |
| 01 | 宣告程式區域 .rio_ops,包含 PROGRAM .rio_switch_ops。 |
| 行號 | 說明 |
| 01 | 對齊四位元組的邊界。 |
| 02~03 | 宣告程式區域 .tracedata,包含 PROGRAM .tracedata 。 |
| 04~05 | 宣告程式區域 __ksymtab,包含 PROGRAM SORT(___ksymtab+*)。 |
| 06~07 | 宣告程式區域 __ksymtab_gpl,包含 PROGRAM SORT(___ksymtab_gpl+*)。 |
| 08~09 | 宣告程式區域 __ksymtab_unused,包含 PROGRAM SORT(___ksymtab_unused+*)。 |
| 10~11 | 宣告程式區域 __ksymtab_unused_gpl,包含 PROGRAM SORT(___ksymtab_unused_gpl+*)。 |
| 12~13 | 宣告程式區域 __ksymtab_gpl_future,包含 PROGRAM SORT(___ksymtab_gpl_future+*) 。 |
| 14~15 | 宣告程式區域 __kcrctab,包含 PROGRAM SORT(___kcrctab+*)。 |
| 16~17 | 宣告程式區域 __kcrctab_gpl,包含 PROGRAM SORT(___kcrctab_gpl+*) 。 |
| 18~19 | 宣告程式區域 __kcrctab_unused,包含 PROGRAM SORT(___kcrctab_unused+*) 。 |
| 20~21 | 宣告程式區域 __kcrctab_unused_gpl,包含 PROGRAM SORT(___kcrctab_unused_gpl+*) 。 |
| 22~23 | 宣告程式區域 __kcrctab_gpl_future,包含 PROGRAM .tracedata 。 |
| 24~25 | 宣告程式區域 __ksymtab_strings,包含 PROGRAM SORT(___kcrctab_gpl_future+*) 。 |
| 25~26 | 宣告程式區域 __init_rodata,包含 PROGRAM .ref.rodata、.devinit.rodata、.devexit.rodata、.cpuinit.rodata、.cpuexit.rodata。 |
| 27 | 宣告程式區域 __param,包含 PROGRAM __param 。 |
| 28 | 宣告程式區域 __modver,包含 PROGRAM __modver 。 |
| 29 | 對齊 4KB 的記憶體邊界。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .data,包含 PROGRAM .tracedata 。 |
| 02 | 宣告連結變數 _sdata,表示這是 .data 開始點,沒有用處。 |
| 03 | 對齊 8KB 的記憶體邊界,放入 PROGRAM .data..init_task。 |
| 04 | 對齊 4KB 的記憶體邊界,放入 PROGRAM .data..nosave。之後再對齊 4KB 的記憶體邊界。 |
| 05 | 對齊 4KB 的記憶體邊界,放入 PROGRAM .data..page_aligned。 |
| 06~7 | 對齊 64 位元組的記憶體邊界,放入 PROGRAM .data..cacheline_aligned、.data、.ref.data、.data..shared_aligned、.devinit.data、.devexit.data、.cpuinit.data、.cpuexit.data。 |
| 08 | 對齊 32 的記憶體邊界,放入 PROGRAM __tracepoints。 |
| 09 | 對齊八的記憶體邊界,並放入 PROGRAM __jump_table。 |
| 10~11 | 對齊八的記憶體邊界,並放入 PROGRAM __verbose、__trace_printk_fmt。 |
| 12 | 建構子群命令,用來放置 C++ 的建構子和除構子資訊。 |
| 13 | 對齊 64 位元組的記憶體邊界,放入 PROGRAM .data..read_mostly。最後再對齊 64 位元組的記憶體邊界。 |
| 14 | 宣告連結變數 _edata,表示這是 .data 結束點,沒有用處。 |
| 15 | 程式區域 .data 的結束點。開始於 .data ,結束於 :data。 |
| 行號 | 說明 |
| 01 | 對齊 4KB 的記憶體邊界。 |
| 02 | 宣告程式區域 .init.begin 和連結變數 __init_begin。之後會有 __init_end 作為對映的結束點。 |
| 行號 | 說明 |
| 01 | 對齊 4KB 的記憶體邊界。 |
| 02 | 宣告程式區域 .init.text,包含 PROGRAM .init.text、.meminit.text。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .init.data。 |
| 02 | 放入 PROGRAM .init.data、.meminit.data、.init.rodata。 |
| 03 | 對齊八位元組的記憶體邊界。 |
| 04 | 放入 PROGRAM _ftrace_events。 |
| 05 | 放入 PROGRAM .meminit.rodata。 |
| 06 | 對齊32位元組的記憶體邊界,放入 PROGRAM .dtb.init.rodata。 |
| 07 | 對齊16位元組的記憶體邊界,放入 PROGRAM .init.setup。 |
| 08 | 放入 PROGRAM .initcallearly.init。 |
| 09~13 | 放入 PROGRAM .initcall0.init、.initcall0s.init、.initcall0.init、.initcall0s.init、.initcall1.init、.initcall1s.init)、
.initcall2.init、.initcall2s.init、.initcall3.init、.initcall3s.init)、.initcall4.init、.initcall4s.init、.initcall5.init、.initcall5s.init)、
.initcallrootfs.init、.initcall6.init、.initcall6s.init、.initcall7.init、.initcall7s.init。
| | 14 | 放入 PROGRAM .con_initcall.init。 |
| 15 | 放入 PROGRAM .security_initcall.init。 |
| 16 | 對齊四位元組的記憶體邊界,放入 PROGRAM .init.ramfs。 |
| 17 | 對齊八位元組的記憶體邊界,放入 PROGRAM .init.ramfs.info。 |
| 行號 | 說明 |
| 01~03 | 宣告程式區域 .x86_trampoline,放入 PROGRAM .x86_trampoline。 |
| 04~06 | 宣告程式區域 .x86_cpu_dev.init,放入 PROGRAM .x86_cpu_dev.init。 |
| 07~10 | 對齊八位元組的記憶體邊界。宣告程式區域 .parainstructions,放入 PROGRAM .parainstructions。 |
| 11~14 | 對齊八位元組的記憶體邊界。宣告程式區域 .altinstructions,放入 PROGRAM .altinstructions。 |
| 15~17 | 宣告程式區域 .altinstr_replacement,放入 PROGRAM .altinstr_replacement。 |
| 18~20 | 宣告程式區域 .iommu_table,放入 PROGRAM .iommu_table。 |
| 行號 | 說明 |
| 01~04 | 對齊八位元組的記憶體邊界。宣告程式區域 .apicdrivers,放入 PROGRAM .apicdrivers。 |
| 05~08 | 對齊八位元組的記憶體邊界。宣告程式區域 .exit.text,放入 PROGRAM .exit.text、.memexit.text。 |
| 09~11 | 宣告程式區域 .exit.data,放入 PROGRAM .exit.data、.memexit.data、.memexit.rodata。 |
| 12 | 對齊 4KB 的記憶體邊界。 |
| 行號 | 說明 |
| 01 | 宣告程式區域 .data..percpu。 |
| 02 | 放入 PROGRAM .data..percpu..first。 |
| 03 | 對齊 4KB 的記憶體邊界。放入 PROGRAM .data..percpu..first。 |
| 04 | 對齊 64 位元組的記憶體邊界。放入 PROGRAM .data..percpu..readmostly。 |
| 05 | 對齊 64 位元組的記憶體邊界。放入 PROGRAM .data..percpu、.data..percpu..shared_aligned。 |
| 06 | 對齊 4KB 的記憶體邊界。 |
| 07 | 宣告程式區域 .init.end。對映於前面的 .init.begin,將二者中間的所有程式區域包裝起來。 |
| 行號 | 說明 |
| 01 | 對齊 4KB 的記憶體邊界。 |
| 02~04 | 宣告程式區域 .smp_locks。放入 PROGRAM .smp_locks。結尾對齊 4KB 的記憶體邊界。 |
| 05 | 對齊 4KB 的記憶體邊界。 |
| 06~08 | 宣告程式區域 .bss。放入 PROGRAM .bss..page_aligned、.bss。結尾對齊 4KB 的記憶體邊界。 |
| 09 | 對齊 4KB 的記憶體邊界。 |
| 10~15 | 宣告程式區域 .brk。將程式區域往後延伸 64KB,再放入 .brk_reservation,並標記為 __brk_limit。 |
| 行號 | 說明 |
| 01 | 標記此處為 _end。 |
| 02 | 放入 PROGRAM .stab、.stabstr、.stab.excl。 |
| 03 | 放入 PROGRAM .stab.exclstr、.stab.index。 |
| 04 | 放入 PROGRAM .stab.indexstr、.comment。 |
| 05 | 放入 PROGRAM .debug、.line、.debug_srcinfo。 |
| 06 | 放入 PROGRAM .debug_sfnames、.debug_aranges。 |
| 07 | 放入 PROGRAM .debug_pubnames、.debug_info、.gnu.linkonce.wi.*。 |
| 08 | 放入 PROGRAM .debug_abbrev、.debug_line。 |
| 09 | 放入 PROGRAM .debug_frame、.debug_str。 |
| 10 | 放入 PROGRAM .debug_loc、.debug_macinfo。 |
| 11 | 放入 PROGRAM .debug_weaknames、.debug_funcnames。 |
| 12 | 放入 PROGRAM .debug_typenames、.debug_varnames。 |
| 13 | DISCARD 表示要丟棄區段,定義在 ld.pdf 3.6.7 。要丟棄區段包括 PROGRAM .exit.text、.memexit.text、.exit.data、.memexit.data、.memexit.rodata、.exitcall.exit、.discard、.discard.、.eh_frame。 |
| 12 | 這個右大括號對映於 SECTIONS 的左大括號。 |
| 行號 | 說明 |
| 01~02 | ASSERT 的敘述中,第一個參數是條件式,第二個參數是條件不成立時要顯示的訊息。當整個映像位址範圍大於 500MB,表示映像太大,顯示錯誤訊息。 |
| 03~04 | 。當kexec_control_code_size大於 2048,表示 kexec 的體積太大,顯示錯誤訊息。 |
|