Bug 20939 - GDB aborts if there is an error in disassembly
Summary: GDB aborts if there is an error in disassembly
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 7.12.1
Assignee: Yao Qi
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-06 16:15 UTC by Yao Qi
Modified: 2017-01-26 22:22 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yao Qi 2016-12-06 16:15:05 UTC
(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

This can be reproduced on aarch64-linux and ppc64-linux.

#0  __GI_abort () at abort.c:51
#1  0x000000000076bd2c in __gnu_cxx::__verbose_terminate_handler() ()
#2  0x0000000000766794 in __cxxabiv1::__terminate(void (*)()) ()
#3  0x00000000007667dc in std::terminate() ()
#4  0x0000000000764848 in __cxa_throw ()
#5  0x000000000053e78c in throw_exception_cxx (exception=...) at ../../binutils-gdb/gdb/common/common-exceptions.c:303
#6  0x000000000053e840 in throw_exception (exception=...) at ../../binutils-gdb/gdb/common/common-exceptions.c:317
#7  throw_it (reason=reason@entry=RETURN_ERROR, error=MEMORY_ERROR, fmt=fmt@entry=0x85ec70 "%s", 
    ap=<error reading variable: Cannot access memory at address 0x474e5543432b2b00>) at ../../binutils-gdb/gdb/common/common-exceptions.c:373
#8  0x000000000053ea58 in throw_verror (error=<optimized out>, fmt=fmt@entry=0x85ec70 "%s", ap=<error reading variable: Cannot access memory at address 0x2>)
    at ../../binutils-gdb/gdb/common/common-exceptions.c:379
#9  0x000000000053eb04 in throw_error (error=<optimized out>, fmt=fmt@entry=0x85ec70 "%s") at ../../binutils-gdb/gdb/common/common-exceptions.c:394
#10 0x0000000000544228 in memory_error (err=TARGET_XFER_E_IO, memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:237
#11 0x00000000006b0a54 in print_insn_aarch64 (pc=0, info=0xffffffffeeb0) at ../../binutils-gdb/opcodes/aarch64-dis.c:3185
#12 0x0000000000553590 in gdb_pretty_print_insn (gdbarch=gdbarch@entry=0xbbceb0, uiout=uiout@entry=0xbc73d0, di=di@entry=0xffffffffeeb0, 
    insn=0xffffffffed40, insn@entry=0xffffffffed90, flags=flags@entry=0, stb=stb@entry=0xbd5100) at ../../binutils-gdb/gdb/disasm.c:276
#13 0x00000000005536c0 in dump_insns (gdbarch=0xbbceb0, gdbarch@entry=0x0, uiout=uiout@entry=0xbc73d0, di=0xffffffffeeb0, di@entry=0xffffffffef90, 
    low=low@entry=0, high=4, high@entry=0, how_many=-1, how_many@entry=0, flags=flags@entry=0, stb=0xbd5100, stb@entry=0x0, end_pc=end_pc@entry=0x0)
    at ../../binutils-gdb/gdb/disasm.c:303
#14 0x0000000000553f8c in do_assembly_only (stb=0x0, flags=0, how_many=0, high=0, low=0, di=0xffffffffef90, uiout=0xbc73d0, gdbarch=0x0)
    at ../../binutils-gdb/gdb/disasm.c:745
#15 gdb_disassembly (gdbarch=gdbarch@entry=0xbbceb0, uiout=0xbc73d0, file_string=file_string@entry=0x0, flags=flags@entry=0, how_many=0, how_many@entry=-1, 
    low=low@entry=0, high=0, high@entry=4) at ../../binutils-gdb/gdb/disasm.c:811
#16 0x0000000000485b08 in print_disassembly (gdbarch=0xbbceb0, name=<optimized out>, low=0, high=4, flags=0) at ../../binutils-gdb/gdb/cli/cli-cmds.c:1151
#17 0x00000000004868fc in print_disassembly (flags=0, high=4, low=0, name=0x0, gdbarch=0xbbceb0) at ../../binutils-gdb/gdb/cli/cli-cmds.c:1140
#18 disassemble_command (arg=<optimized out>, from_tty=<optimized out>) at ../../binutils-gdb/gdb/cli/cli-cmds.c:1303
#19 0x000000000048a2fc in cmd_func (cmd=0xaffcf0, args=0xbc967c "0x0,+4", from_tty=1) at ../../binutils-gdb/gdb/cli/cli-decode.c:1913

We need a fix similar to 89525768cd086a0798a504c81fdf7ebcd4c904e1
Comment 1 Yao Qi 2016-12-06 16:16:01 UTC
GDB 7.12 branch is affected too.
Comment 2 Yao Qi 2016-12-09 14:01:40 UTC
To be clear, "This can be reproduced on aarch64-linux and ppc64-linux." in the bug report, means the host rather than target.

This can be reproduced on native GDB on aarch64-linux and ppc64-linux host.
Comment 3 Yao Qi 2017-01-16 15:30:14 UTC
It is a regression.  GDB 7.11.1 works well (with --enable-build-with-cxx and without --enable-build-with-cxx) on aarch64-linux.

(gdb) disassemble 0x0,+4
Dump of assembler code from 0x0 to 0x4:
   0x0000000000000000:	Cannot access memory at address 0x0
Comment 4 Sourceware Commits 2017-01-20 13:04:00 UTC
The gdb-7.12-branch branch has been updated by Yao Qi <qiyao@sourceware.org>:

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.
Comment 5 Kevin Brodsky 2017-01-23 09:35:08 UTC
Great, thank you Yao!
Comment 6 Sourceware Commits 2017-01-26 14:38:21 UTC
The master branch has been updated by Yao Qi <qiyao@sourceware.org>:

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

commit d8b49cf0c891d09dd58de05ad5cfe396b612cf3b
Author: Yao Qi <yao.qi@linaro.org>
Date:   Thu Jan 26 14:29:20 2017 +0000

    Don't throw exception in dis_asm_memory_error
    
    Hi,
    GDB calls some APIs from opcodes to do disassembly and provide some
    call backs.  This model makes troubles on C++ exception unwinding,
    because GDB is a C++ program, and opcodes is still compiled as C.
    As we can see, frame #10 and #12 are C++, while #frame 11 is C,
    
     #10 0x0000000000544228 in memory_error (err=TARGET_XFER_E_IO, memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:237
     #11 0x00000000006b0a54 in print_insn_aarch64 (pc=0, info=0xffffffffeeb0) at ../../binutils-gdb/opcodes/aarch64-dis.c:3185
     #12 0x0000000000553590 in gdb_pretty_print_insn (gdbarch=gdbarch@entry=0xbbceb0, uiout=uiout@entry=0xbc73d0, di=di@entry=0xffffffffeeb0,
        insn=0xffffffffed40, insn@entry=0xffffffffed90, flags=flags@entry=0,
    
    C++ exception unwinder can't go across frame #11 unless it has
    unwind table.  However, C program on many architectures doesn't
    have it in default.  As a result, GDB aborts, which is described
    in PR 20939.
    
    This is not the first time we see this kind of problem.  We've
    had a commit 89525768cd086a0798a504c81fdf7ebcd4c904e1
    "Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH".
    We can fix the disassembly bug in a similar way, this is the option one.
    
    Since opcodes is built with gdb, we fix this problem in a different
    way as we did for the same issue with readline.  Instead of throwing
    exception in dis_asm_memory_error, we record the failed memory
    address, and throw exception when GDB returns from opcodes disassemblers.
    
    gdb:
    
    2017-01-26  Yao Qi  <yao.qi@linaro.org>
    	    Pedro Alves  <palves@redhat.com>
    
    	PR gdb/20939
    	* disasm.c (gdb_disassembler::dis_asm_memory_error): Don't
    	call memory_error, save memaddr instead.
    	(gdb_disassembler::print_insn): If gdbarch_print_insn returns
    	negative, cal memory_error.
    	* disasm.h (gdb_disassembler) <m_err_memaddr>: New field.
    
    gdb/testsuite:
    
    2017-01-26  Yao Qi  <yao.qi@linaro.org>
    
    	* gdb.base/all-architectures.exp.in (do_arch_tests): Test
    	disassemble on address 0.
Comment 7 Yao Qi 2017-01-26 22:22:03 UTC
It is fixed in master too.