Skip to content

Commit

Permalink
Don't throw exception in dis_asm_memory_error
Browse files Browse the repository at this point in the history
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 8952576
"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  <[email protected]>
	    Pedro Alves  <[email protected]>

	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  <[email protected]>

	* gdb.base/all-architectures.exp.in (do_arch_tests): Test
	disassemble on address 0.
  • Loading branch information
Yao Qi committed Jan 26, 2017
1 parent 658ca58 commit d8b49cf
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 2 deletions.
10 changes: 10 additions & 0 deletions gdb/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2017-01-26 Yao Qi <[email protected]>
Pedro Alves <[email protected]>

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.

2017-01-26 Yao Qi <[email protected]>

* disasm-selftests.c (memory_error_test): New function.
Expand Down
13 changes: 11 additions & 2 deletions gdb/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@ void
gdb_disassembler::dis_asm_memory_error (int err, bfd_vma memaddr,
struct disassemble_info *info)
{
memory_error (TARGET_XFER_E_IO, memaddr);
gdb_disassembler *self
= static_cast<gdb_disassembler *>(info->application_data);

self->m_err_memaddr = memaddr;
}

/* Wrapper of print_address. */
Expand Down Expand Up @@ -765,7 +768,8 @@ fprintf_disasm (void *stream, const char *format, ...)
gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
struct ui_file *file,
di_read_memory_ftype read_memory_func)
: m_gdbarch (gdbarch)
: m_gdbarch (gdbarch),
m_err_memaddr (0)
{
init_disassemble_info (&m_di, file, fprintf_disasm);
m_di.flavour = bfd_target_unknown_flavour;
Expand All @@ -792,8 +796,13 @@ int
gdb_disassembler::print_insn (CORE_ADDR memaddr,
int *branch_delay_insns)
{
m_err_memaddr = 0;

int length = gdbarch_print_insn (arch (), memaddr, &m_di);

if (length < 0)
memory_error (TARGET_XFER_E_IO, m_err_memaddr);

if (branch_delay_insns != NULL)
{
if (m_di.insn_info_valid)
Expand Down
1 change: 1 addition & 0 deletions gdb/disasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class gdb_disassembler
/* Stores data required for disassembling instructions in
opcodes. */
struct disassemble_info m_di;
CORE_ADDR m_err_memaddr;

static int dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr,
unsigned int len,
Expand Down
5 changes: 5 additions & 0 deletions gdb/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2017-01-26 Yao Qi <[email protected]>

* gdb.base/all-architectures.exp.in (do_arch_tests): Test
disassemble on address 0.

2017-01-25 Andreas Arnez <[email protected]>
Yao Qi <[email protected]>

Expand Down
5 changes: 5 additions & 0 deletions gdb/testsuite/gdb.base/all-architectures.exp.in
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ proc print_floats {} {

proc do_arch_tests {} {
print_floats

# GDB can't access memory because there is no loaded executable
# nor live inferior.
gdb_test_internal "disassemble 0x0,+4" \
"Cannot access memory at address 0x0"
}

# Given we can't change arch, osabi, endianness, etc. atomically, we
Expand Down

0 comments on commit d8b49cf

Please sign in to comment.