從 vmlinux.bin(嵌入式 initramfs)重新打封包件系統映像而不重建?
在如何從 vmlinux.bin 中提取文件系統映像?和https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging方法用於獲取和解壓包含在核心映像中的嵌入式 initramfs/initrd。
現在我想將修改後的文件系統(
cpio
+ 可能使用 eg 打包lzma
)插入核心執行檔,而無需重新編譯它。這種方式可以修改核心的ELF鏡像嗎?如果是,那怎麼辦?如果我只是在原地替換字節(也許是一些雜湊?),我是否需要保留一些尊重?
objdump-h
輸出:vmlinux.64.orig: file format elf64-big Sections: Idx Name Size VMA LMA File off Algn 0 .text 004162b8 ffffffff80100000 ffffffff80100000 00010000 2**7 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 __ex_table 000063a0 ffffffff805162c0 ffffffff805162c0 004262c0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .notes 00000024 ffffffff8051c660 ffffffff8051c660 0042c660 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .rodata 0041f700 ffffffff8051d000 ffffffff8051d000 0042d000 2**8 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .pci_fixup 00000d40 ffffffff8093c700 ffffffff8093c700 0084c700 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 __ksymtab 0000a430 ffffffff8093d440 ffffffff8093d440 0084d440 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 __ksymtab_gpl 00004ff0 ffffffff80947870 ffffffff80947870 00857870 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 __ksymtab_strings 00010f14 ffffffff8094c860 ffffffff8094c860 0085c860 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 __init_rodata 00000500 ffffffff8095d778 ffffffff8095d778 0086d778 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 __param 00001388 ffffffff8095dc78 ffffffff8095dc78 0086dc78 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 .data 000508c0 ffffffff80960000 ffffffff80960000 00870000 2**14 CONTENTS, ALLOC, LOAD, DATA 11 .init.text 0002b084 ffffffff809b1000 ffffffff809b1000 008c1000 2**5 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .init.data 00bc6d78 ffffffff809dc088 ffffffff809dc088 008ec088 2**3 CONTENTS, ALLOC, LOAD, DATA 13 .exit.text 000019e0 ffffffff815a2e00 ffffffff815a2e00 014b2e00 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 14 .data.percpu 00003680 ffffffff815a5000 ffffffff815a5000 014b5000 2**7 CONTENTS, ALLOC, LOAD, DATA 15 .bss 00068fb0 ffffffff815b0000 ffffffff815b0000 014b8680 2**16 ALLOC 16 .mdebug.abi64 00000000 ffffffff81618fb0 ffffffff81618fb0 014b8680 2**0 CONTENTS, READONLY 17 .comment 0000cd74 0000000000000000 0000000000000000 014b8680 2**0 CONTENTS, READONLY 18 .gnu.attributes 00000010 0000000000000000 0000000000000000 014c53f4 2**0
正如在 reverseengineering.se 上討論的關於替換 ELF 部分的類似問題的答案中所提到的,
dd
在某些情況下,除了新存檔不會更大(例如是否有重定位)之外,簡單地使用可能就足夠了。
是的,這是可能的,但是改變 .init.ramfs 部分的大小和地址是不夠的,因為核心的 ELF 執行檔與initramfs 部分 的開始和結束的虛擬地址靜態連結。
在 Linux 原始碼中,相關程式碼位於 iniramfs.c 源文件中:
void __init populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); ... }
因此,您還需要在 unpack_to_rootfs() 函式呼叫的機器程式碼中更改這兩個偏移量,該函式位於 .init.text 部分中。(注意重定位表中的任何相關條目!…如果存在)
此外,參考 Icarus 的回复,對 initramfs 部分的大小、文件偏移量和起始虛擬地址以及上述兩個偏移量(unpack_to_rootfs() 函式的參數)的操作,使您能夠添加自己的自定義LARGER在 ELF 文件的最大虛擬地址之上傳入的 initramfs 部分。程序頭 (PHeader) 的“記憶體大小”欄位也需要修改,以反映在舊虛擬地址空間結束後附加的更大的 initramfs 部分。
PS 在將原始 init.ramfs 部分移動到新的高起始虛擬地址後,核心的虛擬地址空間中剩餘的“洞”不會造成任何傷害,因為相關的記憶體稍後會由 init 中定義的 free_initmem(void) 函式釋放.c 源文件。