OSDev.org https://forum.osdev.org/ |
|
UNKNOWN EIP issue https://forum.osdev.org/viewtopic.php?f=13&t=29261 |
Page 1 of 1 |
Author: | BASICFreak [ Fri Apr 24, 2015 12:28 pm ] |
Post subject: | UNKNOWN EIP issue |
Ok, so I have been writing an ELF loader, when I realized my DEBUG_print(f) somehow changes EIP to 0x80010. So, I removed that code and did this in my main function: Code: for(uint32_t xx = 0; xx < 0xFFFF0 ; xx++) outb(DEBUG_PORT, (uint8_t) 'a'); DisAsm-INTEL (with extra BS): Code: 1000ac: bb f0 ff 0f 00 mov ebx,0xffff0 1000b1: c7 04 24 d2 53 10 00 mov DWORD PTR [esp],0x1053d2 1000b8: e8 d3 04 00 00 call 100590 <DEBUG_printf> 1000bd: c7 44 24 04 00 90 10 mov DWORD PTR [esp+0x4],0x109000 1000c4: 00 1000c5: c7 04 24 28 50 10 00 mov DWORD PTR [esp],0x105028 1000cc: e8 bf 04 00 00 call 100590 <DEBUG_printf> 1000d1: 8d b4 26 00 00 00 00 lea esi,[esi+eiz*1+0x0] 1000d8: c7 44 24 04 61 00 00 mov DWORD PTR [esp+0x4],0x61 1000df: 00 1000e0: c7 04 24 e9 00 00 00 mov DWORD PTR [esp],0xe9 1000e7: e8 14 00 00 00 call 100100 <outb> 1000ec: 83 eb 01 sub ebx,0x1 1000ef: 75 e7 jne 1000d8 <kmain+0x98> Just as a way to test, before it is through the loop (ebx says we made it to 0xDBAC8) INT 32 (0x20) is fired. No this is not the PIT as it is masked in the PIC and if I remove the loop we end up with no issue. outb(): Code: void outb(uint16_t port, uint8_t data) { __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data)); } DisAsm-INTEL: Code: 00100100 <outb>: 100100: 8b 44 24 08 mov eax,DWORD PTR [esp+0x8] 100104: 8b 54 24 04 mov edx,DWORD PTR [esp+0x4] 100108: ee out dx,al 100109: c3 ret 10010a: 8d b6 00 00 00 00 lea esi,[esi+0x0] I see no reference to 0x80010 in the binary My INT Handler reports: Code: UNHANDLED INTERRUPT ENCOUNTERED! INTERRUPT # 32 FATAL ERROR: EAX = 0x61 EBX = 0xDBAC8 ECX = 0x1F EDX = 0xE9 EDI = 0x26455 ESI = 0x2640D EBP = 0x67EDC ESP = 0x108FC6 GS = 0x10 FS = 0x62600010 ES = 0x62600010 DS = 0x47E80010 EIP = 0x80010 CS = 0x2020000 EFLAGS = 0xE90000 SS = 0x0 USER-ESP = 0x610000 ERROR-CODE = 0xEC0000 EIP RAM DUMP (EIP - 10) - (EIP + 10): 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 [0x0] 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 ESP RAM DUMP (ESP - 10) - (ESP + 10): 0x0 0x0 0x1F 0x0 0x0 0x0 0x61 0x0 0x0 0x0 [0x20] 0x0 0x0 0x0 0x0 0x0 0xEC 0x0 0x10 0x0 This has stumped me for days now, anyone have an idea where to look or if I'm just blind and missed something obvious? It is not Stack overflow as the stack is from 0x109000 - 0x107000. The kernel ELF is loaded at 0x100000 - 0x10A8A0. |
Author: | Combuster [ Fri Apr 24, 2015 3:39 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
Your regdump is broken. DS, ES and FS are rendered incorrectly, CS has the same problem and additionally is likely a bogus value, EFLAGS with this value is certainly impossible, and the same goes for SS unless it's still zero from real mode. And in this situation, I wouldn't trust the other values either, particularly not EIP. |
Author: | BASICFreak [ Fri Apr 24, 2015 4:11 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
Combuster wrote: Your regdump is broken. DS, ES and FS are rendered incorrectly, CS has the same problem and additionally is likely a bogus value, EFLAGS with this value is certainly impossible, and the same goes for SS unless it's still zero from real mode. And in this situation, I wouldn't trust the other values either, particularly not EIP. I realize some are bogus ESP, EAX, EBX, EDX, and GS is all I trust in that output. If I divide by 0 we get a much more trusted output: Code: UNHANDLED INTERRUPT ENCOUNTERED! INTERRUPT # 0 FATAL ERROR: Division By Zero EAX = 0x1 EBX = 0xFFFF0 ECX = 0x0 EDX = 0x0 EDI = 0x26455 ESI = 0x2640D EBP = 0x67EDC ESP = 0x108FC4 GS = 0x10 FS = 0x10 ES = 0x20010 DS = 0x20010 EIP = 0x1000D9 CS = 0x8 EFLAGS = 0x10246 SS = 0x109000 USER-ESP = 0x105028 ERROR-CODE = 0x0 EIP RAM DUMP (EIP - 10) - (EIP + 10): 0x0 0x0 0xB8 0x1 0x0 0x0 0x0 0x31 0xC9 0x99 [0xF7] 0xF9 0xC7 0x4 0x24 0xED 0x53 0x10 0x0 0x89 ESP RAM DUMP (ESP - 10) - (ESP + 10): 0x0 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x0 0x0 [0x0] 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0xD9 0x0 Although I'm unsure where the extra 0x20000 come from in ES and DS. Also with optimizer level 0 I make it almost all the way through the loop till EBX = 0x26260 I'm taking a break from this... Just wanted to show that those are the values the system thinks are there. |
Author: | Brendan [ Sat Apr 25, 2015 5:00 am ] |
Post subject: | Re: UNKNOWN EIP issue |
Hi, BASICFreak wrote: I realize some are bogus ESP, EAX, EBX, EDX, and GS is all I trust in that output. EAX, ECX and EDX all look correct to me. DS, ES, FS and GS also look correct, except that they're 16-bit registers and you're displaying them as 32-bit values which causes the highest 16-bits (which don't exist) to look like random trash. From there, you can reconstruct the stack contents like this:
0x00080010 = reported EIP 0x02020000 = reported CS 0x00E90000 = reported eflags 0x00108FC6 = reported ESP 0x00000000 = reported SS The 0x0202 part is the only thing that looks like it might be EFLAGS, so using that as an "anchor point" and adjusting the stack contents around it you'd get this:
0x001000EC = potential EIP 0x00000008 = potential CS 0x00000202 = potential eflags 0x8FC600E9 = potential ESP 0x00000010 = potential SS That looks quite believable to me; suggesting that your code to display registers has an "off by 2" bug. For the original "INT 32":
Cheers, Brendan |
Author: | BASICFreak [ Mon Apr 27, 2015 12:04 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
Ok, let me attempt to go in order of the code First Grub is loading my Kernel (so I won't modify boot sector or stage two) On load the kernel sets esp to the bottom of the stack, pushes eax and ebx, then calls kmain kmain checks multiboot flags to make sure it has the information needed. installs GDT installs IDT initializes 8259: Code: // Send Initialize Command _8259_Command_Out(0, INIT); _8259_Command_Out(1, INIT); // Map IRQs (0-15) to 0x20-0x2F _8259_Map(0, 0x20); _8259_Map(1, 0x28); // Tell PICs how to talk _8259_ICW3(0); _8259_ICW3(1); // Tell PICs to use 80x86 mode _8259_ICW4(0); _8259_ICW4(1); // Disable All IRQs _8259_Disable_ALL_IRQ(); _8259_Enable_IRQ(2); Which breaks down into (if I followed the code correctly): Code: outb(0x20, 0x11); outb(0xA0, 0x11); outb(0x21, 0x20); outb(0xA1, 0x28); outb(0x21, 2); outb(0xA1, 4); outb(0x21, 1); outb(0xA1, 1); outb(0x21, 0); outb(0xA1, 0); uint8_t temp = inb(0x21); temp &= ~(1 << 2); outb(0x21, temp); then kmain starts the ints (sti) from this point everything will work perfectly fine no misfired INTs unless I call outb many-many times. For testing only at this point is the loop with outb(0xE9, 'a'); NEVER Makes it this far (while loop is in place): cli or while(true); either way same results. hlt I have also tried setting up the PIT before starting interrupts, but if I send ACK to the PIC after handling what it thinks to be the PIT I then run into a Double Fault, which is captured before it hits a Triple Fault. While the actual PIT IRQ works fine, so it seems to me that the software must be triggering INT 0x20. But again in the disassembled Binary, I don't see a reference to INT 0x20 or address 0x80010. Also I think I have fixed the register dump code here is the new output (still BS on this INT): Code: UNHANDLED INTERRUPT ENCOUNTERED!
INTERRUPT # 32 FATAL ERROR: EAX = 0x61 EBX = 0x26260 ECX = 0x1F EDX = 0xE9 EDI = 0x26455 ESI = 0x2640D EBP = 0x108FF0 ESP = 0x108FB6 GS = 0x10 FS = 0x10 ES = 0x10 DS = 0x10 EIP = 0x80010 CS = 0x0 EFLAGS = 0x0 SS = 0x0 USER-ESP = 0x610000 ERROR-CODE = 0x0 EIP RAM DUMP (EIP - 10) - (EIP + 10): 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 [0x0] 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 ESP RAM DUMP (ESP - 10) - (ESP + 10): 0x0 0x0 0x1F 0x0 0x0 0x0 0x61 0x0 0x0 0x0 [0x20] 0x0 0x0 0x0 0x0 0x0 0xC6 0x0 0x10 0x0 |
Author: | kzinti [ Mon Apr 27, 2015 12:14 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
int 0x20 is your PIT. You programmed the PIC to send IRQ0 (PIT) to 0x20. So I'm not sure your statement about the PIT IRQ working fine is true. |
Author: | BASICFreak [ Mon Apr 27, 2015 1:11 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
OK, so this is why I took a break for two days, ISSUE is resolved. changed my IDT_COMMON from: Code: IDT_COMMON: pusha push ds push es push fs push gs mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov eax, esp push eax mov eax, IDT_HANDLER call eax pop eax pop gs pop fs pop es pop ds popa add esp, 8 iret TO: Code: IDT_COMMON: pusha push ds push es push fs push gs mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov eax, esp push eax mov eax, IDT_HANDLER call eax pop eax pop gs pop fs pop es pop ds popa pop word [tempdataw] add esp, 4 iret tempdataw dw 0 No issue at all now, my ELF phaser and the loop with outb both complete with no issue. Now my question is how many bytes does a word actually take up on the stack? Before IDT_COMMON is called I push byte (error code) then push word (IDT Number) I use a word for IDT Number because anything over 0x7F in a byte causes errors due to signed nature of byte |
Author: | iansjack [ Mon Apr 27, 2015 3:42 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
Quote: Now my question is how many bytes does a word actually take up on the stack? Now my question is "Why are you asking here for the answer to something that is clearly described in the Programmer's Manual?".
|
Author: | Brendan [ Mon Apr 27, 2015 11:32 pm ] |
Post subject: | Re: UNKNOWN EIP issue |
Hi, BASICFreak wrote: Now my question is how many bytes does a word actually take up on the stack? It's a little bit convoluted, but depends on the operand size. For example, "push dword 0x12345678" will consume 4 bytes of stack space, and "push word 0x1234" will consume 2 bytes of stack space (similar to "sub esp,2; mov word [esp],0x1234"). However, for an instruction with a 32-bit operand size and a 2-byte immediate operand, the immediate operand will be sign extended and that 2-byte immediate operand will consume 4 bytes of stack. The same happens with 1-byte immediate operands (which are sign extended to whatever the operand size is). Also, for segment registers if the operands size is 32-bit then the CPU will zero-extend (and not sign extend) the 16-bit value and store 4 bytes. Finally, all of this also applies to 64-bit operand sizes (e.g. 1-byte, 2-byte and 4-byte immediate operands are extended to 8 bytes, segment registers are zero extended to 8 bytes; but something like "push word [foo]" still consumes 2 bytes of stack). Basically, pushing a word on the stack consumes 2 bytes or 4 bytes or 8 bytes, depending on the specific instruction and operand size. Cheers, Brendan |
Author: | Antti [ Tue Apr 28, 2015 10:38 am ] |
Post subject: | Re: UNKNOWN EIP issue |
iansjack wrote: Why are you asking here for the answer to something that is clearly described in the Programmer's Manual? Actually, this one is not very clear. Brendan wrote: However, for an instruction with a 32-bit operand size and a 2-byte immediate operand, the immediate operand will be sign extended and that 2-byte immediate operand will consume 4 bytes of stack. I would not want to complain... but if the operand size is 32-bit, a "push imm16" is not possible without an operand size override. It will consume 2 bytes of stack. Brendan wrote: Finally, all of this also applies to 64-bit operand sizes (e.g. 1-byte, 2-byte and 4-byte immediate operands are extended to 8 bytes, segment registers are zero extended to 8 bytes; but something like "push word [foo]" still consumes 2 bytes of stack). Same as above. |
Author: | Brendan [ Tue Apr 28, 2015 11:03 am ] |
Post subject: | Re: UNKNOWN EIP issue |
Hi, Antti wrote: Brendan wrote: However, for an instruction with a 32-bit operand size and a 2-byte immediate operand, the immediate operand will be sign extended and that 2-byte immediate operand will consume 4 bytes of stack. I would not want to complain... but if the operand size is 32-bit, a "push imm16" is not possible without an operand size override. It will consume 2 bytes of stack. Brendan wrote: Finally, all of this also applies to 64-bit operand sizes (e.g. 1-byte, 2-byte and 4-byte immediate operands are extended to 8 bytes, segment registers are zero extended to 8 bytes; but something like "push word [foo]" still consumes 2 bytes of stack). Same as above. You're right- it's impossible to encode a 2-byte immediate in with 32-bit or 64-bit operand size. Cheers, Brendan |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |