如何控制grub从磁盘加载到内存中的内容量?
Posted
技术标签:
【中文标题】如何控制grub从磁盘加载到内存中的内容量?【英文标题】:How to control the amount of contents loaded into memory from disk by grub? 【发布时间】:2020-12-08 05:51:56 【问题描述】:我正在开发一个由 grub 引导的玩具操作系统。
但是,内核映像中的某些部分(尤其是 objcopy 到原始内核映像的部分)在启动时并未加载到物理内存中。 (即跳转到内核精灵定义的ENTRY后)
这里有一些问题。
什么决定了 grub 从磁盘加载到内存中的内容的大小?可以配置吗?
或者大小是固定的,我应该手动从磁盘读取其余部分吗?
################ 更新################
There are 21 section headers, starting at offset 0x279bfc:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 01000000 001000 009a79 00 AX 0 0 16
[ 2] .rodata PROGBITS 0100a000 00b000 0012b0 00 A 0 0 4096
[ 3] .eh_frame PROGBITS 0100b2b0 00c2b0 0041b0 00 A 0 0 4
[ 4] .data PROGBITS 02000000 011000 002400 00 WA 0 0 4096
[ 5] .bss NOBITS 02002400 013400 108430 00 WA 0 0 1024
[ 6] .percpu_data PROGBITS 0210a880 11b880 002880 00 WA 0 0 4096
[ 7] .comment PROGBITS 00000000 11e100 000011 01 MS 0 0 1
[ 8] .debug_aranges PROGBITS 00000000 11e118 000620 00 0 0 8
[ 9] .debug_info PROGBITS 00000000 11e738 011352 00 0 0 1
[10] .debug_abbrev PROGBITS 00000000 12fa8a 004750 00 0 0 1
[11] .debug_line PROGBITS 00000000 1341da 00577b 00 0 0 1
[12] .debug_str PROGBITS 00000000 139955 00403c 01 MS 0 0 1
[13] .debug_loc PROGBITS 00000000 13d991 008966 00 0 0 1
[14] .debug_ranges PROGBITS 00000000 1462f7 000840 00 0 0 1
[15] .part1 PROGBITS 0c000000 147000 096ba8 00 A 0 0 1
[16] .part2 PROGBITS 0c100000 1de000 096b58 00 A 0 0 1
[17] .srtos_conf PROGBITS 0c1a0000 275000 00064f 00 A 0 0 1
[18] .symtab SYMTAB 00000000 275650 002780 10 19 157 4
[19] .strtab STRTAB 00000000 277dd0 001d64 00 0 0 1
[20] .shstrtab STRTAB 00000000 279b34 0000c7 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
Elf file type is EXEC (Executable file)
Entry point 0x1000038
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x01000000 0x01000000 0x0f460 0x0f460 R E 0x1000
LOAD 0x011000 0x02000000 0x02000000 0x10d100 0x10d100 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text .rodata .eh_frame
01 .data .bss .percpu_data
特别是,我想让 GRUB 加载 .part1
、.part2
和 .srtos_conf
部分。
我猜它们没有加载,因为它们不是程序头的一部分。
如何将这些部分添加为程序标题?
目前,这些都使用objcopy --add-section XXX
合并到内核中,并且部分标志是alloc,readonly,load,contents
。
我必须使用哪个选项将这些部分添加到程序头?
【问题讨论】:
你在使用多重引导吗?你的内核和 ELF 是可执行的吗? @MichaelPetch 是的,我意识到我可以配置 multiboot2 标头来决定 load_addr、load_end_addr 和 bss_end_addr。但是,如果我想加载超出 bss_end_addr 的非零内容,我该怎么办?手动将内容从磁盘加载到内存是唯一的方法吗? @shpark 如果您使用的是 ELF,则不需要这些_addr
选项。 GRUB 应该尊重二进制文件中的程序头以获取该信息。您能否详细说明“尤其是原始内核映像的 objcopy ”是什么意思?我也很好奇readelf -lS <yourkernel.elf>
的输出是什么,因为它准确地显示了你指示加载器在内存中放置的内容。
@ChrisSmeele 哦,我不知道_addr
不推荐。我添加了更多细节,包括readelf
输出。感谢您的帮助!
【参考方案1】:
向 ELF 添加新部分的 objcopy 方法似乎太有限了。 https://reverseengineering.stackexchange.com/a/14780 表示不可能 以这种方式添加程序头条目。
我建议使用 objcopy 为 .part1
等创建目标文件,
然后在构建 kernel.elf 时将这些指定为链接器的附加输入。 objcopy 将放置文件
.data
部分中的内容,并将创建符号
_binary_x_start
/_binary_x_end
/ _binary_x_size
为方便起见。
举个例子:
从任何类型的文件中创建一个目标文件(替换您的目标三元组):
i686-elf-objcopy --input binary -B i386 -O elf32-i386 x x.o
将 x.o 添加到链接器输入会扩展 .data
输出部分以包含
文件内容,自然会导致它被加载器加载。
如果需要,您可以使用链接描述文件控制文件的加载位置。 (带有正确参数的 objcopy 也可以为您执行此操作,但链接描述文件 通常是一种更清洁的方法)。
例如,要将文件专门放置在 0x200000,您可以这样做:
/* ... */
.data :
*(EXCLUDE_FILE(x.o) .data)
. = 0x0200000;
.foo :
x.o (.data)
/* ... */
当然,您也可以重命名目标文件中的部分以避免
EXCLUDE_FILE
这里。
您可能想要查看的另一个选项是使用多重引导模块。将文件作为模块使用可能是一种更简单的方法,但您无法控制它们的加载位置/加载方式。 它还让你更多地参与到多重引导中(我喜欢我的引导加载程序简单且可替换 ;-)。
【讨论】:
谢谢!我会采用这种方法。以上是关于如何控制grub从磁盘加载到内存中的内容量?的主要内容,如果未能解决你的问题,请参考以下文章