This is the mail archive of the mailing list for the GDB project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/2] gdb/riscv: Stop prologue scan if instruction fetch/decode fails

If an error is thrown from the instruction fetch/decode during a
prologue scan then we should stop the prologue scan at that point
rather than propagating the error.

Propagating the error out of the prologue scan was causing unwanted
behaviour when connecting to a remote target.  When connecting to a
remote target GDB will read the $pc value from the target and try to
establish a frame-id, this can involve a prologue scan.

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.

With this patch in place GDB simply stops the prologue scan at the
point of the error, and GDB can now successfully connect.

I did consider placing the error catch within riscv_insn::decode
however, in the end I felt that catching and ignoring errors should be
done on a case by case basis, the other users of riscv_insn::decode
are currently all related to finding the next pc as part of software
single step.  If the user asks for a step and the contents of $pc
can't be read then if feels like terminating that command with an
error is the right thing to do.


	* riscv-tdep.c (riscv_insn::decode): Update header comment.
	(riscv_scan_prologue): Catch errors thrown from
	riscv_insn::decode and stop prologue scan.
 gdb/ChangeLog    |  6 ++++++
 gdb/riscv-tdep.c | 27 ++++++++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index db372e21632..aae93ea2fac 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.  */
 riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -1427,10 +1429,29 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
   for (next_pc = cur_pc = start_pc; cur_pc < end_pc; cur_pc = next_pc)
       struct riscv_insn insn;
+      bool decode_valid = false;
       /* Decode the current instruction, and decide where the next
-	 instruction lives based on the size of this instruction.  */
-      insn.decode (gdbarch, cur_pc);
+	 instruction lives based on the size of this instruction.  If the
+	 decode (which includes fetching from memory) fails then we stop
+	 the prologue scan at this point.  */
+      TRY
+	{
+	  insn.decode (gdbarch, cur_pc);
+	  decode_valid = true;
+	}
+	{
+	  /* Ignore errors.  */
+	}
+      END_CATCH
+      if (!decode_valid)
+	{
+	  end_prologue_addr = cur_pc;
+	  break;
+	}
       gdb_assert (insn.length () > 0);
       next_pc = cur_pc + insn.length ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]