From patchwork Wed Jan 18 16:52:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 18943 Received: (qmail 83368 invoked by alias); 18 Jan 2017 16:52:29 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 83334 invoked by uid 89); 18 Jan 2017 16:52:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=VMA, vma, Throw, *uiout X-HELO: mail-pg0-f65.google.com Received: from mail-pg0-f65.google.com (HELO mail-pg0-f65.google.com) (74.125.83.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 18 Jan 2017 16:52:18 +0000 Received: by mail-pg0-f65.google.com with SMTP id t6so1801661pgt.1 for ; Wed, 18 Jan 2017 08:52:18 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=B+UDT/q6F8VAOdEULVqFV4qokNZvVWS4Oyni5YjoJ4s=; b=KqDivFRC22nd7unVI3cX3v6ky/NB/uIpuMPhWLUZwD94vr+9mUlqEQn4rf4WBLNDto h/dFzg0ey20Yc04d2C9MsFNdQd/kQzpq7JA7sjb+14FkO2OmM9OqsLksfkk85BMoPPa2 gtkm+jgqWdrSyJl6yKgGLxx68vWzBM8fFtb7z1j2na7Ilv+a9iEjRnBF61sP6nqwVqFv 9vrdpBaZb6cO7h6/cGXJLMyj9TFpp4vrwza0L2G/fWBW7/WLtTkVwv4V7yUVyvoDqmGW nRwMhfp4RKtN+RMky4mBcGqVWKNI8KRhK5Xr8gIWB/30ZKEs276P2iJv6GZvuDKxfJNF +QTw== X-Gm-Message-State: AIkVDXL/NL2FpiRBa8sz1Pg0fzFRWnPQRvRIUjC2efaHWDr+M3fPcp5PyN+PmCHemcn+ag== X-Received: by 10.98.70.12 with SMTP id t12mr4862831pfa.47.1484758336459; Wed, 18 Jan 2017 08:52:16 -0800 (PST) Received: from E107787-LIN.cambridge.arm.com (gcc1-power7.osuosl.org. [140.211.15.137]) by smtp.gmail.com with ESMTPSA id t15sm2047081pgn.18.2017.01.18.08.52.15 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Jan 2017 08:52:16 -0800 (PST) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 7.12] Throw SJ/LJ exception on error in disassembly Date: Wed, 18 Jan 2017 16:52:03 +0000 Message-Id: <1484758323-5467-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes 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 in 7.12 branch 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-18 Yao Qi * 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. --- gdb/disasm.c | 66 ++++++++++++++++++++++++++++++++++++++++++++------ gdb/disasm.h | 6 +++++ gdb/event-top.c | 8 ------ gdb/exceptions.h | 8 ++++++ gdb/guile/scm-disasm.c | 15 +----------- 5 files changed, 74 insertions(+), 29 deletions(-) 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) {