This is the mail archive of the gdb-cvs@sourceware.org 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]

[binutils-gdb/gdb-7.12-branch] Throw SJ/LJ exception on error in disassembly


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e2285602341fff057a9b4687b465a9d9cde1303f

commit e2285602341fff057a9b4687b465a9d9cde1303f
Author: Yao Qi <yao.qi@linaro.org>
Date:   Fri Jan 20 13:00:52 2017 +0000

    Throw SJ/LJ exception on error in disassembly
    
    PR 20939 reports that GDB will abort on memory error in disassembly,
    
    (gdb) disassemble 0x0,+4
    Dump of assembler code from 0x0 to 0x4:
    terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
       0x0000000000000000:	Aborted
    
    (gdb) guile (print (arch-disassemble arch 0 #:size 4))^M
    terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'^M
    ERROR: Process no longer exists
    
    This patch fixes PR 20939 by catching C++ exception, throwing SJ/LJ
    exception in the call back passed to C functions of opcodes, and
    catching SJ/LJ exception in gdb, and throw exception.
    
    The patch follows this commit
    
     89525768cd086a0798a504c81fdf7ebcd4c904e1
     Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH
    
    rather than "backport" the fix to this PR I posted for mainline
    https://sourceware.org/ml/gdb-patches/2017-01/msg00288.html because the
    fix for mainline includes 1) some changes to opcodes, 2) some refactors
    in C++.  All of them are risky to backport to 7.12 branch.
    
    With this patch applied to 7.12 branch, GDB doesn't abort on memory error
    in disassembly.  It fixes some test failures in gdb.guile/scm-disasm.exp
    and gdb.python/py-arch.exp on aarch64-linux.
    
    -ERROR: Process no longer exists
    -UNRESOLVED: gdb.guile/scm-disasm.exp: test bad memory access
    +PASS: gdb.guile/scm-disasm.exp: test bad memory access
    
    -ERROR: Process no longer exists
    -UNRESOLVED: gdb.python/py-arch.exp: test bad memory access
    +PASS: gdb.python/py-arch.exp: test bad memory access
    
    I'll add the scm-disasm test to master later.
    
    gdb:
    
    2017-01-20  Yao Qi  <yao.qi@linaro.org>
    
    	PR gdb/20939
    	* disasm.c (dis_asm_memory_error): Catch the error and rethrow
    	it as a SJ/LJ exception.  Add GDB_NOEXCEPT.
    	(disasm_print_insn_noexcept): New function.
    	(disasm_print_insn): New function.
    	(gdb_pretty_print_insn): Call disasm_print_insn instead of
    	gdbarch_print_insn.
    	(gdb_print_insn): Likewise.
    	(gdb_buffered_insn_length): Likewise.
    	* event-top.c (GDB_NOEXCEPT): Move it to ...
    	* exceptions.h (GDB_NOEXCEPT): ... here.
    	* guile/scm-disasm.c (gdbscm_disasm_memory_error): Remove.
    	(gdbscm_print_insn_from_port): Don't set di.memory_errro_func.
    	Call disasm_print_insn rather than gdbarch_print_insn.

Diff:
---
 gdb/ChangeLog          | 17 +++++++++++++
 gdb/disasm.c           | 66 ++++++++++++++++++++++++++++++++++++++++++++------
 gdb/disasm.h           |  6 +++++
 gdb/event-top.c        |  8 ------
 gdb/exceptions.h       |  8 ++++++
 gdb/guile/scm-disasm.c | 15 +-----------
 6 files changed, 91 insertions(+), 29 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 397dbae..e769b9b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2017-01-20  Yao Qi  <yao.qi@linaro.org>
+
+	PR gdb/20939
+	* disasm.c (dis_asm_memory_error): Catch the error and rethrow
+	it as a SJ/LJ exception.  Add GDB_NOEXCEPT.
+	(disasm_print_insn_noexcept): New function.
+	(disasm_print_insn): New function.
+	(gdb_pretty_print_insn): Call disasm_print_insn instead of
+	gdbarch_print_insn.
+	(gdb_print_insn): Likewise.
+	(gdb_buffered_insn_length): Likewise.
+	* event-top.c (GDB_NOEXCEPT): Move it to ...
+	* exceptions.h (GDB_NOEXCEPT): ... here.
+	* guile/scm-disasm.c (gdbscm_disasm_memory_error): Remove.
+	(gdbscm_print_insn_from_port): Don't set di.memory_errro_func.
+	Call disasm_print_insn rather than gdbarch_print_insn.
+
 2017-01-12  Tom Tromey  <tom@tromey.com>
 
 	* python/py-framefilter.c (py_print_frame): Use
diff --git a/gdb/disasm.c b/gdb/disasm.c
index a3fc9aa..f041be3 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -126,12 +126,25 @@ dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
   return target_read_code (memaddr, myaddr, len);
 }
 
-/* Like memory_error with slightly different parameters.  */
+/* Like memory_error with slightly different parameters, but it longjmp
+   out of the opcodes callback.  */
 static void
 dis_asm_memory_error (int err, bfd_vma memaddr,
-		      struct disassemble_info *info)
+		      struct disassemble_info *info) GDB_NOEXCEPT
 {
-  memory_error (TARGET_XFER_E_IO, memaddr);
+  struct gdb_exception exception = exception_none;
+
+  TRY
+    {
+      memory_error (TARGET_XFER_E_IO, memaddr);
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      exception = ex;
+    }
+  END_CATCH
+
+  throw_exception_sjlj (exception);
 }
 
 /* Like print_address with slightly different parameters.  */
@@ -143,6 +156,45 @@ dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
   print_address (gdbarch, addr, (struct ui_file *) info->stream);
 }
 
+/* Wrapper of gdbarch_print_insn, save its return value in *LEN if no
+   exception is thrown out of gdbarch_print_insn.  */
+
+static struct gdb_exception
+disasm_print_insn_noexcept (struct gdbarch *gdbarch, bfd_vma vma,
+			    struct disassemble_info *info,
+			    int *len) GDB_NOEXCEPT
+{
+  struct gdb_exception gdb_expt = exception_none;
+
+  TRY_SJLJ
+    {
+      *len = gdbarch_print_insn (gdbarch, vma, info);
+    }
+  CATCH_SJLJ (ex, RETURN_MASK_ALL)
+    {
+      gdb_expt = ex;
+    }
+  END_CATCH_SJLJ
+
+  return gdb_expt;
+}
+
+int
+disasm_print_insn (struct gdbarch *gdbarch, bfd_vma vma,
+		   struct disassemble_info *info)
+{
+  int len;
+
+  struct gdb_exception gdb_expt
+    = disasm_print_insn_noexcept (gdbarch, vma, info, &len);
+
+  /* Rethrow using the normal EH mechanism.  */
+  if (gdb_expt.reason < 0)
+    throw_exception (gdb_expt);
+
+  return len;
+}
+
 static int
 compare_lines (const void *mle1p, const void *mle2p)
 {
@@ -253,7 +305,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
       struct cleanup *cleanups =
 	make_cleanup_ui_file_delete (opcode_stream);
 
-      size = gdbarch_print_insn (gdbarch, pc, di);
+      size = disasm_print_insn (gdbarch, pc, di);
       end_pc = pc + size;
 
       for (;pc < end_pc; ++pc)
@@ -272,7 +324,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
       do_cleanups (cleanups);
     }
   else
-    size = gdbarch_print_insn (gdbarch, pc, di);
+    size = disasm_print_insn (gdbarch, pc, di);
 
   ui_out_field_stream (uiout, "inst", stb);
   ui_file_rewind (stb);
@@ -833,7 +885,7 @@ gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
   int length;
 
   di = gdb_disassemble_info (gdbarch, stream);
-  length = gdbarch_print_insn (gdbarch, memaddr, &di);
+  length = disasm_print_insn (gdbarch, memaddr, &di);
   if (branch_delay_insns)
     {
       if (di.insn_info_valid)
@@ -914,5 +966,5 @@ gdb_buffered_insn_length (struct gdbarch *gdbarch,
 
   gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
 
-  return gdbarch_print_insn (gdbarch, addr, &di);
+  return disasm_print_insn (gdbarch, addr, &di);
 }
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 4c6fd54..3898b12 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -83,4 +83,10 @@ extern int gdb_buffered_insn_length (struct gdbarch *gdbarch,
 				     const gdb_byte *insn, int max_len,
 				     CORE_ADDR memaddr);
 
+/* Print the instruction at address VMA.   Returns the length of the
+   instruction in bytes.  */
+
+extern int disasm_print_insn (struct gdbarch *gdbarch, bfd_vma vma,
+			      struct disassemble_info *info);
+
 #endif
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 279c7f2..53055de 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -73,14 +73,6 @@ static void async_stop_sig (gdb_client_data);
 #endif
 static void async_sigterm_handler (gdb_client_data arg);
 
-#ifndef __cplusplus
-# define GDB_NOEXCEPT
-#elif __cplusplus < 201103L
-# define GDB_NOEXCEPT throw ()
-#else
-# define GDB_NOEXCEPT noexcept
-#endif
-
 /* Instead of invoking (and waiting for) readline to read the command
    line and pass it back for processing, we use readline's alternate
    interface, via callback functions, so that the event loop can react
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index 29edbb1..2aecdce 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -88,4 +88,12 @@ extern int catch_exceptions_with_msg (struct ui_out *uiout,
 typedef int (catch_errors_ftype) (void *);
 extern int catch_errors (catch_errors_ftype *, void *, char *, return_mask);
 
+#ifndef __cplusplus
+# define GDB_NOEXCEPT
+#elif __cplusplus < 201103L
+# define GDB_NOEXCEPT throw ()
+#else
+# define GDB_NOEXCEPT noexcept
+#endif
+
 #endif
diff --git a/gdb/guile/scm-disasm.c b/gdb/guile/scm-disasm.c
index 64e9558..b66aa5d 100644
--- a/gdb/guile/scm-disasm.c
+++ b/gdb/guile/scm-disasm.c
@@ -123,18 +123,6 @@ gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
   return status != NULL ? -1 : 0;
 }
 
-/* disassemble_info.memory_error_func for gdbscm_print_insn_from_port.
-   Technically speaking, we don't need our own memory_error_func,
-   but to not provide one would leave a subtle dependency in the code.
-   This function exists to keep a clear boundary.  */
-
-static void
-gdbscm_disasm_memory_error (int status, bfd_vma memaddr,
-			    struct disassemble_info *info)
-{
-  memory_error (TARGET_XFER_E_IO, memaddr);
-}
-
 /* disassemble_info.print_address_func for gdbscm_print_insn_from_port.
    Since we need to use our own application_data value, we need to supply
    this routine as well.  */
@@ -174,10 +162,9 @@ gdbscm_print_insn_from_port (struct gdbarch *gdbarch,
   data.offset = offset;
   di.application_data = &data;
   di.read_memory_func = gdbscm_disasm_read_memory;
-  di.memory_error_func = gdbscm_disasm_memory_error;
   di.print_address_func = gdbscm_disasm_print_address;
 
-  length = gdbarch_print_insn (gdbarch, memaddr, &di);
+  length = disasm_print_insn (gdbarch, memaddr, &di);
 
   if (branch_delay_insns)
     {


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