6.828-Hw1-Boot xv6

Homework: boot xv6

Exercise: What is on the stack

Begin by restarting qemu and gdb, and set a break-point at 0x7c00, the start of the boot block (bootasm.S). Single step through the instructions (type si at the gdb prompt). Where in bootasm.S is the stack pointer initialized? (Single step until you see an instruction that moves a value into %esp, the register for the stack pointer.)

It’s at

1
2
# Set up the stack pointer and call into C.
=> 0x7c43: mov $0x7c00,%esp

Single step through the call to bootmain; what is on the stack now?

Before we call bootmain, ESP still points where the boot loader starts.

1
2
3
4
5
6
7
8
9
10
11
12
13
(gdb) b*0x7c48
Breakpoint 1 at 0x7c48
(gdb) c
Continuing.
The target architecture is assumed to be i386
=> 0x7c48: call 0x7d2a
(gdb) x/24x $esp
0x7c00: 0x8ec031fa 0x8ec08ed8 0xa864e4d0 0xb0fa7502
0x7c10: 0xe464e6d1 0x7502a864 0xe6dfb0fa 0x16010f60
0x7c20: 0x200f7c78 0xc88366c0 0xc0220f01 0x087c31ea
0x7c30: 0x10b86600 0x8ed88e00 0x66d08ec0 0x8e0000b8
0x7c40: 0xbce88ee0 0x00007c00 0x0000dde8 0x00b86600
0x7c50: 0xc289668a 0xb866ef66 0xef668ae0 0x9066feeb

Then step into bootmain. Now the first and only element on stack is 0x00007c4d. From bootblock.asm, we can know that This is where the bootmain returns.

1
2
3
4
5
6
7
8
9
10
(gdb) si
=> 0x7d2a: push %ebp
0x00007d2a in ?? ()
(gdb) x/24x $esp
0x7bfc: 0x00007c4d 0x8ec031fa 0x8ec08ed8 0xa864e4d0
0x7c0c: 0xb0fa7502 0xe464e6d1 0x7502a864 0xe6dfb0fa
0x7c1c: 0x16010f60 0x200f7c78 0xc88366c0 0xc0220f01
0x7c2c: 0x087c31ea 0x10b86600 0x8ed88e00 0x66d08ec0
0x7c3c: 0x8e0000b8 0xbce88ee0 0x00007c00 0x0000dde8
0x7c4c: 0x00b86600 0xc289668a 0xb866ef66 0xef668ae0
1
2
3
4
# If bootmain returns (it shouldn't), trigger a Bochs
# breakpoint if running under Bochs, then loop.
movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
7c4d: 66 b8 00 8a mov $0x8a00,%ax

This shows call will also modify %ESP, pushing the return address into the stack.

Continue to run till 0x7d30

1
2
3
4
5
6
7
8
9
10
(gdb) si
=> 0x7d30: sub $0x2c,%esp
0x00007d30 in ?? ()
(gdb) x/24x $esp
0x7bec: 0x00000000 0x00000000 0x00000000 0x00000000
0x7bfc: 0x00007c4d 0x8ec031fa 0x8ec08ed8 0xa864e4d0
0x7c0c: 0xb0fa7502 0xe464e6d1 0x7502a864 0xe6dfb0fa
0x7c1c: 0x16010f60 0x200f7c78 0xc88366c0 0xc0220f01
0x7c2c: 0x087c31ea 0x10b86600 0x8ed88e00 0x66d08ec0
0x7c3c: 0x8e0000b8 0xbce88ee0 0x00007c00 0x0000dde8

That corresponds to this asm code

1
2
3
4
5
7d2a:	55                   	push   %ebp
7d2b: 89 e5 mov %esp,%ebp
7d2d: 57 push %edi
7d2e: 56 push %esi
7d2f: 53 push %ebx

We can know that the stack are like this in memory:

1
2
3
4
5
6
VALUE                 										ADDRESS
0x0(EBX) 0x7bec(ESP)
0x0(ESI) 0x7bf0(ESP+4)
0x0(EDI) 0x7bf4(ESP+8)
0x0(EBP) 0x7bf8(ESP+12)
0x7c4d(Return address) 0x7bfc(ESP+16)

What do the first assembly instructions of bootmain do to the stack? Look for bootmain in bootblock.asm.

1
=> 0x7d2a: 	push   %ebp

Push %ebp into the stack

Continue tracing via gdb (using breakpoints if necessary – see hint below) and look for the call that changes eip to 0x10000c. What does that call do to the stack? (Hint: Think about what this call is trying to accomplish in the boot sequence and try to identify this point in bootmain.c, and the corresponding instruction in the bootmain code in bootblock.asm. This might help you set suitable breakpoints to speed things up.)

It’s at 0x7db2

1
=> 0x7db2: call   *0x10018

In bootmain.c it’s entry()

1
2
3
4
5
6
elf = (struct elfhdr*)0x10000;  // scratch space
//....
// Call the entry point from the ELF header.
// Does not return!
entry = (void(*)(void))(elf->entry);
entry();

From elf.h we can know How did we get 0x10018

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// File header
struct elfhdr {
uint magic; // must equal ELF_MAGIC
uchar elf[12];
ushort type;
ushort machine;
uint version;
uint entry;
......
/*
uint = unsigned int = 4 Bytes
ushort = unsigned short = 1 Byte
uchar = unsigned char = 2 Byte
/*

0x10000 + 4 + C + 2 + 2 + 4 = 0x10018

What on 0x10018 is the destination of call , also the value to be set on %eip

1
2
(gdb) x/x 0x10018
0x10018: 0x0010000c

That’s why next step we are at 0x10000c

From previous question, we’ve already noticed that call will also modify %ESP, pushing the return address into the stack.

Author

BakaFT

Posted on

2021-11-02

Updated on

2023-12-28

Licensed under

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×