public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <andrew.burgess@embecosm.com>
To: Jim Wilson <jimw@sifive.com>
Cc: gdb-patches@sourceware.org, Palmer Dabbelt <palmer@sifive.com>,
	John Baldwin <jhb@freebsd.org>
Subject: Re: [PATCH 1/2] gdb/riscv: Stop prologue scan if instruction fetch/decode fails
Date: Tue, 06 Nov 2018 11:18:00 -0000	[thread overview]
Message-ID: <20181106111845.GI16539@embecosm.com> (raw)
In-Reply-To: <CAFyWVabUfOuBZ09BbgMbUie5M96YOxfwUEbPJ32x-XsCu_Rq1A@mail.gmail.com>

Thanks for the feedback.

* Jim Wilson <jimw@sifive.com> [2018-11-05 15:37:13 -0800]:

> On Mon, Nov 5, 2018 at 3:10 PM Andrew Burgess
> <andrew.burgess@embecosm.com> wrote:
> > If the target has not yet had a program loaded into it, and the $pc
> > value is pointing an unreadable memory, then the prologue scan would
> > throw an error, this would then cause GDB to abandon its attempt to
> > connect to the target.  It was in fact impossible to connect to the
> > target at all.
> 
> In my case, with openocd/spike, the pc value is actually correct and
> there is a valid instruction there.  The problem rather happens in
> riscv_frame_cache which calls get_frame_func, and this returns 0
> because there is no program loaded yet.

You are right that my original explanation isn't quite right.  But I
think the real problem is not whether a program is loaded or not, it's
that GDB can't figure out the function start.  This of course is done
as I understand it by examining the program at GDB's end.  I'm not
sure why I even mention this to be honest, it's largely irrelevant...

>                                          This then causes a scan for
> the prologue to start at address zero, which is wrong, and leads to
> the null deref error that kills the connection.

Interesting, does it actually kill the connection for you?  I too am
testing against openocd/spike, and what I see is that GDB
disconnects, but the target is still running, and I can try to connect
again, and again, and again.....

We probably are seeing the same thing, I just want to make sure we're
not trying to fix different problems :)

>                                                  I have a simpler fix
> based on code I found in mips-tdep.c, which just returns from
> riscv_frame_cache if start_addr is zero, and also in
> riscv_frame_this_id we don't set this_id if the frame_base is zero.

We really shouldn't do that.  I've worked on too many embeded targets
where 0 is a valid address, and every time I hit a "zero is special"
case in GDB I die a little inside.

There certainly is plenty of such code in GDB, there shouldn't be, and
when I run into them, I do try to remove them.

> With your fix, riscv_scan_prologue will be run, the frame cache will
> be filled with incorrect values, and we will try to compute a frame id
> based on bad info.

Yeah, OK.  I don't think I see this as being as big a problem as you
do, the targets in an undefined state, we see undefined things.  I can
live with that.  I'm pretty sure that even with you special case zero
fix, you still see undefined state, its just that some of the value
are undefined to zero....  That said, I do agree a little that leaving
the frame cache partially initialised probably isn't that great.

>                     That doesn't look like the right solution to me.
> My patch is a slightly cleaned up version of the workarounds I sent to
> you last week, which I am testing now.

Sorry, I missed that patch, otherwise I would have replied.

The revised patch below achieves the result you would like (not
setting the frame id) but does so without special casing address
zero.  How do you feel about this?

Thanks,
Andrew

---

gdb/riscv: Handle errors while setting the frame id

When we connect to a remote target one of the first things GDB does is
establish a frame id.  If an error is thrown while building this frame
id then GDB will disconnect from the target.

This can mean that, if the user is attempting to connect to a target
that doesn't yet have a program loaded, or the program the user is
going to load onto the target doesn't match what is already loaded, or
the target is just in some undefined state, then the very first
request for a frame id can fail (for example, by trying to load from
an invalid memory address), and GDB will disconnect.  It is then
impossible for the user to connect to the target and load a new
program at all.

An example of such a session might look like this:

    Reading symbols from ./gdb/testsuite/outputs/gdb.arch/riscv-reg-aliases/riscv-reg-aliases...
    (gdb) target remote :37191
    Remote debugging using :37191
    0x0000000000000100 in ?? ()
    Cannot access memory at address 0x0
    (gdb) load
    You can't do that when your target is `exec'
    (gdb) info frame
    /path/to/gdb/gdb/thread.c:93: internal-error: thread_info* inferior_thread(): Assertion `tp' failed.
    A problem internal to GDB has been detected,
    further debugging may prove unreliable.
    Quit this debugging session? (y or n)

The solution is to handle errors in riscv_frame_this_id, and leave the
this_id variable with its default value, which is the predefined
'outermost' frame.

With this fix in place, connecting to the same target now looks like
this:

    (gdb) target remote :37191
    Remote debugging using :37191
    0x0000000000000100 in ?? ()
    (gdb) info frame
    Stack level 0, frame at 0x0:
     pc = 0x100; saved pc = <not saved>
     Outermost frame: outermost
     Arglist at unknown address.
     Locals at unknown address, Previous frame's sp in sp

gdb/ChangeLog:

	* riscv-tdep.c (riscv_insn::decode): Update header comment.
	(riscv_frame_this_id): Catch errors thrown while building the
	frame cache, leave the frame id as the default, which is the outer
	frame id.
---
 gdb/ChangeLog    |  7 +++++++
 gdb/riscv-tdep.c | 17 ++++++++++++++---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index db372e21632..7a92fc7fae5 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -1256,7 +1256,9 @@ riscv_insn::fetch_instruction (struct gdbarch *gdbarch,
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
-/* Fetch from target memory an instruction at PC and decode it.  */
+/* Fetch from target memory an instruction at PC and decode it.  This can
+   throw an error if the memory access fails, callers are responsible for
+   handling this error if that is appropriate.  */
 
 void
 riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -2752,8 +2754,17 @@ riscv_frame_this_id (struct frame_info *this_frame,
 {
   struct riscv_unwind_cache *cache;
 
-  cache = riscv_frame_cache (this_frame, prologue_cache);
-  *this_id = cache->this_id;
+  TRY
+    {
+      cache = riscv_frame_cache (this_frame, prologue_cache);
+      *this_id = cache->this_id;
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      /* Ignore errors, this leaves the frame id as the predefined outer
+         frame id which terminates the backtrace at this point.  */
+    }
+  END_CATCH
 }
 
 /* Implement the prev_register callback for RiscV frame unwinder.  */
-- 
2.14.5

  reply	other threads:[~2018-11-06 11:18 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-05 23:10 [PATCH 0/2] RISC-V Prologue Scan And Test Improvement Andrew Burgess
2018-11-05 23:10 ` [PATCH 2/2] gdb/riscv: Update test to support targets without FP hardware Andrew Burgess
2018-11-05 23:10 ` [PATCH 1/2] gdb/riscv: Stop prologue scan if instruction fetch/decode fails Andrew Burgess
2018-11-05 23:37   ` Jim Wilson
2018-11-06 11:18     ` Andrew Burgess [this message]
2018-11-06 19:40       ` Jim Wilson

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=20181106111845.GI16539@embecosm.com \
    --to=andrew.burgess@embecosm.com \
    --cc=gdb-patches@sourceware.org \
    --cc=jhb@freebsd.org \
    --cc=jimw@sifive.com \
    --cc=palmer@sifive.com \
    /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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).