Issue
I am working on a toy OS that is booted by grub.
However, some of the sections in the kernel images (especially which are objcopy-ed to original kernel image) are not loaded into physical memory at boot time. (i.e., after jumping to ENTRY defined by kernel elf)
Here are some questions.
What determines the amount of the size of the contents that is loaded into memory from the disk by the grub? Can I configure it?
Or the size is fixed, and should I just read the rest of them manually from the disk?
################ Updates ################
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
In particular, I want to have GRUB load .part1
, .part2
and .srtos_conf
sections.
I guess they are not loaded as they are not part of program headers.
How can I add these sections as program headers?
Currently, these are merged to the kernel using objcopy --add-section XXX
and the section flags are alloc,readonly,load,contents
.
Which option do I have to use to add these sections to program headers?
Solution
The objcopy method to add new sections to the ELF appears to be too limited. https://reverseengineering.stackexchange.com/a/14780 suggests it is impossible to add program header entries this way.
I would instead suggest to create object files for .part1
etc. using objcopy,
and to then specify these as additional inputs to your linker when building your kernel.elf. Objcopy will place the file
contents in a .data
section for you, and will create symbols
_binary_x_start
/_binary_x_end
/ _binary_x_size
for convenience.
As an example:
Creating an object file out of any type of file (substitute your target triplet):
i686-elf-objcopy --input binary -B i386 -O elf32-i386 x x.o
Adding x.o to the linker inputs expands the .data
output section to contain
the file contents, and naturally results in it being loaded by the loader.
If needed, you can get control over where the file is loaded by using a linker script. (objcopy with the right arguments may also do this for you, but a linker script is usually a cleaner approach).
For example, to place a file specifically at 0x200000, you might do:
/* ... */
.data : {
*(EXCLUDE_FILE(x.o) .data)
}
. = 0x0200000;
.foo : {
x.o (.data)
}
/* ... */
Of course you can also rename the section in your object file to avoid the
EXCLUDE_FILE
here.
Another option you may want to look at is using multiboot modules. Having the files as modules can be an easier approach, but gives you less control over where/how they are loaded.
It also ties you in to multiboot more than you may like (I like my bootloaders simple and replaceable ;-).
Answered By - Chris Smeele Answer Checked By - Katrina (WPSolving Volunteer)