diff options
author | Yao Qi <yao.qi@linaro.org> | 2017-01-20 13:00:52 +0000 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2017-01-20 13:00:52 +0000 |
commit | e2285602341fff057a9b4687b465a9d9cde1303f (patch) | |
tree | 8269c44fdad73dc84753deededa8e43eb5b9d8c8 | |
parent | c3766ac6f9231f00ff3fda0e36b176ba44d16f5b (diff) | |
download | gdb-e2285602341fff057a9b4687b465a9d9cde1303f.zip gdb-e2285602341fff057a9b4687b465a9d9cde1303f.tar.gz gdb-e2285602341fff057a9b4687b465a9d9cde1303f.tar.bz2 |
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.
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/disasm.c | 66 | ||||
-rw-r--r-- | gdb/disasm.h | 6 | ||||
-rw-r--r-- | gdb/event-top.c | 8 | ||||
-rw-r--r-- | gdb/exceptions.h | 8 | ||||
-rw-r--r-- | 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) { |