aboutsummaryrefslogtreecommitdiff
path: root/gdb/disasm.c
diff options
context:
space:
mode:
authorPeter Bergner <bergner@vnet.ibm.com>2017-02-28 12:32:07 -0600
committerPeter Bergner <bergner@vnet.ibm.com>2017-02-28 12:32:07 -0600
commit65b48a81404cb058c75c562f7dfdeb74f07eba72 (patch)
treee377b88638eb395dabeac3d31c7199e1acd2edea /gdb/disasm.c
parent2979a883540d9ce6e41dd0509ea2a345de9cf050 (diff)
downloadgdb-65b48a81404cb058c75c562f7dfdeb74f07eba72.zip
gdb-65b48a81404cb058c75c562f7dfdeb74f07eba72.tar.gz
gdb-65b48a81404cb058c75c562f7dfdeb74f07eba72.tar.bz2
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.
Diffstat (limited to 'gdb/disasm.c')
-rw-r--r--gdb/disasm.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 64d6684..ab080e2 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -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);
+}