Skip to content

Instantly share code, notes, and snippets.

@CodingKoopa
Last active February 26, 2023 07:35
Show Gist options
  • Select an option

  • Save CodingKoopa/b07ab0797ff24a7dfb924c65e749e887 to your computer and use it in GitHub Desktop.

Select an option

Save CodingKoopa/b07ab0797ff24a7dfb924c65e749e887 to your computer and use it in GitHub Desktop.
SeaBIOS/xv6 stuff

xv6 boot

boot process

mainly just considering PATA/IDE (QEMU's default interface of choice)

glosses over memory model

Boot process:

Execution starts in the BIOS. QEMU's default BIOS image is SeaBIOS; Bochs can also use SeaBIOS but provides its own BIOS ROM by default (https://bochs.sourceforge.io/doc/docbook/user/bochsrc.html). We will use the SeaBIOS process as a reference: [https://www.seabios.org/Execution_and_code_flow]

QEMUEXTRA="--fw_cfg \"etc/show-boot-menu,string=1\""

modified SeaBIOS cfg modified SeaBIOS makefile gdbinit

troubleshooting boot

hexdump kernel lines up with x/120hx 0x10000 in GDB

$1 = {magic = 1179403647, elf = "\001\001\001\000\000\000\000\000\000\000\000", type = 2, machine = 3, version = 1, entry = 1048588, phoff = 52, shoff = 201436, flags = 0, ehsize = 52, phentsize = 32, phnum = 3, shentsize = 40, shnum = 17, shstrndx = 16}

~~however, if we x/10i 0x1000c, the instructions are obviously not the assembly entry we have in our source - the ELF is bad

wait no that address is in the ELF header

maybe the linker script is wrong?~~ maybe just misread? looks fine to me

okay, i hardcoded it to jump to the right place, but now it fails when jumping to a high addr

 segfault simulator <3  None  
=> 0x100032:    jmp    *%eax
0x00100032 in ?? ()
 segfault simulator <3  None  x/16i 0x801030d0
   0x801030d0 <main>:   lea    0x4(%esp),%ecx
   0x801030d4 <main+4>: and    $0xfffffff0,%esp
   0x801030d7 <main+7>: push   -0x4(%ecx)
   0x801030da <main+10>:        push   %ebp
   0x801030db <main+11>:        mov    %esp,%ebp
   0x801030dd <main+13>:        push   %ebx
   0x801030de <main+14>:        push   %ecx
   0x801030df <main+15>:        sub    $0x8,%esp
   0x801030e2 <main+18>:        push   $0x80400000
   0x801030e7 <main+23>:        push   $0x801154d0
   0x801030ec <main+28>:        call   0x80102690 <kinit1>
   0x801030f1 <main+33>:        call   0x80106fb0 <kvmalloc>
   0x801030f6 <main+38>:        call   0x801032d0 <mpinit>
   0x801030fb <main+43>:        call   0x80102880 <lapicinit>
   0x80103100 <main+48>:        call   0x80106a70 <seginit>
   0x80103105 <main+53>:        call   0x80103520 <picinit>
 segfault simulator <3  None  ni

looking at page directories:

x/16i entry
   0x10000c:    mov    %cr4,%eax
   0x10000f:    or     $0x10,%eax
   0x100012:    mov    %eax,%cr4
   0x100015:    mov    $0x109000,%eax
   0x10001a:    mov    %eax,%cr3
   0x10001d:    mov    %cr0,%eax
   0x100020:    or     $0x80010000,%eax
   0x100025:    mov    %eax,%cr0
   0x100028:    mov    $0x801154d0,%esp
   0x10002d:    mov    $0x801030d0,%eax
   0x100032:    jmp    *%eax
   0x100034:    xchg   %ax,%ax
   0x100036:    xchg   %ax,%ax
   0x100038:    xchg   %ax,%ax
   0x10003a:    xchg   %ax,%ax
   0x10003c:    xchg   %ax,%ax
 segfault simulator <3  bootmain  x/16x 0x109000
0x109000:       0x00000083      0x00000000      0x00000000      0x00000000
0x109010:       0x00000000      0x00000000      0x00000000      0x00000000
0x109020:       0x00000000      0x00000000      0x00000000      0x00000000

finding the high vt page directory entry:

x/x 0x109000 + (0x80000000 >> 22) * 4
0x109800:       0x00000083

nicer soln to the NOTE issue

According to this pull request, xv6 fails to boot on binutils 2.36. The author is correct; the informative .note.gnu.property section causes the ELF loader to hang. [https://lists.llvm.org/pipermail/llvm-dev/2018-March/121951.html]

getting there

so, the problem occurs when linking the initcode. first, look at the compiled initcode object:

$ readelf -S initcode.o
There are 18 section headers, starting at offset 0x380:

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        00000000 000034 00002c 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 000268 000018 08   I 15   1  4
  [ 3] .data             PROGBITS        00000000 000060 000000 00  WA  0   0  1
  [ 4] .bss              NOBITS          00000000 000060 000000 00  WA  0   0  1
  [ 5] .note.gnu.pr[...] NOTE            00000000 000060 000028 00   A  0   0  4
  [ 6] .debug_line       PROGBITS        00000000 000088 00004b 00   C  0   0  4
  [ 7] .rel.debug_line   REL             00000000 000280 000020 08   I 15   6  4
  [ 8] .debug_line_str   PROGBITS        00000000 0000d3 000033 01  MS  0   0  1
  [ 9] .debug_info       PROGBITS        00000000 000106 000024 00      0   0  1
  [10] .rel.debug_info   REL             00000000 0002a0 000030 08   I 15   9  4
  [11] .debug_abbrev     PROGBITS        00000000 00012a 000014 00      0   0  1
  [12] .debug_aranges    PROGBITS        00000000 000140 000020 00      0   0  8
  [13] .rel.debug_a[...] REL             00000000 0002d0 000010 08   I 15  12  4
  [14] .debug_str        PROGBITS        00000000 000160 00003f 01  MS  0   0  1
  [15] .symtab           SYMTAB          00000000 0001a0 0000b0 10     16  10  4
  [16] .strtab           STRTAB          00000000 000250 000016 00      0   0  1
  [17] .shstrtab         STRTAB          00000000 0002e0 00009f 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),
  D (mbind), p (processor specific)

the Note sections exist, but they are not doing any harm. but then, look at what happens when perform linking on it (not with other objects, yet):

readelf -S initcode.out
There are 12 section headers, starting at offset 0x368:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.pr[...] NOTE            080480b4 0000e0 000028 00   A  0   0  4
  [ 2] .text             PROGBITS        00000000 0000b4 00002c 00 WAX  0   0  4
  [ 3] .debug_aranges    PROGBITS        00000000 000108 000020 00      0   0  8
  [ 4] .debug_info       PROGBITS        00000000 000128 000024 00      0   0  1
  [ 5] .debug_abbrev     PROGBITS        00000000 00014c 000014 00      0   0  1
  [ 6] .debug_line       PROGBITS        00000000 000160 00004c 00      0   0  1
  [ 7] .debug_str        PROGBITS        00000000 0001ac 00003f 01  MS  0   0  1
  [ 8] .debug_line_str   PROGBITS        00000000 0001eb 000033 01  MS  0   0  1
  [ 9] .symtab           SYMTAB          00000000 000220 000090 10     10   5  4
  [10] .strtab           STRTAB          00000000 0002b0 000033 00      0   0  1
  [11] .shstrtab         STRTAB          00000000 0002e3 000084 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),
  D (mbind), p (processor specific)

the note has been placed at a super high address

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment