pczarn / rustboot

A multi-platform kernel written in Rust
http://pczarn.github.io/rustboot/doc/main/index.html
MIT License
197 stars 15 forks source link

Memory access error #13

Open alexchandel opened 10 years ago

alexchandel commented 10 years ago

Building on OS X gives me the page fault error: "Accessed 0xc0000014 from 0x1196c".

The instruction pointer is different every time I build, but the cr2 is always 0xc0000014. The stack starts at 0xc0000000, .

However, I've noticed that the instruction pointer 0x1196c points to inside "000118fa <exception_handler_asm>:"

000118fa <exception_handler_asm>:
   118fa:   0f a8                   push   gs
   118fc:   0f a0                   push   fs
   118fe:   06                      push   es
   118ff:   1e                      push   ds
   11900:   60                      pusha  
   11901:   89 e6                   mov    esi,esp
...
   1194c:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
   11950:   c7 44 24 14 04 00 00    mov    DWORD PTR [esp+0x14],0x4
   11957:   00 
   11958:   8d 44 24 20             lea    eax,[esp+0x20]
   1195c:   89 44 24 18             mov    DWORD PTR [esp+0x18],eax
   11960:   c7 44 24 1c 02 00 00    mov    DWORD PTR [esp+0x1c],0x2
   11967:   00 
   11968:   8d 44 24 10             lea    eax,[esp+0x10]
   1196c:   89 44 24 7c             mov    DWORD PTR [esp+0x7c],eax
   11970:   8d 83 cc e1 ff ff       lea    eax,[ebx-0x1e34]
   11976:   89 44 24 70             mov    DWORD PTR [esp+0x70],eax
   1197a:   8d 44 24 7c             lea    eax,[esp+0x7c]
   1197e:   89 44 24 74             mov    DWORD PTR [esp+0x74],eax
   11982:   8d 83 0c fe ff ff       lea    eax,[ebx-0x1f4]
   11988:   89 44 24 60             mov    DWORD PTR [esp+0x60],eax
   1198c:   c7 44 24 64 02 00 00    mov    DWORD PTR [esp+0x64],0x2
   11993:   00 
   11994:   8d 44 24 70             lea    eax,[esp+0x70]
   11998:   89 44 24 68             mov    DWORD PTR [esp+0x68],eax
   1199c:   c7 44 24 6c 01 00 00    mov    DWORD PTR [esp+0x6c],0x1
   119a3:   00 
   119a4:   8d 84 24 88 00 00 00    lea    eax,[esp+0x88]
   119ab:   89 84 24 84 00 00 00    mov    DWORD PTR [esp+0x84],eax
...

Shouldn't Context::save() save the instruction address from before the interrupt, or does the page fault actually occur in the exception handler?

I've noticed that subtracting different values from esp changes the cr2 value slightly.

Also in case it's related, I'm curious how _binary_initram_elf_start gets resolved. It's declared as an external u8, and never referenced again. The closest thing I can find is the _start label in module.asm. But in the disassembly, I find this unfamiliar code:

00013cd0 <_binary_initram_elf_start>:
   13cd0:   7f 45                   jg     13d17 <_binary_initram_elf_start+0x47>
   13cd2:   4c                      dec    esp
   13cd3:   46                      inc    esi
   13cd4:   01 01                   add    DWORD PTR [ecx],eax
   13cd6:   01 00                   add    DWORD PTR [eax],eax
    ...
   13ce0:   02 00                   add    al,BYTE PTR [eax]
   13ce2:   03 00                   add    eax,DWORD PTR [eax]
...
   13d14:   78 00                   js     13d16 <_binary_initram_elf_start+0x46>
   13d16:   00 00                   add    BYTE PTR [eax],al
   13d18:   78 00                   js     13d1a <_binary_initram_elf_start+0x4a>
   13d1a:   00 00                   add    BYTE PTR [eax],al
   13d1c:   05 00 00 00 00          add    eax,0x0
   13d21:   10 00                   adc    BYTE PTR [eax],al
    ...

Edit: figured out the linker creating the _binary_initram_elf_start section. The actual jump location is 0x08048060, which first appears in initram.elf. This error still doesn't make sense, since module.asm doesn't access the stack.

alexchandel commented 10 years ago

Actually, look at the disassembly for "jmp *$0" :: "m"(self.eip), "{esp}"(self.esp) that I found in main:

...
   10b56:   89 44 24 34             mov    DWORD PTR [esp+0x34],eax
   10b5a:   89 cc                   mov    esp,ecx
   10b5c:   31 c0                   xor    eax,eax
   10b5e:   31 d2                   xor    edx,edx
   10b60:   ff 64 24 34             jmp    DWORD PTR [esp+0x34]
...

Notice how esp is clobbered before the new instruction pointer is loaded. Guess what [esp+0x34] is then? Page Fault. Instead, load eip first:

asm!("xor edx, edx
      jmp DWORD PTR $0" :: "{eax}"(self.eip), "{esp}"(self.esp) :: "volatile", "intel");