Loading and launching programs

Loading and launching programs
Michal Sojka1
Czech Technical University in Prague,
Faculty of Electrical Engineering
Email: [email protected]
April 15, 2015
1
Based on exercises by Benjamin Engel from TU Dresden.
M. Sojka
A3B33OSD, task E3
April 15, 2015
1 / 16
Roadmap
Last week
I
Start hard-coded root task
This week
I
Start arbitrary program as root task
I
The program is provided in a separate binary
I
Required memory mapping is read from binary’s header
M. Sojka
A3B33OSD, task E3
April 15, 2015
2 / 16
Prerequisites
I
Brief look into program startup assembly and linker script
I
Multiboot – passing information from bootloader to the OS
kernel
I
ELF binary format
M. Sojka
A3B33OSD, task E3
April 15, 2015
3 / 16
Program binaries
Program binaries
I
Composed of headers, segments and sections
I
One segment contains one or more sections
I
A section may or may not belong to a segment
I
All of this is controlled by “linker scripts”
Linker script – user/src/linker.ld
I
Program entry point at symbol __start
I
Two segments: data (rw=6) and text (rx=5)
I
Put section .text in segment text and sections .data and .bss
in segment data
I
ALIGN stack and text to page boundary (0x1000)
M. Sojka
A3B33OSD, task E3
April 15, 2015
4 / 16
Program binaries
Program startup – user/src/start.S
.text
.global __start
__start:
mov $stack_top, %esp
call main_func
ud2
I
Put this into the .text section
I
Define global symbol __start:
I
Setup a stack by loading the address of stack_top into esp
(stack_top is defined in linker.ld)
I
Call main_func()
M. Sojka
A3B33OSD, task E3
April 15, 2015
5 / 16
Program binaries
Building and inspecting the user program
I
Goto user/build and make user binary
I
Inspect binary by nm -C user.nova.debug
00002004
00002000
0000301 e
00002000
00003000
0000300 c
D
D
T
D
T
T
foobar_in_data
foobar_in_data2
main_func
stack_top
__start
syscall3 ( unsigned int , unsigned int , un
I
There are three symbols in the text section (T) and three in
data section (D)
I
Dump the binary: hexdump -C user.nova
I
Decode headers: objdump -x user.nova
M. Sojka
A3B33OSD, task E3
April 15, 2015
6 / 16
Bootloader
Bootloader
I
We will use GRUB – standard GNU/Linux bootloader
I
Among others, it implements multiboot specification
I
It specifies how does bootloader pass various pieces of
information to the OS kernel.
I
We let the bootloader load not only the kernel (hypervisor) but
also the user.nova file:
ls boot
cat boot/menu.lst
M. Sojka
# bootloader configuration file
A3B33OSD, task E3
April 15, 2015
7 / 16
Bootloader
Multiboot information (multiboot.h)
https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
EBX
flags
I
mem_lower
mem_upper
Data structure passed by the bootloader to
the OS kernel
I
Flags is required, all the others are optional
boot_device
I
cmdline
mods_count
If flags:3 (3rd bit) is set, mods_count
and mods_addr are valid
I
mods_addr is the physical address to an
mods_addr
syms[4]
mmap_length
mmap_addr
...
M. Sojka
array of module structs with length
mods_count
mod_start
mod_end
string
reserved
A3B33OSD, task E3
mod_start
mod_end
string
reserved
April 15, 2015
...
8 / 16
Bootloader
Accessing data from the bootloader – remapping
I
I
Problem: Multiboot info (mbi) address (in EBX register) and
mods_addr are physical addresses
We need to (temporarily) map them into the virtual address
space. This can be done with the following function:
void * Ptab::remap(phys_addr)
I
It maps the physical memory into “kernel’s remap area” and
returns a pointer to it.
The previous mapping is replaced, thus returned pointers are
remap
only usable before the next call to remap!
▼area
virtual memory
Multi boot info
▼
M. Sojka
Kernel
physical memory
A3B33OSD, task E3
April 15, 2015
9 / 16
Bootloader
Task 1 – Find and map the user binary
1. Open kern/src/ec.cc: root_invoke()
2. Ec::current->regs.eax contains mbi pointer (see start.S to
understand why)
3. remap Multiboot Info, check flags:3, get mods_addr and
count
4. remap Multiboot module structure, print start and end address
of user binary
5. remap user binary (it’s an ELF object)
6. see kern/include/multiboot.h and elf.h
M. Sojka
A3B33OSD, task E3
April 15, 2015
10 / 16
ELF format
Executable and Linkable Format (ELF)
http://www.sco.com/developers/devspecs/gabi41.pdf, chapter 4
ELF header
Program header
table
I
The format of binaries on Unix systems
I
ELF header contains offset where to
find PH table (ph_offset)
I
Program header table describes the
segments to be used at runtime
code segment
data segment
...
M. Sojka
A3B33OSD, task E3
April 15, 2015
11 / 16
ELF format
ELF header (elf.h)
magic: 7f ’E’ ’L’ ’F’
data
version padd.
padding
padding
type
machine
version
entry
ph_offset
sh_offset
flags
eh_size
ph_size
ph_count
sh_size
sh_count
strtab
class
M. Sojka
A3B33OSD, task E3
I
Check magic, data == 1
and type == 2
I
entry – user EIP
I
ph_count: number of
program headers
I
ph_offset: where within the
file the program header table
starts
April 15, 2015
12 / 16
ELF format
Program header table
ELF header
type
file offset
virtual address
physical address
file size
mem size
flags
alignment
I
If type == PT_LOAD (== 1) load this
segment
I
Flags:2 ⇒ writable
I
Offset: where this segment starts relative
to the beginning of the file
I
Virtual address: where to map this
segment to
I
File/Mem size: segment size in file and
memory
type
file offset
...
M. Sojka
A3B33OSD, task E3
April 15, 2015
13 / 16
ELF format
Task 2 – Decode the ELF
1. Continue in root_invoke()
I
user binary is still mapped in
2. Set current->regs.eip to the correct entry point (from ELF
header)
3. Remap program header table and iterate over all (two)
program segments
3.1 If type != PT_LOAD, ignore this segment
3.2 Print all virt/phys addresses and mem sizes
I
I
I
M. Sojka
Align them properly to 4k page boundaries
phys/virt addresses: align down
mem size: align up
A3B33OSD, task E3
April 15, 2015
14 / 16
Map and start the program
Task 3 – Map and start the program
1. Some sanity checks:
I
I
File size and mem size should be equal
Virtual address and file offset should be equal (modulo page
size)
2. Add mapping for all pages in all segments:
Ptab::insert_mapping (virt, phys, attr)
I Inserts a mapping from virtual address virt to physical
address phys with attributes attr
I If flags & Ph::PF_W ⇒ should be mapped writable, thus
attr = 7, otherwise attr = 5
I (See class Ph in kernel/include/elf.h)
3. ret_user_iret() to start user program
M. Sojka
A3B33OSD, task E3
April 15, 2015
15 / 16
Map and start the program
Understanding Ptab::insert_mapping – x86 page tables
cr3
pdir addr
page directory
page table
0x1000
ptab addr
ptab addr
31
1
1
1
2
...
.data
.stack
0x2000
.text
1
12
20 bit phys addr
page addr
page addr
1
0
S R
P
UW
P – present (1 : entry valid)
R/W – 0 : read only, 1 : writable
S/U – 0 : kernel only, 1 : user
M. Sojka
A3B33OSD, task E3
April 15, 2015
16 / 16