diff options
author | Andrew Burgess <aburgess@redhat.com> | 2022-04-04 15:48:19 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2022-06-15 09:44:55 +0100 |
commit | 8b39b1e7ab20609ced6a224cae440f19e6ae02c1 (patch) | |
tree | 015e347bb39704d9424f3068c1ea372146d90b48 /gdb/disasm.h | |
parent | 15e15b2d9cd3b1db68f99cd3b047352142ddfd1c (diff) | |
download | fsf-binutils-gdb-8b39b1e7ab20609ced6a224cae440f19e6ae02c1.zip fsf-binutils-gdb-8b39b1e7ab20609ced6a224cae440f19e6ae02c1.tar.gz fsf-binutils-gdb-8b39b1e7ab20609ced6a224cae440f19e6ae02c1.tar.bz2 |
gdb: refactor the non-printing disassemblers
This commit started from an observation I made while working on some
other disassembler patches, that is, that the function
gdb_buffered_insn_length, is broken ... sort of.
I noticed that the gdb_buffered_insn_length function doesn't set up
the application data field if the disassemble_info structure.
Further, I noticed that some architectures, for example, ARM, require
that the application_data field be set, see gdb_print_insn_arm in
arm-tdep.c.
And so, if we ever use gdb_buffered_insn_length for ARM, then GDB will
likely crash. Which is why I said only "sort of" broken. Right now
we don't use gdb_buffered_insn_length with ARM, so maybe it isn't
broken yet?
Anyway to prove to myself that there was a problem here I extended the
disassembler self tests in disasm-selftests.c to include a test of
gdb_buffered_insn_length. As I run the test for all architectures, I
do indeed see GDB crash for ARM.
To fix this we need gdb_buffered_insn_length to create a disassembler
that inherits from gdb_disassemble_info, but we also need this new
disassembler to not print anything.
And so, I introduce a new gdb_non_printing_disassembler class, this is
a disassembler that doesn't print anything to the output stream.
I then observed that both ARC and S12Z also create non-printing
disassemblers, but these are slightly different. While the
disassembler in gdb_non_printing_disassembler reads the instruction
from a buffer, the ARC and S12Z disassemblers read from target memory
using target_read_code.
And so, I further split gdb_non_printing_disassembler into two
sub-classes, gdb_non_printing_memory_disassembler and
gdb_non_printing_buffer_disassembler.
The new selftests now pass, but otherwise, there should be no user
visible changes after this commit.
Diffstat (limited to 'gdb/disasm.h')
-rw-r--r-- | gdb/disasm.h | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/gdb/disasm.h b/gdb/disasm.h index f31ca92..ec51203 100644 --- a/gdb/disasm.h +++ b/gdb/disasm.h @@ -136,6 +136,56 @@ protected: ATTRIBUTE_PRINTF(3,4); }; +/* A basic disassembler that doesn't actually print anything. */ + +struct gdb_non_printing_disassembler : public gdb_disassemble_info +{ + gdb_non_printing_disassembler (struct gdbarch *gdbarch, + read_memory_ftype read_memory_func) + : gdb_disassemble_info (gdbarch, nullptr /* stream */, + read_memory_func, + nullptr /* memory_error_func */, + nullptr /* print_address_func */, + null_fprintf_func, + null_fprintf_styled_func) + { /* Nothing. */ } + +private: + + /* Callback used as the disassemble_info's fprintf_func callback, this + doesn't write anything to STREAM, but just returns 0. */ + static int null_fprintf_func (void *stream, const char *format, ...) + ATTRIBUTE_PRINTF(2,3); + + /* Callback used as the disassemble_info's fprintf_styled_func callback, + , this doesn't write anything to STREAM, but just returns 0. */ + static int null_fprintf_styled_func (void *stream, + enum disassembler_style style, + const char *format, ...) + ATTRIBUTE_PRINTF(3,4); +}; + +/* A non-printing disassemble_info management class. The disassemble_info + setup by this class will not print anything to the output stream (there + is no output stream), and the instruction to be disassembled will be + read from target memory. */ + +struct gdb_non_printing_memory_disassembler + : public gdb_non_printing_disassembler +{ + /* Constructor. GDBARCH is the architecture to disassemble for. */ + gdb_non_printing_memory_disassembler (struct gdbarch *gdbarch) + :gdb_non_printing_disassembler (gdbarch, dis_asm_read_memory) + { /* Nothing. */ } + +private: + + /* Implements the read_memory_func disassemble_info callback. */ + static int dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, + unsigned int len, + struct disassemble_info *info); +}; + /* A dissassembler class that provides 'print_insn', a method for disassembling a single instruction to the output stream. */ @@ -278,10 +328,4 @@ extern char *get_disassembler_options (struct gdbarch *gdbarch); extern void set_disassembler_options (const char *options); -/* Setup DINFO with its output function and output stream setup so that - nothing is printed while disassembling. */ - -extern void init_disassemble_info_for_no_printing - (struct disassemble_info *dinfo); - #endif |