Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Celelibi <celelibi@gmail.com>
To: Duane Ellis <duane@duaneellis.com>
Cc: gdb@sourceware.org
Subject: Re: Tracing another stack
Date: Sat, 05 Dec 2015 18:33:00 -0000	[thread overview]
Message-ID: <CAJR2zJ89vA=eTCfzga1dVHthVS3NZYPidu4Ptgu7OhFB=zyTSA@mail.gmail.com> (raw)
In-Reply-To: <863D4E7B-2D4E-448B-8B41-EE97612A3BA3@duaneellis.com>

2015-12-01 14:24 UTC+01:00, Duane Ellis <duane@duaneellis.com>:
>
>>> But - when I have the debugger attached I set a breakpoint on that
>>> endless
>>> loop so I get a breakpoint hit.
>>> And using the debugger i set that global variable to 1
>>
>> Attaching the debugger soon enough isn't a problem. The problem is
>> that when an interrupt occurs (like a division by zero), the code that
>> gets executed isn't mine. And this code sets up a new stack and goes
>> into a fancy "while (1) {}”.
>
>
> You are building UEFI … So why can’t you build replacement library (or
> object file) that you can use for the purposes of debug? Then remove this
> later in production.
>
>
>>
>> I just found a solution that consists in setting a breakpoint directly
>> in the interrupt handler, before the stack is modified. But this is
>> definitely not as generic as examining another stack given its
>> address.
>>
>> Maybe what I did by setting $rip and $rsp was good but gdb had a cache
>> of the stack frame?

Turns out I just needed to set $rbp as well. However, this technique
wouldn't restore the value of the registers. But those are printed by
QEMU when it generates some exceptions like "Divide Error". So it
should be possible to restore all the instructions that gdb allow me
to access (unfortunately, very few special registers).

>>
>>>
>>> Step 3: I can now step out of this code :-) and back through the
>>> exception
>>> return
>>> 	Which will eventually land me back in the offending location.
>>
>> What do you call "the exception return”?
>
> The structure of an exception handler is normally this:
>
> Entry:
> 	Step 1: Save special registers.
> 	Step 2: Establish *new* stack
> 	Step 3: Possibly get an exception code or reason number (i.e.: IRQ umber or
> TRAP number)
> 	Step 4: Call some handler function using the standard C calling protocol
> 	Step 5: Cleanup after function call
> 	Step 6: Go back to the original stack
> 	Step 7: Restore special registers
> 	Step 8: Perform the exception return instruction
>
> In your case, the “some handler” is effectively a “while(1) {}” loop - (step
> 4) and you have a breakpoint there.
>
> Your DIV0 or NULL POINTER access occurs and you hit the breakpoint
> 	
> My earlier example the while() loop would become:
>
> 1: volatile int variable;
> 2: some_handler(void)
> 3: {
> 4:	variable = 1;
> 5:	while( variable != 0 ){    }
> 6: }
>
> In my example, I would set the variable to 0, then continue to step,
> eventually I would step past line 6 and execute the function exit sequence.

Maybe the infinite loop in OVMF wasn't written in a facy way for
nothing after all.

VOID
EFIAPI
CpuDeadLoop (
  VOID
  )
{
  volatile UINTN  Index;

  for (Index = 0; Index == 0;);
}

Index is volatile, so I should be able to apply your technique as
well. I just tried and it works. Returning to the user code is just
not as trivial as it could be. I guess I could just put a breakpoint
on the iret instruction and automatically perform a "ni" command at
that point.

>
> Important: Write the offending address down, and keep repeating the
> experiment. Often you will see a common address or address range.
> If you do find a pattern then set up the hardware rd/wr breakpoint on that
> memory range.  It is no exact science, and you might have to do this a few
> times.

Well, in QEMU, my bugs are usually very repeatable.


Anyway, thanks for all the help.


Best regards,
Celelibi


  parent reply	other threads:[~2015-12-05 18:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-28  6:03 Celelibi
2015-11-28 13:37 ` Duane Ellis
2015-12-01  8:46   ` Celelibi
     [not found]     ` <863D4E7B-2D4E-448B-8B41-EE97612A3BA3@duaneellis.com>
2015-12-05 18:33       ` Celelibi [this message]
2015-11-30 16:28 ` Sterling Augustine
     [not found] ` <CAEG7qUxk2qKo4RM9syqco26EtQkeiviP3GOrHkqyJJViwAX3dQ@mail.gmail.com>
2015-12-01  8:57   ` Celelibi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJR2zJ89vA=eTCfzga1dVHthVS3NZYPidu4Ptgu7OhFB=zyTSA@mail.gmail.com' \
    --to=celelibi@gmail.com \
    --cc=duane@duaneellis.com \
    --cc=gdb@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox