GDB: Add support for the new set/show disassembler-options commands.

This commit adds support to GDB so that it can modify the disassembler-options
value that is passed to the disassembler, similar to objdump's -M option.
Currently, the only supported targets are ARM, PowerPC and S/390, but
adding support for a new target(s) is not difficult.

include/
	* dis-asm.h (disasm_options_t): New typedef.
	(parse_arm_disassembler_option): Remove prototype.
	(set_arm_regname_option): Likewise.
	(get_arm_regnames): Likewise.
	(get_arm_regname_num_options): Likewise.
	(disassemble_init_s390): New prototype.
	(disassembler_options_powerpc): Likewise.
	(disassembler_options_arm): Likewise.
	(disassembler_options_s390): Likewise.
	(remove_whitespace_and_extra_commas): Likewise.
	(disassembler_options_cmp): Likewise.
	(next_disassembler_option): New inline function.
	(FOR_EACH_DISASSEMBLER_OPTION): New macro.

opcodes/
	* disassemble.c Include "safe-ctype.h".
	(disassemble_init_for_target): Handle s390 init.
	(remove_whitespace_and_extra_commas): New function.
	(disassembler_options_cmp): Likewise.
	* arm-dis.c: Include "libiberty.h".
	(NUM_ELEM): Delete.
	(regnames): Use long disassembler style names.
	Add force-thumb and no-force-thumb options.
	(NUM_ARM_REGNAMES): Rename from this...
	(NUM_ARM_OPTIONS): ...to this.  Use ARRAY_SIZE.
	(get_arm_regname_num_options): Delete.
	(set_arm_regname_option): Likewise.
	(get_arm_regnames): Likewise.
	(parse_disassembler_options): Likewise.
	(parse_arm_disassembler_option): Rename from this...
	(parse_arm_disassembler_options): ...to this.  Make static.
	Use new FOR_EACH_DISASSEMBLER_OPTION macro to scan over options.
	(print_insn): Use parse_arm_disassembler_options.
	(disassembler_options_arm): New function.
	(print_arm_disassembler_options): Handle updated regnames.
	* ppc-dis.c: Include "libiberty.h".
	(ppc_opts): Add "32" and "64" entries.
	(ppc_parse_cpu): Use ARRAY_SIZE and disassembler_options_cmp.
	(powerpc_init_dialect): Add break to switch statement.
	Use new FOR_EACH_DISASSEMBLER_OPTION macro.
	(disassembler_options_powerpc): New function.
	(print_ppc_disassembler_options): Use ARRAY_SIZE.
	Remove printing of "32" and "64".
	* s390-dis.c: Include "libiberty.h".
	(init_flag): Remove unneeded variable.
	(struct s390_options_t): New structure type.
	(options): New structure.
	(init_disasm): Rename from this...
	(disassemble_init_s390): ...to this.  Add initializations for
	current_arch_mask and option_use_insn_len_bits_p.  Remove init_flag.
	(print_insn_s390): Delete call to init_disasm.
	(disassembler_options_s390): New function.
	(print_s390_disassembler_options): Print using information from
	struct 'options'.
	* po/opcodes.pot: Regenerate.

binutils/
	* objdump.c (main): Use remove_whitespace_and_extra_commas.

gdb/
	* NEWS: Mention new set/show disassembler-options commands.
	* doc/gdb.texinfo: Document new set/show disassembler-options commands.
	* disasm.c: Include "arch-utils.h", "gdbcmd.h" and "safe-ctype.h".
	(prospective_options): New static variable.
	(gdb_disassembler::gdb_disassembler): Initialize
	m_di.disassembler_options.
	(gdb_buffered_insn_length_init_dis): Initilize di->disassembler_options.
	(get_disassembler_options): New function.
	(set_disassembler_options): Likewise.
	(set_disassembler_options_sfunc): Likewise.
	(show_disassembler_options_sfunc): Likewise.
	(disassembler_options_completer): Likewise.
	(_initialize_disasm): Likewise.
	* disasm.h (get_disassembler_options): New prototype.
	(set_disassembler_options): Likewise.
	* gdbarch.sh (gdbarch_disassembler_options): New variable.
	(gdbarch_verify_disassembler_options): Likewise.
	* gdbarch.c: Regenerate.
	* gdbarch.h: Likewise.
	* arm-tdep.c (num_disassembly_options): Delete.
	(set_disassembly_style): Likewise.
	(arm_disassembler_options): New static variable.
	(set_disassembly_style_sfunc): Convert short style name into long
	option name.  Call set_disassembler_options.
	(show_disassembly_style_sfunc): New function.
	(arm_gdbarch_init): Call set_gdbarch_disassembler_options and
	set_gdbarch_verify_disassembler_options.
	(_initialize_arm_tdep): Delete regnames variable and update callers.
	(arm_disassembler_options): Initialize.
	(disasm_options): New variable.
	(num_disassembly_options): Rename from this...
	(num_disassembly_styles): ...to this.  Compute by scanning through
	disasm_options.
	(valid_disassembly_styles): Initialize using disasm_options.
	Remove calls to parse_arm_disassembler_option, get_arm_regnames and
	set_arm_regname_option.
	Pass show_disassembly_style_sfunc to the "disassembler" setshow command.
	* rs6000-tdep.c (powerpc_disassembler_options): New static variable.
	(rs6000_gdbarch_init): Call set_gdbarch_disassembler_options and
	set_gdbarch_verify_disassembler_options.
	* s390-tdep.c (s390_disassembler_options): New static variable.
	(s390_gdbarch_init):all set_gdbarch_disassembler_options and
	set_gdbarch_verify_disassembler_options.

gdb/testsuite/
	* gdb.arch/powerpc-power.exp: Delete test.
	* gdb.arch/powerpc-power.s: Likewise.
	* gdb.disasm/disassembler-options.exp: New test.
	* gdb.arch/powerpc-altivec.exp: Likewise.
	* gdb.arch/powerpc-altivec.s: Likewise.
	* gdb.arch/powerpc-altivec2.exp: Likewise.
	* gdb.arch/powerpc-altivec2.s: Likewise.
	* gdb.arch/powerpc-altivec3.exp: Likewise.
	* gdb.arch/powerpc-altivec3.s: Likewise.
	* gdb.arch/powerpc-power7.exp: Likewise.
	* gdb.arch/powerpc-power7.s: Likewise.
	* gdb.arch/powerpc-power8.exp: Likewise.
	* gdb.arch/powerpc-power8.s: Likewise.
	* gdb.arch/powerpc-power9.exp: Likewise.
	* gdb.arch/powerpc-power9.s: Likewise.
	* gdb.arch/powerpc-vsx.exp: Likewise.
	* gdb.arch/powerpc-vsx.s: Likewise.
	* gdb.arch/powerpc-vsx2.exp: Likewise.
	* gdb.arch/powerpc-vsx2.s: Likewise.
	* gdb.arch/powerpc-vsx3.exp: Likewise.
	* gdb.arch/powerpc-vsx3.s: Likewise.
	* gdb.arch/arm-disassembler-options.exp: Likewise.
	* gdb.arch/powerpc-disassembler-options.exp: Likewise.
	* gdb.arch/s390-disassembler-options.exp: Likewise.
This commit is contained in:
Peter Bergner
2017-02-28 12:32:07 -06:00
parent 2979a88354
commit 65b48a8140
46 changed files with 4607 additions and 3099 deletions

View File

@@ -18,19 +18,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
#include "target.h"
#include "value.h"
#include "ui-out.h"
#include "disasm.h"
#include "gdbcore.h"
#include "gdbcmd.h"
#include "dis-asm.h"
#include "source.h"
#include "safe-ctype.h"
#include <algorithm>
/* Disassemble functions.
FIXME: We should get rid of all the duplicate code in gdb that does
the same thing: disassemble_command() and the gdbtk variation. */
/* This variable is used to hold the prospective disassembler_options value
which is set by the "set disassembler_options" command. */
static char *prospective_options = NULL;
/* 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
@@ -780,6 +787,7 @@ gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
m_di.endian = gdbarch_byte_order (gdbarch);
m_di.endian_code = gdbarch_byte_order_for_code (gdbarch);
m_di.application_data = this;
m_di.disassembler_options = get_disassembler_options (gdbarch);
disassemble_init_for_target (&m_di);
}
@@ -888,6 +896,7 @@ gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
di->endian = gdbarch_byte_order (gdbarch);
di->endian_code = gdbarch_byte_order_for_code (gdbarch);
di->disassembler_options = get_disassembler_options (gdbarch);
disassemble_init_for_target (di);
}
@@ -904,3 +913,173 @@ gdb_buffered_insn_length (struct gdbarch *gdbarch,
return gdbarch_print_insn (gdbarch, addr, &di);
}
char *
get_disassembler_options (struct gdbarch *gdbarch)
{
char **disassembler_options = gdbarch_disassembler_options (gdbarch);
if (disassembler_options == NULL)
return NULL;
return *disassembler_options;
}
void
set_disassembler_options (char *prospective_options)
{
struct gdbarch *gdbarch = get_current_arch ();
char **disassembler_options = gdbarch_disassembler_options (gdbarch);
const disasm_options_t *valid_options;
char *options = remove_whitespace_and_extra_commas (prospective_options);
char *opt;
/* Allow all architectures, even ones that do not support 'set disassembler',
to reset their disassembler options to NULL. */
if (options == NULL)
{
if (disassembler_options != NULL)
{
free (*disassembler_options);
*disassembler_options = NULL;
}
return;
}
valid_options = gdbarch_valid_disassembler_options (gdbarch);
if (valid_options == NULL)
{
fprintf_filtered (gdb_stdlog, _("\
'set disassembler-options ...' is not supported on this architecture.\n"));
return;
}
/* Verify we have valid disassembler options. */
FOR_EACH_DISASSEMBLER_OPTION (opt, options)
{
size_t i;
for (i = 0; valid_options->name[i] != NULL; i++)
if (disassembler_options_cmp (opt, valid_options->name[i]) == 0)
break;
if (valid_options->name[i] == NULL)
{
fprintf_filtered (gdb_stdlog,
_("Invalid disassembler option value: '%s'.\n"),
opt);
return;
}
}
free (*disassembler_options);
*disassembler_options = xstrdup (options);
}
static void
set_disassembler_options_sfunc (char *args, int from_tty,
struct cmd_list_element *c)
{
set_disassembler_options (prospective_options);
}
static void
show_disassembler_options_sfunc (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
struct gdbarch *gdbarch = get_current_arch ();
const disasm_options_t *valid_options;
const char *options = get_disassembler_options (gdbarch);
if (options == NULL)
options = "";
fprintf_filtered (file, _("The current disassembler options are '%s'\n"),
options);
valid_options = gdbarch_valid_disassembler_options (gdbarch);
if (valid_options == NULL)
return;
fprintf_filtered (file, _("\n\
The following disassembler options are supported for use with the\n\
'set disassembler-options <option>[,<option>...]' command:\n"));
if (valid_options->description != NULL)
{
size_t i, max_len = 0;
/* Compute the length of the longest option name. */
for (i = 0; valid_options->name[i] != NULL; i++)
{
size_t len = strlen (valid_options->name[i]);
if (max_len < len)
max_len = len;
}
for (i = 0, max_len++; valid_options->name[i] != NULL; i++)
{
fprintf_filtered (file, " %s", valid_options->name[i]);
if (valid_options->description[i] != NULL)
fprintf_filtered (file, "%*c %s",
(int)(max_len - strlen (valid_options->name[i])), ' ',
valid_options->description[i]);
fprintf_filtered (file, "\n");
}
}
else
{
size_t i;
fprintf_filtered (file, " ");
for (i = 0; valid_options->name[i] != NULL; i++)
{
fprintf_filtered (file, "%s", valid_options->name[i]);
if (valid_options->name[i + 1] != NULL)
fprintf_filtered (file, ", ");
wrap_here (" ");
}
fprintf_filtered (file, "\n");
}
}
/* A completion function for "set disassembler". */
static VEC (char_ptr) *
disassembler_options_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
{
struct gdbarch *gdbarch = get_current_arch ();
const disasm_options_t *opts = gdbarch_valid_disassembler_options (gdbarch);
if (opts != NULL)
{
/* Only attempt to complete on the last option text. */
const char *separator = strrchr (text, ',');
if (separator != NULL)
text = separator + 1;
text = skip_spaces_const (text);
return complete_on_enum (opts->name, text, word);
}
return NULL;
}
/* Initialization code. */
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_disasm;
void
_initialize_disasm (void)
{
struct cmd_list_element *cmd;
/* Add the command that controls the disassembler options. */
cmd = add_setshow_string_noescape_cmd ("disassembler-options", no_class,
&prospective_options, _("\
Set the disassembler options.\n\
Usage: set disassembler-options <option>[,<option>...]\n\n\
See: 'show disassembler-options' for valid option values.\n"), _("\
Show the disassembler options."), NULL,
set_disassembler_options_sfunc,
show_disassembler_options_sfunc,
&setlist, &showlist);
set_cmd_completer (cmd, disassembler_options_completer);
}