From: Richard Henderson <rth@twiddle.net>
To: "Maciej W. Rozycki" <macro@codesourcery.com>
Cc: qemu-devel@nongnu.org, Aurelien Jarno <aurelien@aurel32.net>
Subject: Re: [Qemu-devel] [PATCH] MIPS: Correct branch-likely single-stepping
Date: Tue, 12 Jun 2012 07:55:07 -0700 [thread overview]
Message-ID: <4FD7584B.2080908@twiddle.net> (raw)
In-Reply-To: <alpine.DEB.1.10.1206072353260.23962@tp.orcam.me.uk>
On 2012-06-07 18:05, Maciej W. Rozycki wrote:
> From: Nathan Froyd <froydnj@codesourcery.com>
>
> We have a problem with single-stepping branch-likely instructions.
> Here's Nathan's original note:
>
> "[This] is a problem with single-stepping in QEMU: it manifests as
> the program corrupting the register set--specifically the return
> address--and going into an infinite loop. The problem is that we were
> not correctly saving state when single-stepping over branch likely
> instructions. In the program, we had this sequence:
>
> 0x8000b328: bnezl v0,0x8000b318
> 0x8000b32c: lw v0,0(s1) # branch delay slot
> 0x8000b330: lw ra,28(sp)
>
> The cause of the problem was the QEMU sets a flag in its internal
> translation state indicating that we had previously translated a branch
> likely instruction. When we generated the "skip over instruction" for a
> not-taken branch, this flag was not correctly cleared for the beginning
> of the next translation block. The result was that we skipped the
> instruction at 0x8000b32c (good) *and* the instruction at 0x8000b330
> (bad). $ra therefore never got restored."
>
> I have verified the problem is still there, here's a relevant raw GDB
> session (addresses are different, but code is essentially the same):
>
> (gdb) continue
> Continuing.
>
> Breakpoint 2, 0x8000b460 in __libc_init_array ()
> 4: /x $ra = 0x8000b460
> 2: x/i $pc
> => 0x8000b460 <__libc_init_array+124>: sltu v0,s0,s2
> (gdb) stepi
> 0x8000b464 in __libc_init_array ()
> 4: /x $ra = 0x8000b460
> 2: x/i $pc
> => 0x8000b464 <__libc_init_array+128>:
> bnezl v0,0x8000b454 <__libc_init_array+112>
> 0x8000b468 <__libc_init_array+132>: lw v0,0(s1)
> (gdb)
> 0x8000b46c in __libc_init_array ()
> 4: /x $ra = 0x8000b460
> 2: x/i $pc
> => 0x8000b46c <__libc_init_array+136>: lw ra,28(sp)
> (gdb)
> 0x8000b470 in __libc_init_array ()
> 4: /x $ra = 0x8000b460
> 2: x/i $pc
> => 0x8000b470 <__libc_init_array+140>: lw s2,24(sp)
> (gdb)
>
> -- oops! -- $ra still the same! Fixed with Nathan's change:
What about this comment, from the main body of gen_intermediate_code_internal:
/* Execute a branch and its delay slot as a single instruction.
This is what GDB expects and is consistent with what the
hardware does (e.g. if a delay slot instruction faults, the
reported PC is the PC of the branch). */
if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
break;
That suggests we should not have split the lw away from the bnezl in
the first place, and thus the fix should be elsewhere.
Even failing that, this
> tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
> + /* Fake saving hflags so that gen_goto_tb doesn't overwrite the
> + * hflags we saved above. */
> + saved_hflags = ctx->saved_hflags;
> + ctx->saved_hflags = ctx->hflags;
> gen_goto_tb(ctx, 1, ctx->pc + 4);
> + ctx->saved_hflags = saved_hflags;
seems needlessly convoluted. Does anyone think that
/* Save and restore the state we're currently in (inside a branch-likely delay),
while clearing that state as we exit the current TB. */
temp_sh = ctx->saved_hflags;
temp_h = ctx->hflags;
ctx->hflags &= ~MIPS_HFLAG_BMASK;
gen_goto_tb(...)
ctx->saved_hflags = temp_sh;
ctx->hflags = temp_h;
is any clearer? I.e. let gen_goto_tb do what it so very much wants to do, which
is save hflags to env on the way out.
r~
next prev parent reply other threads:[~2012-06-12 14:55 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-08 1:05 [Qemu-devel] [PATCH] MIPS: Correct branch-likely single-stepping Maciej W. Rozycki
2012-06-12 14:55 ` Richard Henderson [this message]
2014-12-13 2:34 ` [Qemu-devel] [PATCH v2] " Maciej W. Rozycki
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=4FD7584B.2080908@twiddle.net \
--to=rth@twiddle.net \
--cc=aurelien@aurel32.net \
--cc=macro@codesourcery.com \
--cc=qemu-devel@nongnu.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.