OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 4:23 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: UNKNOWN EIP issue
PostPosted: Fri Apr 24, 2015 12:28 pm 
Offline
Member
Member
User avatar

Joined: Fri Jan 16, 2009 8:34 pm
Posts: 284
Location: Louisiana, USA
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.

_________________
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Fri Apr 24, 2015 3:39 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
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.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Fri Apr 24, 2015 4:11 pm 
Offline
Member
Member
User avatar

Joined: Fri Jan 16, 2009 8:34 pm
Posts: 284
Location: Louisiana, USA
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.

_________________
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Sat Apr 25, 2015 5:00 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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:
    0x00EC0000 = reported error code
    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:
    0x0000???? = potential error code
    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":
  • you disabled interrupts with CLI
  • IRQ0 occurred and the IRQ wasn't masked, so the PIC chip tried to deliver it but couldn't because interrupts where disabled, so the PIC chip set a bit in its "interrupt received register" instead
  • You reprogrammed the PIC chip (I assume) and masked all the IRQs; but this does not clear the PIC chip's "interrupt received register"
  • You enabled interrupts with STI, the PIC chip noticed and checked its "interrupt received register", saw it has something it can deliver now, and sent it to you as "interrupt 32".
The correct way to mask all IRQs is:
  • Leave interrupts enabled in the CPU (STI)
  • Mask all IRQs in the PIC chips
  • Do a few NOP instructions or something (to give the hardware a chance to deliver any pending IRQs)
  • Only after all pending IRQs have been handled (by BIOS), disable interrupts with CLI if you could be bothered (there's actually no reason to use CLI at all).
  • Reprogram the PIC chip


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Mon Apr 27, 2015 12:04 pm 
Offline
Member
Member
User avatar

Joined: Fri Jan 16, 2009 8:34 pm
Posts: 284
Location: Louisiana, USA
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

_________________
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Mon Apr 27, 2015 12:14 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
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.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Mon Apr 27, 2015 1:11 pm 
Offline
Member
Member
User avatar

Joined: Fri Jan 16, 2009 8:34 pm
Posts: 284
Location: Louisiana, USA
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

_________________
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Mon Apr 27, 2015 3:42 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
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?".


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Mon Apr 27, 2015 11:32 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Tue Apr 28, 2015 10:38 am 
Offline
Member
Member

Joined: Thu Jul 05, 2012 5:12 am
Posts: 923
Location: Finland
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.

_________________
Undefined behavior since 2012


Top
 Profile  
 
 Post subject: Re: UNKNOWN EIP issue
PostPosted: Tue Apr 28, 2015 11:03 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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. :oops:


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 32 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group