Add more styling to "disassemble"
This adds more styling to the disassemble command. In particular, addresses and function names in the disassembly are now styled. This required fixing a small latent bug in set_output_style. This function always passed NULL to emit_style_escape; but when writing to a file other than gdb_stdout, it should emit the style escape directly. (FWIW this is another argument for better integrating the pager with ui_file and getting rid of this entire layer.) gdb/ChangeLog 2019-08-06 Tom Tromey <tom@tromey.com> * utils.c (set_output_style): Sometimes pass stream to emit_style_escape. * ui-out.h (class ui_out) <can_emit_style_escape>: Declare. * record-btrace.c (btrace_insn_history): Update. * mi/mi-out.h (class mi_ui_out) <can_emit_style_escape>: New method. * disasm.h (gdb_pretty_print_disassembler): Add uiout parameter. Update initializers. <m_uiout>: New field. <m_di>: Move lower. * disasm.c (gdb_pretty_print_disassembler::pretty_print_insn): Remove "uiout" parameter. (dump_insns): Update. * cli-out.h (class cli_ui_out) <can_emit_style_escape>: Declare. * cli-out.c (cli_ui_out::can_emit_style_escape): New method. gdb/testsuite/ChangeLog 2019-08-06 Tom Tromey <tom@tromey.com> * gdb.base/style.exp: Add disassemble test. * gdb.base/style.c (some_called_function): New function. (main): Use it.
This commit is contained in:
parent
ddbcedf5de
commit
046bebe1c0
@ -1,3 +1,21 @@
|
||||
2019-08-06 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* utils.c (set_output_style): Sometimes pass stream to
|
||||
emit_style_escape.
|
||||
* ui-out.h (class ui_out) <can_emit_style_escape>: Declare.
|
||||
* record-btrace.c (btrace_insn_history): Update.
|
||||
* mi/mi-out.h (class mi_ui_out) <can_emit_style_escape>: New
|
||||
method.
|
||||
* disasm.h (gdb_pretty_print_disassembler): Add uiout parameter.
|
||||
Update initializers.
|
||||
<m_uiout>: New field.
|
||||
<m_di>: Move lower.
|
||||
* disasm.c (gdb_pretty_print_disassembler::pretty_print_insn):
|
||||
Remove "uiout" parameter.
|
||||
(dump_insns): Update.
|
||||
* cli-out.h (class cli_ui_out) <can_emit_style_escape>: Declare.
|
||||
* cli-out.c (cli_ui_out::can_emit_style_escape): New method.
|
||||
|
||||
2019-08-06 Christian Biesinger <cbiesinger@google.com>
|
||||
|
||||
* symtab.c (symbol_cache_lookup): Change int to enum block_enum.
|
||||
|
@ -316,6 +316,12 @@ cli_ui_out::set_stream (struct ui_file *stream)
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
cli_ui_out::can_emit_style_escape () const
|
||||
{
|
||||
return m_streams.back ()->can_emit_style_escape ();
|
||||
}
|
||||
|
||||
/* CLI interface to display tab-completion matches. */
|
||||
|
||||
/* CLI version of displayer.crlf. */
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
|
||||
ui_file *set_stream (ui_file *stream);
|
||||
|
||||
bool can_emit_style_escape () const override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void do_table_begin (int nbrofcols, int nr_rows,
|
||||
|
49
gdb/disasm.c
49
gdb/disasm.c
@ -191,8 +191,7 @@ compare_lines (const void *mle1p, const void *mle2p)
|
||||
/* See disasm.h. */
|
||||
|
||||
int
|
||||
gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
|
||||
const struct disasm_insn *insn,
|
||||
gdb_pretty_print_disassembler::pretty_print_insn (const struct disasm_insn *insn,
|
||||
gdb_disassembly_flags flags)
|
||||
{
|
||||
/* parts of the symbolic representation of the address */
|
||||
@ -204,37 +203,37 @@ gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
|
||||
struct gdbarch *gdbarch = arch ();
|
||||
|
||||
{
|
||||
ui_out_emit_tuple tuple_emitter (uiout, NULL);
|
||||
ui_out_emit_tuple tuple_emitter (m_uiout, NULL);
|
||||
pc = insn->addr;
|
||||
|
||||
if (insn->number != 0)
|
||||
{
|
||||
uiout->field_unsigned ("insn-number", insn->number);
|
||||
uiout->text ("\t");
|
||||
m_uiout->field_unsigned ("insn-number", insn->number);
|
||||
m_uiout->text ("\t");
|
||||
}
|
||||
|
||||
if ((flags & DISASSEMBLY_SPECULATIVE) != 0)
|
||||
{
|
||||
if (insn->is_speculative)
|
||||
{
|
||||
uiout->field_string ("is-speculative", "?");
|
||||
m_uiout->field_string ("is-speculative", "?");
|
||||
|
||||
/* The speculative execution indication overwrites the first
|
||||
character of the PC prefix.
|
||||
We assume a PC prefix length of 3 characters. */
|
||||
if ((flags & DISASSEMBLY_OMIT_PC) == 0)
|
||||
uiout->text (pc_prefix (pc) + 1);
|
||||
m_uiout->text (pc_prefix (pc) + 1);
|
||||
else
|
||||
uiout->text (" ");
|
||||
m_uiout->text (" ");
|
||||
}
|
||||
else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
|
||||
uiout->text (pc_prefix (pc));
|
||||
m_uiout->text (pc_prefix (pc));
|
||||
else
|
||||
uiout->text (" ");
|
||||
m_uiout->text (" ");
|
||||
}
|
||||
else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
|
||||
uiout->text (pc_prefix (pc));
|
||||
uiout->field_core_addr ("address", gdbarch, pc);
|
||||
m_uiout->text (pc_prefix (pc));
|
||||
m_uiout->field_core_addr ("address", gdbarch, pc);
|
||||
|
||||
std::string name, filename;
|
||||
bool omit_fname = ((flags & DISASSEMBLY_OMIT_FNAME) != 0);
|
||||
@ -243,19 +242,19 @@ gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
|
||||
{
|
||||
/* We don't care now about line, filename and unmapped. But we might in
|
||||
the future. */
|
||||
uiout->text (" <");
|
||||
m_uiout->text (" <");
|
||||
if (!omit_fname)
|
||||
uiout->field_string ("func-name", name.c_str (),
|
||||
ui_out_style_kind::FUNCTION);
|
||||
m_uiout->field_string ("func-name", name.c_str (),
|
||||
ui_out_style_kind::FUNCTION);
|
||||
/* For negative offsets, avoid displaying them as +-N; the sign of
|
||||
the offset takes the place of the "+" here. */
|
||||
if (offset >= 0)
|
||||
uiout->text ("+");
|
||||
uiout->field_signed ("offset", offset);
|
||||
uiout->text (">:\t");
|
||||
m_uiout->text ("+");
|
||||
m_uiout->field_signed ("offset", offset);
|
||||
m_uiout->text (">:\t");
|
||||
}
|
||||
else
|
||||
uiout->text (":\t");
|
||||
m_uiout->text (":\t");
|
||||
|
||||
m_insn_stb.clear ();
|
||||
|
||||
@ -279,15 +278,15 @@ gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
|
||||
spacer = " ";
|
||||
}
|
||||
|
||||
uiout->field_stream ("opcodes", m_opcode_stb);
|
||||
uiout->text ("\t");
|
||||
m_uiout->field_stream ("opcodes", m_opcode_stb);
|
||||
m_uiout->text ("\t");
|
||||
}
|
||||
else
|
||||
size = m_di.print_insn (pc);
|
||||
|
||||
uiout->field_stream ("inst", m_insn_stb);
|
||||
m_uiout->field_stream ("inst", m_insn_stb);
|
||||
}
|
||||
uiout->text ("\n");
|
||||
m_uiout->text ("\n");
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -303,13 +302,13 @@ dump_insns (struct gdbarch *gdbarch,
|
||||
memset (&insn, 0, sizeof (insn));
|
||||
insn.addr = low;
|
||||
|
||||
gdb_pretty_print_disassembler disasm (gdbarch);
|
||||
gdb_pretty_print_disassembler disasm (gdbarch, uiout);
|
||||
|
||||
while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
|
||||
{
|
||||
int size;
|
||||
|
||||
size = disasm.pretty_print_insn (uiout, &insn, flags);
|
||||
size = disasm.pretty_print_insn (&insn, flags);
|
||||
if (size <= 0)
|
||||
break;
|
||||
|
||||
|
20
gdb/disasm.h
20
gdb/disasm.h
@ -112,26 +112,32 @@ extern int gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
|
||||
class gdb_pretty_print_disassembler
|
||||
{
|
||||
public:
|
||||
explicit gdb_pretty_print_disassembler (struct gdbarch *gdbarch)
|
||||
: m_di (gdbarch, &m_insn_stb)
|
||||
explicit gdb_pretty_print_disassembler (struct gdbarch *gdbarch,
|
||||
struct ui_out *uiout)
|
||||
: m_uiout (uiout),
|
||||
m_insn_stb (uiout->can_emit_style_escape ()),
|
||||
m_di (gdbarch, &m_insn_stb)
|
||||
{}
|
||||
|
||||
/* Prints the instruction INSN into UIOUT and returns the length of
|
||||
the printed instruction in bytes. */
|
||||
int pretty_print_insn (struct ui_out *uiout, const struct disasm_insn *insn,
|
||||
/* Prints the instruction INSN into the saved ui_out and returns the
|
||||
length of the printed instruction in bytes. */
|
||||
int pretty_print_insn (const struct disasm_insn *insn,
|
||||
gdb_disassembly_flags flags);
|
||||
|
||||
private:
|
||||
/* Returns the architecture used for disassembling. */
|
||||
struct gdbarch *arch () { return m_di.arch (); }
|
||||
|
||||
/* The disassembler used for instruction printing. */
|
||||
gdb_disassembler m_di;
|
||||
/* The ui_out that is used by pretty_print_insn. */
|
||||
struct ui_out *m_uiout;
|
||||
|
||||
/* The buffer used to build the instruction string. The
|
||||
disassembler is initialized with this stream. */
|
||||
string_file m_insn_stb;
|
||||
|
||||
/* The disassembler used for instruction printing. */
|
||||
gdb_disassembler m_di;
|
||||
|
||||
/* The buffer used to build the raw opcodes string. */
|
||||
string_file m_opcode_stb;
|
||||
};
|
||||
|
@ -40,6 +40,11 @@ public:
|
||||
/* Return the version number of the current MI. */
|
||||
int version ();
|
||||
|
||||
bool can_emit_style_escape () const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid)
|
||||
|
@ -778,7 +778,7 @@ btrace_insn_history (struct ui_out *uiout,
|
||||
gdb::optional<ui_out_emit_tuple> src_and_asm_tuple;
|
||||
gdb::optional<ui_out_emit_list> asm_list;
|
||||
|
||||
gdb_pretty_print_disassembler disasm (gdbarch);
|
||||
gdb_pretty_print_disassembler disasm (gdbarch, uiout);
|
||||
|
||||
for (btrace_insn_iterator it = *begin; btrace_insn_cmp (&it, end) != 0;
|
||||
btrace_insn_next (&it, 1))
|
||||
@ -841,7 +841,7 @@ btrace_insn_history (struct ui_out *uiout,
|
||||
if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
|
||||
dinsn.is_speculative = 1;
|
||||
|
||||
disasm.pretty_print_insn (uiout, &dinsn, flags);
|
||||
disasm.pretty_print_insn (&dinsn, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
2019-08-06 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdb.base/style.exp: Add disassemble test.
|
||||
* gdb.base/style.c (some_called_function): New function.
|
||||
(main): Use it.
|
||||
|
||||
2019-08-05 Christian Biesinger <cbiesinger@google.com>
|
||||
|
||||
* gdb.python/py-block.exp: Test dictionary access on blocks.
|
||||
|
@ -15,8 +15,13 @@
|
||||
|
||||
#define SOME_MACRO 23
|
||||
|
||||
int some_called_function (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
return 0; /* break here */
|
||||
return some_called_function (); /* break here */
|
||||
}
|
||||
|
@ -83,6 +83,10 @@ save_vars { env(TERM) } {
|
||||
"Defined at $base_file_expr:16\r\n#define SOME_MACRO 23"
|
||||
}
|
||||
|
||||
set func [style some_called_function function]
|
||||
# Somewhere should see the call to the function.
|
||||
gdb_test "disassemble main" "[style $hex address].*$func.*"
|
||||
|
||||
gdb_exit
|
||||
gdb_spawn
|
||||
|
||||
|
@ -145,6 +145,10 @@ class ui_out
|
||||
bool query_table_field (int colno, int *width, int *alignment,
|
||||
const char **col_name);
|
||||
|
||||
/* Return true if this stream is prepared to handle style
|
||||
escapes. */
|
||||
virtual bool can_emit_style_escape () const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid)
|
||||
|
@ -1442,9 +1442,11 @@ set_output_style (struct ui_file *stream, const ui_file_style &style)
|
||||
if (!stream->can_emit_style_escape ())
|
||||
return;
|
||||
|
||||
/* Note that we don't pass STREAM here, because we want to emit to
|
||||
/* Note that we may not pass STREAM here, when we want to emit to
|
||||
the wrap buffer, not directly to STREAM. */
|
||||
emit_style_escape (style);
|
||||
if (stream == gdb_stdout)
|
||||
stream = nullptr;
|
||||
emit_style_escape (style, stream);
|
||||
}
|
||||
|
||||
/* See utils.h. */
|
||||
|
Loading…
Reference in New Issue
Block a user