diff options
author | Maciej W. Rozycki <macro@mips.com> | 2018-07-02 23:57:21 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@mips.com> | 2018-07-02 23:57:21 +0100 |
commit | 471b9d15076fffb738f1bc6fcea41d0dcb59c947 (patch) | |
tree | 2d57149ea32d39c1e8922e2644641e55aa672b8b /gdb | |
parent | b638b5d57fafc84a8dc0ff91d7579a3c24aad90c (diff) | |
download | gdb-471b9d15076fffb738f1bc6fcea41d0dcb59c947.zip gdb-471b9d15076fffb738f1bc6fcea41d0dcb59c947.tar.gz gdb-471b9d15076fffb738f1bc6fcea41d0dcb59c947.tar.bz2 |
GDB PR tdep/8282: MIPS: Wire in `set disassembler-options'
Implement MIPS target support for passing options to the disassembler,
complementing commit 65b48a81404c ("GDB: Add support for the new
set/show disassembler-options commands.").
This includes options that expect an argument, so adjust the generic
code and data structures used so as to handle such options. So as to
give backends syntax flexibility no specific delimiter has been defined
to separate options from their respective arguments, so it has to be
included as the last character of the option name. Completion code
however has not been adjusted and consequently option arguments cannot
be completed at this time.
Also the MIPS target has non-empty defaults for the options, so that ABI
names for the general-purpose registers respect our `set mips abi ...'
setting rather than always being determined from the ELF headers of the
binary file selected. Handle these defaults as implicit options, never
shown to the user and always prepended to the user-specified options, so
that the latters can override the defaults.
The resulting output for the MIPS target is as follows:
(gdb) show disassembler-options
The current disassembler options are ''
The following disassembler options are supported for use with the
'set disassembler-options <option>[,<option>...]' command:
no-aliases Use canonical instruction forms.
msa Recognize MSA instructions.
virt Recognize the virtualization ASE instructions.
xpa Recognize the eXtended Physical Address (XPA) ASE
instructions.
ginv Recognize the Global INValidate (GINV) ASE instructions.
gpr-names=ABI Print GPR names according to specified ABI.
Default: based on binary being disassembled.
fpr-names=ABI Print FPR names according to specified ABI.
Default: numeric.
cp0-names=ARCH Print CP0 register names according to specified architecture.
Default: based on binary being disassembled.
hwr-names=ARCH Print HWR names according to specified architecture.
Default: based on binary being disassembled.
reg-names=ABI Print GPR and FPR names according to specified ABI.
reg-names=ARCH Print CP0 register and HWR names according to specified
architecture.
For the options above, the following values are supported for "ABI":
numeric 32 n32 64
For the options above, the following values are supported for "ARCH":
numeric r3000 r3900 r4000 r4010 vr4100 vr4111 vr4120 r4300 r4400 r4600
r4650 r5000 vr5400 vr5500 r5900 r6000 rm7000 rm9000 r8000 r10000 r12000
r14000 r16000 mips5 mips32 mips32r2 mips32r3 mips32r5 mips32r6 mips64
mips64r2 mips64r3 mips64r5 mips64r6 interaptiv-mr2 sb1 loongson2e
loongson2f loongson3a octeon octeon+ octeon2 octeon3 xlr xlp
(gdb)
which corresponds to what `objdump --help' used to print for the MIPS
target, with minor formatting changes, most notably option argument
lists being wrapped, but also the amount of white space separating
options from the respective descriptions. The relevant part the new
code is now also used by `objdump --help', which means these formatting
changes apply to both outputs, except for argument list wrapping, which
is GDB-specific.
This also adds a separating new line between the heading and option
lists where descriptions are provided, hence:
(gdb) set architecture s390:31-bit
(gdb) show disassembler-options
The current disassembler options are ''
The following disassembler options are supported for use with the
'set disassembler-options <option>[,<option>...]' command:
esa Disassemble in ESA architecture mode
zarch Disassemble in z/Architecture mode
insnlength Print unknown instructions according to length from first two bits
(gdb)
but:
(gdb) set architecture powerpc:common
(gdb) show disassembler-options
The current disassembler options are ''
The following disassembler options are supported for use with the
'set disassembler-options <option>[,<option>...]' command:
403, 405, 440, 464, 476, 601, 603, 604, 620, 7400, 7410, 7450, 7455, 750cl,
821, 850, 860, a2, altivec, any, booke, booke32, cell, com, e200z4, e300,
e500, e500mc, e500mc64, e5500, e6500, e500x2, efs, efs2, power4, power5,
power6, power7, power8, power9, ppc, ppc32, 32, ppc64, 64, ppc64bridge,
ppcps, pwr, pwr2, pwr4, pwr5, pwr5x, pwr6, pwr7, pwr8, pwr9, pwrx, raw, spe,
spe2, titan, vle, vsx
(gdb)
Existing affected target backends have been adjusted accordingly.
This has been verified manually with:
(gdb) set architecture arm
(gdb) set architecture powerpc:common
(gdb) set architecture s390:31-bit
to cause no issues with the `show disassembler-options' and `set
disassembler-options' commands. A test case for the MIPS target has
also been provided, covering the default settings with ABI overrides as
well as disassembler option overrides.
2018-07-02 Maciej W. Rozycki <macro@mips.com>
Simon Marchi <simon.marchi@polymtl.ca>
include/
PR tdep/8282
* dis-asm.h (disasm_option_arg_t): New typedef.
(disasm_options_and_args_t): Likewise.
(disasm_options_t): Add `arg' member, document members.
(disassembler_options_mips): New prototype.
(disassembler_options_arm, disassembler_options_powerpc)
(disassembler_options_s390): Update prototypes.
opcodes/
PR tdep/8282
* mips-dis.c (mips_option_arg_t): New enumeration.
(mips_options): New variable.
(disassembler_options_mips): New function.
(print_mips_disassembler_options): Reimplement in terms of
`disassembler_options_mips'.
* arm-dis.c (disassembler_options_arm): Adapt to using the
`disasm_options_and_args_t' structure.
* ppc-dis.c (disassembler_options_powerpc): Likewise.
* s390-dis.c (disassembler_options_s390): Likewise.
gdb/
PR tdep/8282
* disasm.h (gdb_disassembler): Add
`m_disassembler_options_holder'. member
* disasm.c (get_all_disassembler_options): New function.
(gdb_disassembler::gdb_disassembler): Use it.
(gdb_buffered_insn_length_init_dis): Likewise.
(gdb_buffered_insn_length): Adjust accordingly.
(set_disassembler_options): Handle options with arguments.
(show_disassembler_options_sfunc): Likewise. Add a leading new
line if showing options with descriptions.
(disassembler_options_completer): Adapt to using the
`disasm_options_and_args_t' structure.
* mips-tdep.c (mips_disassembler_options): New variable.
(mips_disassembler_options_o32): Likewise.
(mips_disassembler_options_n32): Likewise.
(mips_disassembler_options_n64): Likewise.
(gdb_print_insn_mips): Don't set `disassembler_options'.
(gdb_print_insn_mips_n32, gdb_print_insn_mips_n64): Remove
functions.
(mips_gdbarch_init): Always set `gdbarch_print_insn' to
`gdb_print_insn_mips'. Set `gdbarch_disassembler_options',
`gdbarch_disassembler_options_implicit' and
`gdbarch_valid_disassembler_options'.
* arm-tdep.c (_initialize_arm_tdep): Adapt to using the
`disasm_options_and_args_t' structure.
* gdbarch.sh (disassembler_options_implicit): New `gdbarch'
method.
(valid_disassembler_options): Switch from `disasm_options_t' to
the `disasm_options_and_args_t' structure.
* NEWS: Document `set disassembler-options' support for the MIPS
target.
* gdbarch.h: Regenerate.
* gdbarch.c: Regenerate.
gdb/doc/
PR tdep/8282
* gdb.texinfo (Source and Machine Code): Document `set
disassembler-options' support for the MIPS target.
gdb/testsuite/
PR tdep/8282
* gdb.arch/mips-disassembler-options.exp: New test.
* gdb.arch/mips-disassembler-options.s: New test source.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 37 | ||||
-rw-r--r-- | gdb/NEWS | 3 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 3 | ||||
-rw-r--r-- | gdb/disasm.c | 127 | ||||
-rw-r--r-- | gdb/disasm.h | 5 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 2 | ||||
-rw-r--r-- | gdb/gdbarch.c | 28 | ||||
-rw-r--r-- | gdb/gdbarch.h | 7 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 3 | ||||
-rw-r--r-- | gdb/mips-tdep.c | 60 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/mips-disassembler-options.exp | 58 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/mips-disassembler-options.s | 30 |
14 files changed, 316 insertions, 59 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0f601bd..7bb4100 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,40 @@ +2018-07-02 Maciej W. Rozycki <macro@mips.com> + Simon Marchi <simon.marchi@polymtl.ca> + + PR tdep/8282 + * disasm.h (gdb_disassembler): Add + `m_disassembler_options_holder'. member + * disasm.c (get_all_disassembler_options): New function. + (gdb_disassembler::gdb_disassembler): Use it. + (gdb_buffered_insn_length_init_dis): Likewise. + (gdb_buffered_insn_length): Adjust accordingly. + (set_disassembler_options): Handle options with arguments. + (show_disassembler_options_sfunc): Likewise. Add a leading new + line if showing options with descriptions. + (disassembler_options_completer): Adapt to using the + `disasm_options_and_args_t' structure. + * mips-tdep.c (mips_disassembler_options): New variable. + (mips_disassembler_options_o32): Likewise. + (mips_disassembler_options_n32): Likewise. + (mips_disassembler_options_n64): Likewise. + (gdb_print_insn_mips): Don't set `disassembler_options'. + (gdb_print_insn_mips_n32, gdb_print_insn_mips_n64): Remove + functions. + (mips_gdbarch_init): Always set `gdbarch_print_insn' to + `gdb_print_insn_mips'. Set `gdbarch_disassembler_options', + `gdbarch_disassembler_options_implicit' and + `gdbarch_valid_disassembler_options'. + * arm-tdep.c (_initialize_arm_tdep): Adapt to using the + `disasm_options_and_args_t' structure. + * gdbarch.sh (disassembler_options_implicit): New `gdbarch' + method. + (valid_disassembler_options): Switch from `disasm_options_t' to + the `disasm_options_and_args_t' structure. + * NEWS: Document `set disassembler-options' support for the MIPS + target. + * gdbarch.h: Regenerate. + * gdbarch.c: Regenerate. + 2018-07-02 Sebastian Huber <sebastian.huber@embedded-brains.de> * riscv-tdep.c (riscv_register_aliases): Swap "fp" and "s0" entries. @@ -3,6 +3,9 @@ *** Changes since GDB 8.1 +* The 'set disassembler-options' command now supports specifying options + for the MIPS target. + * The 'symbol-file' command now accepts an '-o' option to add a relative offset to all sections. diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 3ea0e79..fdfb360 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -9572,7 +9572,8 @@ _initialize_arm_tdep (void) arm_disassembler_options = xstrdup ("reg-names-std"); - const disasm_options_t *disasm_options = disassembler_options_arm (); + const disasm_options_t *disasm_options + = &disassembler_options_arm ()->options; int num_disassembly_styles = 0; for (i = 0; disasm_options->name[i] != NULL; i++) if (CONST_STRNEQ (disasm_options->name[i], "reg-names-")) diff --git a/gdb/disasm.c b/gdb/disasm.c index 6983903..11793df 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -722,6 +722,31 @@ fprintf_disasm (void *stream, const char *format, ...) return 0; } +/* Combine implicit and user disassembler options and return them + in a newly-created string. */ + +static std::string +get_all_disassembler_options (struct gdbarch *gdbarch) +{ + const char *implicit = gdbarch_disassembler_options_implicit (gdbarch); + const char *options = get_disassembler_options (gdbarch); + const char *comma = ","; + + if (implicit == nullptr) + { + implicit = ""; + comma = ""; + } + + if (options == nullptr) + { + options = ""; + comma = ""; + } + + return string_printf ("%s%s%s", implicit, comma, options); +} + gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch, struct ui_file *file, di_read_memory_ftype read_memory_func) @@ -746,7 +771,9 @@ 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); + m_disassembler_options_holder = get_all_disassembler_options (gdbarch); + if (!m_disassembler_options_holder.empty ()) + m_di.disassembler_options = m_disassembler_options_holder.c_str (); disassemble_init_for_target (&m_di); } @@ -833,13 +860,16 @@ gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...) return 0; } -/* Initialize a struct disassemble_info for gdb_buffered_insn_length. */ +/* Initialize a struct disassemble_info for gdb_buffered_insn_length. + Upon return, *DISASSEMBLER_OPTIONS_HOLDER owns the string pointed + to by DI.DISASSEMBLER_OPTIONS. */ static void gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch, struct disassemble_info *di, const gdb_byte *insn, int max_len, - CORE_ADDR addr) + CORE_ADDR addr, + std::string *disassembler_options_holder) { init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf); @@ -855,7 +885,9 @@ 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); + *disassembler_options_holder = get_all_disassembler_options (gdbarch); + if (!disassembler_options_holder->empty ()) + di->disassembler_options = disassembler_options_holder->c_str (); disassemble_init_for_target (di); } @@ -867,8 +899,10 @@ gdb_buffered_insn_length (struct gdbarch *gdbarch, const gdb_byte *insn, int max_len, CORE_ADDR addr) { struct disassemble_info di; + std::string disassembler_options_holder; - gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr); + gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr, + &disassembler_options_holder); return gdbarch_print_insn (gdbarch, addr, &di); } @@ -887,6 +921,7 @@ set_disassembler_options (char *prospective_options) { struct gdbarch *gdbarch = get_current_arch (); char **disassembler_options = gdbarch_disassembler_options (gdbarch); + const disasm_options_and_args_t *valid_options_and_args; const disasm_options_t *valid_options; char *options = remove_whitespace_and_extra_commas (prospective_options); const char *opt; @@ -903,20 +938,42 @@ set_disassembler_options (char *prospective_options) return; } - valid_options = gdbarch_valid_disassembler_options (gdbarch); - if (valid_options == NULL) + valid_options_and_args = gdbarch_valid_disassembler_options (gdbarch); + if (valid_options_and_args == NULL) { fprintf_filtered (gdb_stdlog, _("\ 'set disassembler-options ...' is not supported on this architecture.\n")); return; } + valid_options = &valid_options_and_args->options; + /* 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) + if (valid_options->arg != NULL && valid_options->arg[i] != NULL) + { + size_t len = strlen (valid_options->name[i]); + bool found = false; + const char *arg; + size_t j; + + if (memcmp (opt, valid_options->name[i], len) != 0) + continue; + arg = opt + len; + for (j = 0; valid_options->arg[i]->values[j] != NULL; j++) + if (disassembler_options_cmp + (arg, valid_options->arg[i]->values[j]) == 0) + { + found = true; + break; + } + if (found) + break; + } + else if (disassembler_options_cmp (opt, valid_options->name[i]) == 0) break; if (valid_options->name[i] == NULL) { @@ -943,6 +1000,8 @@ 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_and_args_t *valid_options_and_args; + const disasm_option_arg_t *valid_args; const disasm_options_t *valid_options; const char *options = get_disassembler_options (gdbarch); @@ -952,11 +1011,13 @@ show_disassembler_options_sfunc (struct ui_file *file, int from_tty, fprintf_filtered (file, _("The current disassembler options are '%s'\n"), options); - valid_options = gdbarch_valid_disassembler_options (gdbarch); + valid_options_and_args = gdbarch_valid_disassembler_options (gdbarch); - if (valid_options == NULL) + if (valid_options_and_args == NULL) return; + valid_options = &valid_options_and_args->options; + fprintf_filtered (file, _("\n\ The following disassembler options are supported for use with the\n\ 'set disassembler-options <option>[,<option>...]' command:\n")); @@ -965,10 +1026,15 @@ The following disassembler options are supported for use with the\n\ { size_t i, max_len = 0; + fprintf_filtered (file, "\n"); + /* 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 (valid_options->arg != NULL && valid_options->arg[i] != NULL) + len += strlen (valid_options->arg[i]->name); if (max_len < len) max_len = len; } @@ -976,10 +1042,17 @@ The following disassembler options are supported for use with the\n\ for (i = 0, max_len++; valid_options->name[i] != NULL; i++) { fprintf_filtered (file, " %s", valid_options->name[i]); + if (valid_options->arg != NULL && valid_options->arg[i] != NULL) + fprintf_filtered (file, "%s", valid_options->arg[i]->name); if (valid_options->description[i] != NULL) - fprintf_filtered (file, "%*c %s", - (int)(max_len - strlen (valid_options->name[i])), ' ', - valid_options->description[i]); + { + size_t len = strlen (valid_options->name[i]); + + if (valid_options->arg != NULL && valid_options->arg[i] != NULL) + len += strlen (valid_options->arg[i]->name); + fprintf_filtered (file, "%*c %s", (int) (max_len - len), ' ', + valid_options->description[i]); + } fprintf_filtered (file, "\n"); } } @@ -990,12 +1063,33 @@ The following disassembler options are supported for use with the\n\ for (i = 0; valid_options->name[i] != NULL; i++) { fprintf_filtered (file, "%s", valid_options->name[i]); + if (valid_options->arg != NULL && valid_options->arg[i] != NULL) + fprintf_filtered (file, "%s", valid_options->arg[i]->name); if (valid_options->name[i + 1] != NULL) fprintf_filtered (file, ", "); wrap_here (" "); } fprintf_filtered (file, "\n"); } + + valid_args = valid_options_and_args->args; + if (valid_args != NULL) + { + size_t i, j; + + for (i = 0; valid_args[i].name != NULL; i++) + { + fprintf_filtered (file, _("\n\ + For the options above, the following values are supported for \"%s\":\n "), + valid_args[i].name); + for (j = 0; valid_args[i].values[j] != NULL; j++) + { + fprintf_filtered (file, " %s", valid_args[i].values[j]); + wrap_here (" "); + } + fprintf_filtered (file, "\n"); + } + } } /* A completion function for "set disassembler". */ @@ -1006,10 +1100,13 @@ 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); + const disasm_options_and_args_t *opts_and_args + = gdbarch_valid_disassembler_options (gdbarch); - if (opts != NULL) + if (opts_and_args != NULL) { + const disasm_options_t *opts = &opts_and_args->options; + /* Only attempt to complete on the last option text. */ const char *separator = strrchr (text, ','); if (separator != NULL) diff --git a/gdb/disasm.h b/gdb/disasm.h index 6aa046a..d71f113 100644 --- a/gdb/disasm.h +++ b/gdb/disasm.h @@ -66,6 +66,11 @@ private: /* Stores data required for disassembling instructions in opcodes. */ struct disassemble_info m_di; + + /* If we own the string in `m_di.disassembler_options', we do so + using this field. */ + std::string m_disassembler_options_holder; + CORE_ADDR m_err_memaddr; static int dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 6954398..fbdab9b 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2018-07-02 Maciej W. Rozycki <macro@mips.com> + + PR tdep/8282 + * gdb.texinfo (Source and Machine Code): Document `set + disassembler-options' support for the MIPS target. + 2018-06-28 Petr Tesarik <ptesarik@suse.cz> * gdb.texinfo (Files): Document "add-symbol-file -o offset". diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7fb6ac5..91ec219 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8759,7 +8759,7 @@ The default value is the empty string. If it is necessary to specify more than one disassembler option, then multiple options can be placed together into a comma separated list. -Currently this command is only supported on targets ARM, PowerPC +Currently this command is only supported on targets ARM, MIPS, PowerPC and S/390. @kindex show disassembler-options diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 0c8d8ee..e2abf26 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -350,8 +350,9 @@ struct gdbarch gdbarch_gcc_target_options_ftype *gcc_target_options; gdbarch_gnu_triplet_regexp_ftype *gnu_triplet_regexp; gdbarch_addressable_memory_unit_size_ftype *addressable_memory_unit_size; + const char * disassembler_options_implicit; char ** disassembler_options; - const disasm_options_t * valid_disassembler_options; + const disasm_options_and_args_t * valid_disassembler_options; gdbarch_type_align_ftype *type_align; }; @@ -707,6 +708,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of gcc_target_options, invalid_p == 0 */ /* Skip verify of gnu_triplet_regexp, invalid_p == 0 */ /* Skip verify of addressable_memory_unit_size, invalid_p == 0 */ + /* Skip verify of disassembler_options_implicit, invalid_p == 0 */ /* Skip verify of disassembler_options, invalid_p == 0 */ /* Skip verify of valid_disassembler_options, invalid_p == 0 */ /* Skip verify of type_align, invalid_p == 0 */ @@ -902,6 +904,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: disassembler_options = %s\n", pstring_ptr (gdbarch->disassembler_options)); fprintf_unfiltered (file, + "gdbarch_dump: disassembler_options_implicit = %s\n", + pstring (gdbarch->disassembler_options_implicit)); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_displaced_step_copy_insn_p() = %d\n", gdbarch_displaced_step_copy_insn_p (gdbarch)); fprintf_unfiltered (file, @@ -5044,6 +5049,23 @@ set_gdbarch_addressable_memory_unit_size (struct gdbarch *gdbarch, gdbarch->addressable_memory_unit_size = addressable_memory_unit_size; } +const char * +gdbarch_disassembler_options_implicit (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + /* Skip verify of disassembler_options_implicit, invalid_p == 0 */ + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_disassembler_options_implicit called\n"); + return gdbarch->disassembler_options_implicit; +} + +void +set_gdbarch_disassembler_options_implicit (struct gdbarch *gdbarch, + const char * disassembler_options_implicit) +{ + gdbarch->disassembler_options_implicit = disassembler_options_implicit; +} + char ** gdbarch_disassembler_options (struct gdbarch *gdbarch) { @@ -5061,7 +5083,7 @@ set_gdbarch_disassembler_options (struct gdbarch *gdbarch, gdbarch->disassembler_options = disassembler_options; } -const disasm_options_t * +const disasm_options_and_args_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); @@ -5073,7 +5095,7 @@ gdbarch_valid_disassembler_options (struct gdbarch *gdbarch) void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, - const disasm_options_t * valid_disassembler_options) + const disasm_options_and_args_t * valid_disassembler_options) { gdbarch->valid_disassembler_options = valid_disassembler_options; } diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index d13672bd..0df1fd1 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1549,11 +1549,14 @@ extern void set_gdbarch_addressable_memory_unit_size (struct gdbarch *gdbarch, g /* Functions for allowing a target to modify its disassembler options. */ +extern const char * gdbarch_disassembler_options_implicit (struct gdbarch *gdbarch); +extern void set_gdbarch_disassembler_options_implicit (struct gdbarch *gdbarch, const char * disassembler_options_implicit); + extern char ** gdbarch_disassembler_options (struct gdbarch *gdbarch); extern void set_gdbarch_disassembler_options (struct gdbarch *gdbarch, char ** disassembler_options); -extern const disasm_options_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch); -extern void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, const disasm_options_t * valid_disassembler_options); +extern const disasm_options_and_args_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch); +extern void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, const disasm_options_and_args_t * valid_disassembler_options); /* Type alignment. */ diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index c85444d..4473943 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -1157,8 +1157,9 @@ m;const char *;gnu_triplet_regexp;void;;;default_gnu_triplet_regexp;;0 m;int;addressable_memory_unit_size;void;;;default_addressable_memory_unit_size;;0 # Functions for allowing a target to modify its disassembler options. +v;const char *;disassembler_options_implicit;;;0;0;;0;pstring (gdbarch->disassembler_options_implicit) v;char **;disassembler_options;;;0;0;;0;pstring_ptr (gdbarch->disassembler_options) -v;const disasm_options_t *;valid_disassembler_options;;;0;0;;0;host_address_to_string (gdbarch->valid_disassembler_options) +v;const disasm_options_and_args_t *;valid_disassembler_options;;;0;0;;0;host_address_to_string (gdbarch->valid_disassembler_options) # Type alignment. m;ULONGEST;type_align;struct type *type;type;;default_type_align;;0 diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 32b2d40..36fae02 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -214,6 +214,18 @@ static unsigned int mips_debug = 0; struct target_desc *mips_tdesc_gp32; struct target_desc *mips_tdesc_gp64; +/* The current set of options to be passed to the disassembler. */ +static char *mips_disassembler_options; + +/* Implicit disassembler options for individual ABIs. These tell + libopcodes to use general-purpose register names corresponding + to the ABI we have selected, perhaps via a `set mips abi ...' + override, rather than ones inferred from the ABI set in the ELF + headers of the binary file selected for debugging. */ +static const char mips_disassembler_options_o32[] = "gpr-names=32"; +static const char mips_disassembler_options_n32[] = "gpr-names=n32"; +static const char mips_disassembler_options_n64[] = "gpr-names=64"; + const struct mips_regnum * mips_regnum (struct gdbarch *gdbarch) { @@ -6990,40 +7002,9 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info) memaddr &= (info->mach == bfd_mach_mips16 || info->mach == bfd_mach_mips_micromips) ? ~1 : ~3; - /* Set the disassembler options. */ - if (!info->disassembler_options) - /* This string is not recognized explicitly by the disassembler, - but it tells the disassembler to not try to guess the ABI from - the bfd elf headers, such that, if the user overrides the ABI - of a program linked as NewABI, the disassembly will follow the - register naming conventions specified by the user. */ - info->disassembler_options = "gpr-names=32"; - return default_print_insn (memaddr, info); } -static int -gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info) -{ - /* Set up the disassembler info, so that we get the right - register names from libopcodes. */ - info->disassembler_options = "gpr-names=n32"; - info->flavour = bfd_target_elf_flavour; - - return gdb_print_insn_mips (memaddr, info); -} - -static int -gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info) -{ - /* Set up the disassembler info, so that we get the right - register names from libopcodes. */ - info->disassembler_options = "gpr-names=64"; - info->flavour = bfd_target_elf_flavour; - - return gdb_print_insn_mips (memaddr, info); -} - /* Implement the breakpoint_kind_from_pc gdbarch method. */ static int @@ -8727,12 +8708,19 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info); - if (mips_abi == MIPS_ABI_N32) - set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips_n32); - else if (mips_abi == MIPS_ABI_N64) - set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips_n64); + set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips); + if (mips_abi == MIPS_ABI_N64) + set_gdbarch_disassembler_options_implicit + (gdbarch, (const char *) mips_disassembler_options_n64); + else if (mips_abi == MIPS_ABI_N32) + set_gdbarch_disassembler_options_implicit + (gdbarch, (const char *) mips_disassembler_options_n32); else - set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips); + set_gdbarch_disassembler_options_implicit + (gdbarch, (const char *) mips_disassembler_options_o32); + set_gdbarch_disassembler_options (gdbarch, &mips_disassembler_options); + set_gdbarch_valid_disassembler_options (gdbarch, + disassembler_options_mips ()); /* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint, HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 93c849c..e802927 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-07-02 Maciej W. Rozycki <macro@mips.com> + + PR tdep/8282 + * gdb.arch/mips-disassembler-options.exp: New test. + * gdb.arch/mips-disassembler-options.s: New test source. + 2018-06-29 Pedro Alves <palves@redhat.com> * gdb.threads/names.exp: Adjust expected "info threads" output. diff --git a/gdb/testsuite/gdb.arch/mips-disassembler-options.exp b/gdb/testsuite/gdb.arch/mips-disassembler-options.exp new file mode 100644 index 0000000..8db3026 --- /dev/null +++ b/gdb/testsuite/gdb.arch/mips-disassembler-options.exp @@ -0,0 +1,58 @@ +# Copyright 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test MIPS disassembler options. + +if { ![istarget "mips*-*-*"] } then { + verbose "Skipping MIPS disassembler option tests." + return +} + +standard_testfile .s +set objfile [standard_output_file ${testfile}.o] + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {}] \ + != "" } { + return +} + +clean_restart ${objfile} + +proc mips_disassemble_test { func insn mesg } { + gdb_test "disassemble $func" \ + "Dump of assembler code for function\ + $func:\r\n\[^:\]+:\t$insn\r\nEnd of assembler dump\." \ + $mesg +} + +# Verify defaults. +mips_disassemble_test foo "move\tv0,v1" "disassemble default" + +# Verify option overrides. +gdb_test "set disassembler-options gpr-names=numeric" +mips_disassemble_test foo "move\t\\\$2,\\\$3" "disassemble numeric, gpr-names" +# Check multiple options too. +gdb_test "set disassembler-options msa,reg-names=numeric,reg-names=r3000" +mips_disassemble_test foo "move\t\\\$2,\\\$3" "disassemble numeric, reg-names" + +# Verify ABI overrides. +mips_disassemble_test bar "move\t\\\$2,\\\$8" "disassemble ABI, numeric" +gdb_test "set disassembler-options" +gdb_test "set mips abi o32" +mips_disassemble_test bar "move\tv0,t0" "disassemble ABI, o32" +gdb_test "set mips abi n32" +mips_disassemble_test bar "move\tv0,a4" "disassemble ABI, n32" +gdb_test "set mips abi n64" +mips_disassemble_test bar "move\tv0,a4" "disassemble ABI, n64" diff --git a/gdb/testsuite/gdb.arch/mips-disassembler-options.s b/gdb/testsuite/gdb.arch/mips-disassembler-options.s new file mode 100644 index 0000000..6bf48cc --- /dev/null +++ b/gdb/testsuite/gdb.arch/mips-disassembler-options.s @@ -0,0 +1,30 @@ +# This test is part of GDB, the GNU debugger. +# +# Copyright 2018 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Note: this is meant to be buildable as MIPS16 or microMIPS code too. + + .globl foo + .ent foo +foo: + move $2, $3 + .end foo + + .globl bar + .ent bar +bar: + move $2, $8 + .end bar |