diff --git a/gdb/NEWS b/gdb/NEWS index 1178a37017e..742f4fe47fb 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -39,6 +39,12 @@ set width NUMBER set width unlimited +* Disassembler styling using libopcodes. GDB now supports + disassembler styling using libopcodes. This is only available for + some targets (currently x86 and RISC-V). For unsupported targets + Python Pygments is still used. For supported targets, libopcodes + styling is used by default. + * New commands maintenance set ignore-prologue-end-flag on|off @@ -53,6 +59,28 @@ show print nibbles This controls whether the 'print/t' command will display binary values in groups of four bits, known as "nibbles". The default is 'off'. +maintenance set libopcodes-styling on|off +maintenance show libopcodes-styling + These can be used to force off libopcodes based styling, the Python + Pygments styling will then be used instead. + +set style disassembler comment +show style disassembler comment +set style disassembler immediate +show style disassembler immediate +set style disassembler mnemonic +show style disassembler mnemonic +set style disassembler register +show style disassembler register +set style disassembler address +show style disassembler address +set style disassembler symbol +show style disassembler symbol + For targets that support libopcodes based styling, these settings + control how various aspects of the disassembler output are styled. + The 'disassembler address' and 'disassembler symbol' styles are + aliases for the 'address' and 'function' styles respectively. + * Changed commands maintenance info line-table diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c index 3fd85f4aa86..abf685561fa 100644 --- a/gdb/cli/cli-style.c +++ b/gdb/cli/cli-style.c @@ -110,6 +110,23 @@ cli_style_option version_style ("version", ui_file_style::MAGENTA, /* See cli-style.h. */ +cli_style_option disasm_mnemonic_style ("mnemonic", ui_file_style::GREEN); + +/* See cli-style.h. */ + +cli_style_option disasm_register_style ("register", ui_file_style::RED); + +/* See cli-style.h. */ + +cli_style_option disasm_immediate_style ("immediate", ui_file_style::BLUE); + +/* See cli-style.h. */ + +cli_style_option disasm_comment_style ("comment", ui_file_style::WHITE, + ui_file_style::DIM); + +/* See cli-style.h. */ + cli_style_option::cli_style_option (const char *name, ui_file_style::basic_color fg, ui_file_style::intensity intensity) @@ -224,15 +241,16 @@ cli_style_option::do_show_intensity (struct ui_file *file, int from_tty, /* See cli-style.h. */ -void +set_show_commands cli_style_option::add_setshow_commands (enum command_class theclass, const char *prefix_doc, struct cmd_list_element **set_list, struct cmd_list_element **show_list, bool skip_intensity) { - add_setshow_prefix_cmd (m_name, theclass, prefix_doc, prefix_doc, - &m_set_list, &m_show_list, set_list, show_list); + set_show_commands prefix_cmds + = add_setshow_prefix_cmd (m_name, theclass, prefix_doc, prefix_doc, + &m_set_list, &m_show_list, set_list, show_list); set_show_commands commands; @@ -274,6 +292,8 @@ cli_style_option::add_setshow_commands (enum command_class theclass, commands.set->set_context (this); commands.show->set_context (this); } + + return prefix_cmds; } static cmd_list_element *style_set_list; @@ -387,11 +407,13 @@ Configure filename colors and display intensity."), &style_set_list, &style_show_list, false); - function_name_style.add_setshow_commands (no_class, _("\ + set_show_commands function_prefix_cmds + = function_name_style.add_setshow_commands (no_class, _("\ Function name display styling.\n\ Configure function name colors and display intensity"), - &style_set_list, &style_show_list, - false); + &style_set_list, + &style_show_list, + false); variable_name_style.add_setshow_commands (no_class, _("\ Variable name display styling.\n\ @@ -399,11 +421,12 @@ Configure variable name colors and display intensity"), &style_set_list, &style_show_list, false); - address_style.add_setshow_commands (no_class, _("\ + set_show_commands address_prefix_cmds + = address_style.add_setshow_commands (no_class, _("\ Address display styling.\n\ Configure address colors and display intensity"), - &style_set_list, &style_show_list, - false); + &style_set_list, &style_show_list, + false); title_style.add_setshow_commands (no_class, _("\ Title display styling.\n\ @@ -451,4 +474,70 @@ Version string display styling.\n\ Configure colors used to display the GDB version string."), &style_set_list, &style_show_list, false); + + disasm_mnemonic_style.add_setshow_commands (no_class, _("\ +Disassembler mnemonic display styling.\n\ +Configure the colors and display intensity for instruction mnemonics\n\ +in the disassembler output. The \"disassembler mnemonic\" style is\n\ +used to display instruction mnemonics as well as any assembler\n\ +directives, e.g. \".byte\", \".word\", etc.\n\ +\n\ +This style will only be used for targets that support libopcodes based\n\ +disassembler styling. When Python Pygments based styling is used\n\ +then this style has no effect."), + &style_disasm_set_list, + &style_disasm_show_list, + false); + + disasm_register_style.add_setshow_commands (no_class, _("\ +Disassembler register display styling.\n\ +Configure the colors and display intensity for registers in the\n\ +disassembler output.\n\ +\n\ +This style will only be used for targets that support libopcodes based\n\ +disassembler styling. When Python Pygments based styling is used\n\ +then this style has no effect."), + &style_disasm_set_list, + &style_disasm_show_list, + false); + + disasm_immediate_style.add_setshow_commands (no_class, _("\ +Disassembler immediate display styling.\n\ +Configure the colors and display intensity for immediates in the\n\ +disassembler output. The \"disassembler immediate\" style is used for\n\ +any number that is not an address, this includes constants in arithmetic\n\ +instructions, as well as address offsets in memory access instructions.\n\ +\n\ +This style will only be used for targets that support libopcodes based\n\ +disassembler styling. When Python Pygments based styling is used\n\ +then this style has no effect."), + &style_disasm_set_list, + &style_disasm_show_list, + false); + + disasm_comment_style.add_setshow_commands (no_class, _("\ +Disassembler comment display styling.\n\ +Configure the colors and display intensity for comments in the\n\ +disassembler output. The \"disassembler comment\" style is used for\n\ +the comment character, and everything after the comment character up to\n\ +the end of the line. The comment style overrides any other styling,\n\ +e.g. a register name in a comment will use the comment styling.\n\ +\n\ +This style will only be used for targets that support libopcodes based\n\ +disassembler styling. When Python Pygments based styling is used\n\ +then this style has no effect."), + &style_disasm_set_list, + &style_disasm_show_list, + false); + + /* Setup 'disassembler address' style and 'disassembler symbol' style, + these are aliases for 'address' and 'function' styles respectively. */ + add_alias_cmd ("address", address_prefix_cmds.set, no_class, 0, + &style_disasm_set_list); + add_alias_cmd ("address", address_prefix_cmds.show, no_class, 0, + &style_disasm_show_list); + add_alias_cmd ("symbol", function_prefix_cmds.set, no_class, 0, + &style_disasm_set_list); + add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0, + &style_disasm_show_list); } diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h index f69df47098c..4090cf01333 100644 --- a/gdb/cli/cli-style.h +++ b/gdb/cli/cli-style.h @@ -43,12 +43,13 @@ public: /* Return the style name. */ const char *name () { return m_name; }; - /* Call once to register this CLI style with the CLI engine. */ - void add_setshow_commands (enum command_class theclass, - const char *prefix_doc, - struct cmd_list_element **set_list, - struct cmd_list_element **show_list, - bool skip_intensity); + /* Call once to register this CLI style with the CLI engine. Returns + the set/show prefix commands for the style. */ + set_show_commands add_setshow_commands (enum command_class theclass, + const char *prefix_doc, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list, + bool skip_intensity); /* Return the 'set style NAME' command list, that can be used to build a lambda DO_SET to call add_setshow_commands. */ @@ -116,6 +117,21 @@ extern cli_style_option title_style; /* The metadata style. */ extern cli_style_option metadata_style; +/* The disassembler style for mnemonics or assembler directives + (e.g. '.byte', etc). */ +extern cli_style_option disasm_mnemonic_style; + +/* The disassembler style for register names. */ +extern cli_style_option disasm_register_style; + +/* The disassembler style for numerical values that are not addresses, this + includes immediate operands (e.g. in, an add instruction), but also + address offsets (e.g. in a load instruction). */ +extern cli_style_option disasm_immediate_style; + +/* The disassembler style for comments. */ +extern cli_style_option disasm_comment_style; + /* The border style of a TUI window that does not have the focus. */ extern cli_style_option tui_border_style; diff --git a/gdb/disasm.c b/gdb/disasm.c index 6c64c14feee..cf27a32fbe7 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -41,6 +41,63 @@ which is set by the "set disassembler_options" command. */ static std::string prospective_options; +/* When this is true we will try to use libopcodes to provide styling to + the disassembler output. */ + +static bool use_libopcodes_styling = true; + +/* To support the set_use_libopcodes_styling function we have a second + variable which is connected to the actual set/show option. */ + +static bool use_libopcodes_styling_option = use_libopcodes_styling; + +/* The "maint show libopcodes-styling enabled" command. */ + +static void +show_use_libopcodes_styling (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + gdb_non_printing_memory_disassembler dis (target_gdbarch ()); + bool supported = dis.disasm_info ()->created_styled_output; + + if (supported || !use_libopcodes_styling) + gdb_printf (file, _("Use of libopcodes styling support is \"%s\".\n"), + value); + else + { + /* Use of libopcodes styling is not supported, and the user has this + turned on! */ + gdb_printf (file, _("Use of libopcodes styling support is \"off\"" + " (not supported on architecture \"%s\")\n"), + gdbarch_bfd_arch_info (target_gdbarch ())->printable_name); + } +} + +/* The "maint set libopcodes-styling enabled" command. */ + +static void +set_use_libopcodes_styling (const char *args, int from_tty, + struct cmd_list_element *c) +{ + gdb_non_printing_memory_disassembler dis (target_gdbarch ()); + bool supported = dis.disasm_info ()->created_styled_output; + + /* If the current architecture doesn't support libopcodes styling then we + give an error here, but leave the underlying setting enabled. This + means that if the user switches to an architecture that does support + libopcodes styling the setting will be enabled. */ + + if (use_libopcodes_styling_option && !supported) + { + use_libopcodes_styling_option = use_libopcodes_styling; + error (_("Use of libopcodes styling not supported on architecture \"%s\"."), + gdbarch_bfd_arch_info (target_gdbarch ())->printable_name); + } + else + use_libopcodes_styling = use_libopcodes_styling_option; +} + /* This structure is used to store line number information for the deprecated /m option. We need a different sort of line table from the normal one cuz we can't @@ -160,7 +217,26 @@ gdb_disassembler::dis_asm_print_address (bfd_vma addr, gdb_disassembler *self = static_cast(info->application_data); - print_address (self->arch (), addr, self->stream ()); + if (self->in_comment_p ()) + { + /* Calling 'print_address' might add styling to the output (based on + the properties of the stream we're writing too). This is usually + fine, but if we are in an assembler comment then we'd prefer to + have the comment style, rather than the default address style. + + Print the address into a temporary buffer which doesn't support + styling, then reprint this unstyled address with the default text + style. + + As we are inside a comment right now, the standard print routine + will ensure that the comment is printed to the user with a + suitable comment style. */ + string_file tmp; + print_address (self->arch (), addr, &tmp); + self->fprintf_styled_func (self, dis_style_text, "%s", tmp.c_str ()); + } + else + print_address (self->arch (), addr, self->stream ()); } /* See disasm.h. */ @@ -202,11 +278,54 @@ gdb_printing_disassembler::fprintf_styled_func (void *dis_info, const char *format, ...) { ui_file *stream = stream_from_gdb_disassemble_info (dis_info); + gdb_printing_disassembler *dis = (gdb_printing_disassembler *) dis_info; va_list args; va_start (args, format); - gdb_vprintf (stream, format, args); + std::string content = string_vprintf (format, args); va_end (args); + + /* Once in a comment then everything should be styled as a comment. */ + if (style == dis_style_comment_start) + dis->set_in_comment (true); + if (dis->in_comment_p ()) + style = dis_style_comment_start; + + /* Now print the content with the correct style. */ + const char *txt = content.c_str (); + switch (style) + { + case dis_style_mnemonic: + case dis_style_assembler_directive: + fputs_styled (txt, disasm_mnemonic_style.style (), stream); + break; + + case dis_style_register: + fputs_styled (txt, disasm_register_style.style (), stream); + break; + + case dis_style_immediate: + case dis_style_address_offset: + fputs_styled (txt, disasm_immediate_style.style (), stream); + break; + + case dis_style_address: + fputs_styled (txt, address_style.style (), stream); + break; + + case dis_style_symbol: + fputs_styled (txt, function_name_style.style (), stream); + break; + + case dis_style_comment_start: + fputs_styled (txt, disasm_comment_style.style (), stream); + break; + + case dis_style_text: + gdb_puts (txt, stream); + break; + } + /* Something non -ve. */ return 0; } @@ -818,7 +937,20 @@ gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch, read_memory_ftype func) : gdb_printing_disassembler (gdbarch, &m_buffer, func, dis_asm_memory_error, dis_asm_print_address), - m_buffer (!use_ext_lang_colorization_p && disassembler_styling + /* The use of m_di.created_styled_output here is a bit of a cheat, but + it works fine for now. Currently, for all targets that support + libopcodes styling, this field is set during the call to + disassemble_init_for_target, which was called as part of the + initialization of gdb_printing_disassembler. And so, we are able to + spot if a target supports libopcodes styling, and create m_buffer in + the correct styling mode. + + If there's ever a target that only sets created_styled_output during + the actual disassemble phase, then the logic here will have to + change. */ + m_buffer ((!use_ext_lang_colorization_p + || (use_libopcodes_styling && m_di.created_styled_output)) + && disassembler_styling && file->can_emit_style_escape ()), m_dest (file) { /* Nothing. */ } @@ -903,14 +1035,17 @@ gdb_disassembler::print_insn (CORE_ADDR memaddr, { m_err_memaddr.reset (); m_buffer.clear (); + this->set_in_comment (false); int length = gdb_print_insn_1 (arch (), memaddr, &m_di); - /* If we have successfully disassembled an instruction, styling is on, we - think that the extension language might be able to perform styling for - us, and the destination can support styling, then lets call into the - extension languages in order to style this output. */ + /* If we have successfully disassembled an instruction, disassembler + styling using the extension language is on, and libopcodes hasn't + already styled the output for us, and, if the destination can support + styling, then lets call into the extension languages in order to style + this output. */ if (length > 0 && disassembler_styling + && (!m_di.created_styled_output || !use_libopcodes_styling) && use_ext_lang_colorization_p && m_dest->can_emit_style_escape ()) { @@ -1311,4 +1446,39 @@ Show the disassembler options."), NULL, show_disassembler_options_sfunc, &setlist, &showlist); set_cmd_completer (set_show_disas_opts.set, disassembler_options_completer); + + + /* All the 'maint set|show libopcodes-styling' sub-commands. */ + static struct cmd_list_element *maint_set_libopcodes_styling_cmdlist; + static struct cmd_list_element *maint_show_libopcodes_styling_cmdlist; + + /* Adds 'maint set|show libopcodes-styling'. */ + add_setshow_prefix_cmd ("libopcodes-styling", class_maintenance, + _("Set libopcodes-styling specific variables."), + _("Show libopcodes-styling specific variables."), + &maint_set_libopcodes_styling_cmdlist, + &maint_show_libopcodes_styling_cmdlist, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); + + /* Adds 'maint set|show gnu-source-highlight enabled'. */ + add_setshow_boolean_cmd ("enabled", class_maintenance, + &use_libopcodes_styling_option, _("\ +Set whether the libopcodes styling support should be used."), _("\ +Show whether the libopcodes styling support should be used."),_("\ +When enabled, GDB will try to make use of the builtin libopcodes styling\n\ +support, to style the disassembler output. Not every architecture has\n\ +styling support within libopcodes, so enabling this is not a guarantee\n\ +that libopcodes styling will be available.\n\ +\n\ +When this option is disabled, GDB will make use of the Python Pygments\n\ +package (if available) to style the disassembler output.\n\ +\n\ +All disassembler styling can be disabled with:\n\ +\n\ + set style disassembler enabled off"), + set_use_libopcodes_styling, + show_use_libopcodes_styling, + &maint_set_libopcodes_styling_cmdlist, + &maint_show_libopcodes_styling_cmdlist); } diff --git a/gdb/disasm.h b/gdb/disasm.h index 54176eb095a..2921d537e0a 100644 --- a/gdb/disasm.h +++ b/gdb/disasm.h @@ -138,6 +138,16 @@ protected: const char *format, ...) ATTRIBUTE_PRINTF(3,4); + /* Return true if the disassembler is considered inside a comment, false + otherwise. */ + bool in_comment_p () const + { return m_in_comment; } + + /* Set whether the disassembler should be considered as within comment + text or not. */ + void set_in_comment (bool c) + { m_in_comment = c; } + private: /* When libopcodes calls the fprintf_func and fprintf_styled_func @@ -151,6 +161,12 @@ private: /* The stream to which output should be sent. */ struct ui_file *m_stream; + + /* Are we inside a comment? This will be set true if the disassembler + uses styled output and emits a start of comment character. It is up + to the code that uses this disassembler class to reset this flag back + to false at a suitable time (e.g. at the end of every line). */ + bool m_in_comment; }; /* A basic disassembler that doesn't actually print anything. */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7a4e337d15b..86394f631ac 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -26526,6 +26526,7 @@ then it will be used. @item show style sources Show the current state of source code styling. +@anchor{style_disassembler_enabled} @item set style disassembler enabled @samp{on|off} Enable or disable disassembler styling. This affects whether disassembler output, such as the output of the @code{disassemble} @@ -26533,13 +26534,32 @@ command, is styled. Disassembler styling only works if styling in general is enabled (with @code{set style enabled on}), and if a source highlighting library is available to @value{GDBN}. -To highlight disassembler output, @value{GDBN} must be compiled with -Python support, and the Python Pygments package must be available. If -these requirements are not met then @value{GDBN} will not highlight -disassembler output, even when this option is @samp{on}. +The two source highlighting libraries that @value{GDBN} could use to +style disassembler output are; @value{GDBN}'s builtin disassembler, or +the Python Pygments package. + +@value{GDBN}'s first choice will be to use the builtin disassembler +for styling, this usually provides better results, being able to style +different types of instruction operands differently. However, the +builtin disassembler is not able to style all architectures. + +For architectures that the builtin disassembler is unable to style, +@value{GDBN} will fall back to use the Python Pygments package where +possible. In order to use the Python Pygments package, @value{GDBN} +must be built with Python support, and the Pygments package must be +installed. + +If neither of these options are available then @value{GDBN} will +produce unstyled disassembler output, even when this setting is +@samp{on}. + +To discover if the current architecture supports styling using the +builtin disassembler library see @ref{maint_libopcodes_styling,,@kbd{maint +show libopcodes-styling enabled}}. @item show style disassembler enabled Show the current state of disassembler styling. + @end table Subcommands of @code{set style} control specific forms of styling. @@ -26584,6 +26604,11 @@ Control the styling of function names. These are managed with the @code{set style function} family of commands. By default, this style's foreground color is yellow. +This style is also used for symbol names in styled disassembler output +if @value{GDBN} is using its builtin disassembler library for styling +(@pxref{style_disassembler_enabled,,@kbd{set style disassembler +enabled}}). + @item variable Control the styling of variable names. These are managed with the @code{set style variable} family of commands. By default, this style's @@ -26594,6 +26619,11 @@ Control the styling of addresses. These are managed with the @code{set style address} family of commands. By default, this style's foreground color is blue. +This style is also used for addresses in styled disassembler output +if @value{GDBN} is using its builtin disassembler library for styling +(@pxref{style_disassembler_enabled,,@kbd{set style disassembler +enabled}}). + @item version Control the styling of @value{GDBN}'s version number text. By default, this style's foreground color is magenta and it has bold @@ -26642,6 +26672,47 @@ general styling to @value{GDBN}. @xref{TUI Configuration}. Control the styling of the active TUI border; that is, the TUI window that has the focus. +@item disassembler comment +Control the styling of comments in the disassembler output. These are +managed with the @code{set style disassembler comment} family of +commands. This style is only used when @value{GDBN} is styling using +its builtin disassembler library +(@pxref{style_disassembler_enabled,,@kbd{set style disassembler +enabled}}). By default, this style's intensity is dim, and its +foreground color is white. + +@item disassembler immediate +Control the styling of numeric operands in the disassembler output. +These are managed with the @code{set style disassembler immediate} +family of commands. This style is not used for instruction operands +that represent addresses, in that case the @samp{disassembler address} +style is used. This style is only used when @value{GDBN} is styling +using its builtin disassembler library. By default, this style's +foreground color is blue. + +@item disassembler address +Control the styling of address operands in the disassembler output. +This is an alias for the @samp{address} style. + +@item disassembler symbol +Control the styling of symbol names in the disassembler output. This +is an alias for the @samp{function} style. + +@item disassembler mnemonic +Control the styling of instruction mnemonics in the disassembler +output. These are managed with the @code{set style disassembler +mnemonic} family of commands. This style is also used for assembler +directives, e.g.@: @code{.byte}, @code{.word}, etc. This style is +only used when @value{GDBN} is styling using its builtin disassembler +library. By default, this style's foreground color is green. + +@item disassembler register +Control the styling of register operands in the disassembler output. +These are managed with the @code{set style disassembler register} +family of commands. This style is only used when @value{GDBN} is +styling using its builtin disassembler library. By default, this style's +foreground color is red. + @end table @node Numbers @@ -40415,6 +40486,29 @@ This option is useful for debugging @value{GDBN}'s use of the Pygments library when @value{GDBN} is linked against the GNU Source Highlight library. +@anchor{maint_libopcodes_styling} +@kindex maint set libopcodes-styling enabled +@kindex maint show libopcodes-styling enabled +@item maint set libopcodes-styling enabled @r{[}on|off@r{]} +@itemx maint show libopcodes-styling enabled +Control whether @value{GDBN} should use its builtin disassembler +(@file{libopcodes}) to style disassembler output (@pxref{Output +Styling}). The builtin disassembler does not support styling for all +architectures. + +When this option is @samp{off} the builtin disassembler will not be +used for styling, @value{GDBN} will fall back to using the Python +Pygments package if possible. + +Trying to set this option @samp{on} for an architecture that the +builtin disassembler is unable to style will give an error, otherwise, +the builtin disassembler will be used to style disassembler output. + +This option is @samp{on} by default for supported architectures. + +This option is useful for debugging @value{GDBN}'s use of the Pygments +library when @value{GDBN} is built for an architecture that supports +styling with the builtin disassembler @kindex maint space @cindex memory used by commands @item maint space @var{value}