From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16626 invoked by alias); 23 Jan 2017 23:35:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 16601 invoked by uid 89); 23 Jan 2017 23:35:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.1 required=5.0 tests=BAYES_50,RCVD_IN_DNSWL_LOW,SPF_PASS,UNSUBSCRIBE_BODY autolearn=no version=3.3.2 spammy=1700, 3340, 4700, 5100 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Jan 2017 23:34:48 +0000 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v0NNXiRo033036 for ; Mon, 23 Jan 2017 18:34:46 -0500 Received: from e33.co.us.ibm.com (e33.co.us.ibm.com [32.97.110.151]) by mx0a-001b2d01.pphosted.com with ESMTP id 285edp1akm-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 23 Jan 2017 18:34:43 -0500 Received: from localhost by e33.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 23 Jan 2017 16:34:42 -0700 Received: from d03dlp01.boulder.ibm.com (9.17.202.177) by e33.co.us.ibm.com (192.168.1.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 23 Jan 2017 16:34:39 -0700 Received: from b03cxnp07028.gho.boulder.ibm.com (b03cxnp07028.gho.boulder.ibm.com [9.17.130.15]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id A77E41FF0021; Mon, 23 Jan 2017 16:34:17 -0700 (MST) Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v0NNYdJr14025192; Mon, 23 Jan 2017 16:34:39 -0700 Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2FA4A78038; Mon, 23 Jan 2017 16:34:39 -0700 (MST) Received: from otta.local (unknown [9.80.203.250]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP id 70A9678057; Mon, 23 Jan 2017 16:34:37 -0700 (MST) Subject: Re: [PATCH 1/2] Add support for setting disassembler-options in GDB for POWER, ARM and S390 To: Pedro Alves References: <83eg28dcjk.fsf@gnu.org> <019eaf5d-9ace-539e-8501-feb3cb0eed6c@vnet.ibm.com> Cc: Eli Zaretskii , nickc@redhat.com, gdb-patches@sourceware.org, uweigand@de.ibm.com, amodra@gmail.com, binutils@sourceware.org From: Peter Bergner Date: Mon, 23 Jan 2017 23:35:00 -0000 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17012323-0008-0000-0000-00000700F7CA X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00006486; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000200; SDB=6.00811737; UDB=6.00395796; IPR=6.00589154; BA=6.00005084; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00014019; XFM=3.00000011; UTC=2017-01-23 23:34:41 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17012323-0009-0000-0000-00003F40F38A Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2017-01-23_20:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701230293 X-IsSubscribed: yes X-SW-Source: 2017-01/txt/msg00481.txt.bz2 On 11/18/16 11:23 AM, Pedro Alves wrote: > On 11/18/2016 04:56 PM, Peter Bergner wrote: > >> diff --git a/gdb/NEWS b/gdb/NEWS >> index a597405..54a6b7b 100644 >> --- a/gdb/NEWS >> +++ b/gdb/NEWS >> @@ -36,6 +36,16 @@ >> >> Synopsys ARC arc*-*-elf32 >> >> +* New commands >> + >> +set disassembler-options >> +show disassembler-options >> + Controls the passing of target specific information to the disassembler. >> + If it is necessary to specify more than one disassembler option then >> + multiple options can be placed together into a comma separated list. >> + Default is ''. Currently the only supported targets are ARM, PowerPC >> + and S/390. >> + > > This will need a change to the GDB manual as well. It'd probably > be a good idea to refer to the -M/--disassembler-options section > of the binutils/disassembler manual for the architecture specific > options. > > It'll be good to include an arch-independent gdb test to make sure > that "set disassembler-options" on other architectures doesn't > crash and cover some corner cases. E.g., test at least both: > > "set disassembler-options" > "set disassembler-options non-existing-option" Just got back to this, sorry for taking so long. Ok, NEWS and GDB manual updated and the arch-independent test case has been added in this version. I ran this on power8 (supported arch) and an x86_64 (unsupported arch) and the new test case passes on both. I have also now included the splitting of the huge ppc test case into the smaller cpu specific tests that use the new set disassembler-options command. Ok now? Peter include/ * dis-asm.h (parse_arm_disassembler_option): Remove prototype. (set_arm_regname_option): Likewise. (disassemble_init_s390): New prototype. (disassembler_options_names_powerpc): Likewise. (disassembler_options_names_arm): Likewise. (disassembler_options_desc_arm): Likewise. (disassembler_options_names_s390): Likewise. (disassembler_options_desc_s390): Likewise. opcodes/ * disassemble.c (disassemble_init_for_target): Handle s390 init. * ppc-dis.c: Include "libiberty.h". (ppc_opts): Add "32" and "64" entries. (parse_ppc_dis_option): New function. (disassembler_options_names_powerpc): Likewise. (powerpc_init_dialect): Use parse_ppc_dis_option(). Add break to switch statement. (print_ppc_disassembler_options): Remove printing of "32" and "64". * arm-dis.c: Include "libiberty.h". (struct arm_regname): Add 'long_name' field. (regnames): Initialize it. (set_arm_regname_option): Remove function. (parse_arm_disassembler_option): Make static. (disassembler_options_names_arm): New function. (disassembler_options_desc_arm): Likewise. * s390-dis.c: Include "libiberty.h". (struct 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. (disassembler_options_names_s390): New function. (disassembler_options_desc_s390): Likewise. (print_s390_disassembler_options): Print using information from struct 'options'. gdb/ * NEWS: Mention new set/show disassembler-options commands. * doc/gdb.texinfo: Document new set/show disassembler-options commands. * gdbarch.sh (gdbarch_disassembler_options): New variable. (gdbarch_disassembler_options_names): Likewise. (gdbarch_disassembler_options_descriptions): Likewise. * gdbarch.c: Regenerate. * gdbarch.h: Likewise. * disasm.c: Include "arch-utils.h", "gdbcmd.h", "gdbcmd.h" and "safe-ctype.h". (gdb_disassemble_info): Initilize di.disassembler_options. (gdb_buffered_insn_length_init_dis): Initilize di->application_data and di->disassembler_options. (cleanup_disassembler_options): New function. (parse_disassembler_options): Likewise. (set_disassembler_options): Likewise. (show_disassembler_options): Likewise. (disassembler_options_completer): Likewise. (_initialize_disasm): Likewise. * disasm.h (set_disassembler_options): New prototype. (show_disassembler_options): Likewise. * rs6000-tdep.c (rs6000_gdbarch_init): Call set_gdbarch_disassembler_options_names. * arm-tdep.c: Include "disasm.h" and "cli/cli-decode.h". (disassembly_style): Delete static variable. (set_disassembly_style): Delete function and prototype. (show_disassembly_style_sfunc): New function. (set_disassembly_style_sfunc): Call set_disassembler_options. (arm_gdbarch_init): Call set_gdbarch_disassembler_options, set_gdbarch_disassembler_options_names and set_gdbarch_disassembler_options_descriptions. (_initialize_arm_tdep): New static variable 'disassembly_style'; Remove calls to parse_arm_disassembler_option & set_arm_regname_option. Pass show_disassembly_style_sfunc to the "disassembler" setshow command. * s390-tdep.c (s390_gdbarch_init): Call functions set_gdbarch_disassembler_options_names and set_gdbarch_disassembler_options_descriptions. gdb/testsuite/ * 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/powerpc-power.exp: Delete test. * gdb.arch/powerpc-power.s: Likewise. diff --git a/gdb/NEWS b/gdb/NEWS index 21e8cd3..cac639e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -68,6 +68,16 @@ flash-erase Erases all the flash memory regions reported by the target. This is equivalent to the CLI command flash-erase. +* New commands + +set disassembler-options +show disassembler-options + Controls the passing of target specific information to the disassembler. + If it is necessary to specify more than one disassembler option then + multiple options can be placed together into a comma separated list. + Default is ''. Currently, the only supported targets are ARM, PowerPC + and S/390. + *** Changes in GDB 7.12 * GDB and GDBserver now build with a C++ compiler by default. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dcca91b..afb9a88 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8516,7 +8516,26 @@ location of the relocation table. On some architectures, @value{GDBN} might be able to resolve these to actual function names. @table @code -@kindex set disassembly-flavor +@kindex set disassembler-options +@cindex disassembler options +@item set disassembler-options @var{option1}[,@var{option2}@dots{}] +This command controls the passing of target specific information to the +disassembler. For a list of valid options, please refer to the +@code{-M}/@code{--disassembler-options} section of the @samp{objdump} +manual and/or the output of @kbd{objdump --help}. The default value is ''. + +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 +and S/390. + +@kindex show disassembler-options +@item show disassembler-options +Show the current setting of the disassembler options. +@end table + +@table @code +@kindex set disassembler-options @cindex Intel disassembly flavor @cindex AT&T disassembly flavor @item set disassembly-flavor @var{instruction-set} diff --git a/include/dis-asm.h b/include/dis-asm.h index 4872920..6803588 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -332,14 +332,18 @@ extern void print_ppc_disassembler_options (FILE *); extern void print_riscv_disassembler_options (FILE *); extern void print_arm_disassembler_options (FILE *); extern void print_arc_disassembler_options (FILE *); -extern void parse_arm_disassembler_option (char *); extern void print_s390_disassembler_options (FILE *); extern int get_arm_regname_num_options (void); -extern int set_arm_regname_option (int); extern int get_arm_regnames (int, const char **, const char **, const char *const **); extern bfd_boolean aarch64_symbol_is_valid (asymbol *, struct disassemble_info *); extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *); extern void disassemble_init_powerpc (struct disassemble_info *); +extern void disassemble_init_s390 (struct disassemble_info *); +extern const char **disassembler_options_names_powerpc (void); +extern const char **disassembler_options_names_arm (void); +extern const char **disassembler_options_desc_arm (void); +extern const char **disassembler_options_names_s390 (void); +extern const char **disassembler_options_desc_s390 (void); /* Fetch the disassembler for a given BFD, if that support is available. */ extern disassembler_ftype disassembler (bfd *); diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 2987403..548a3d5 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -26,6 +26,7 @@ #include "opcode/arm.h" #include "opintl.h" #include "safe-ctype.h" +#include "libiberty.h" #include "floatformat.h" /* FIXME: This shouldn't be done here. */ @@ -3191,6 +3192,7 @@ static const char *const arm_shift[] = typedef struct { const char *name; + const char *long_name; const char *description; const char *reg_names[16]; } @@ -3198,17 +3200,17 @@ arm_regname; static const arm_regname regnames[] = { - { "raw" , "Select raw register names", + { "raw" , "reg-names-raw", "Select raw register names", { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, - { "gcc", "Select register names used by GCC", + { "gcc", "reg-names-gcc", "Select register names used by GCC", { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, - { "std", "Select register names used in ARM's ISA documentation", + { "std", "reg-names-std", "Select register names used in ARM's ISA documentation", { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, - { "apcs", "Select register names used in the APCS", + { "apcs", "reg-names-apcs", "Select register names used in the APCS", { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, - { "atpcs", "Select register names used in the ATPCS", + { "atpcs", "reg-names-atpcs", "Select register names used in the ATPCS", { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, - { "special-atpcs", "Select special register names used in the ATPCS", + { "special-atpcs", "reg-names-special-atpcs", "Select special register names used in the ATPCS", { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}, }; @@ -3261,14 +3263,6 @@ get_arm_regname_num_options (void) } int -set_arm_regname_option (int option) -{ - int old = regname_selected; - regname_selected = option; - return old; -} - -int get_arm_regnames (int option, const char **setname, const char **setdescription, @@ -6126,7 +6120,7 @@ arm_symbol_is_valid (asymbol * sym, /* Parse an individual disassembler option. */ -void +static void parse_arm_disassembler_option (char *option) { if (option == NULL) @@ -6842,6 +6836,46 @@ print_insn_little_arm (bfd_vma pc, struct disassemble_info *info) return print_insn (pc, info, TRUE); } +const char ** +disassembler_options_names_arm (void) +{ + static const char **options = NULL; + + if (options == NULL) + { + size_t i; + size_t num_options = NUM_ARM_REGNAMES + 2; + options = XNEWVEC (const char *, num_options + 1); + for (i = 0; i < NUM_ARM_REGNAMES; i++) + options[i] = regnames[i].long_name; + options[i++] = "force-thumb"; + options[i++] = "no-force-thumb"; + options[i] = NULL; + } + + return options; +} + +const char ** +disassembler_options_desc_arm (void) +{ + static const char **desc = NULL; + + if (desc == NULL) + { + size_t i; + size_t num_desc = NUM_ARM_REGNAMES + 2; + desc = XNEWVEC (const char *, num_desc + 1); + for (i = 0; i < NUM_ARM_REGNAMES; i++) + desc[i] = regnames[i].description; + desc[i++] = "Assume all insns are Thumb insns"; + desc[i++] = "Examine preceding label to determine an insn's type"; + desc[i] = NULL; + } + + return desc; +} + void print_arm_disassembler_options (FILE *stream) { diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 1b15242..81e9136 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -649,6 +649,11 @@ disassemble_init_for_target (struct disassemble_info * info) disassemble_init_powerpc (info); break; #endif +#ifdef ARCH_s390 + case bfd_arch_s390: + disassemble_init_s390 (info); + break; +#endif default: break; } diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index e0eff7a..b866c6d 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -26,6 +26,7 @@ #include "elf/ppc.h" #include "opintl.h" #include "opcode/ppc.h" +#include "libiberty.h" /* This file provides several disassembler functions, all of which use the disassembler interface defined in dis-asm.h. Several functions @@ -172,8 +173,12 @@ struct ppc_mopt ppc_opts[] = { 0 }, { "ppc32", PPC_OPCODE_PPC, 0 }, + { "32", PPC_OPCODE_PPC, + 0 }, { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64, 0 }, + { "64", PPC_OPCODE_PPC | PPC_OPCODE_64, + 0 }, { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE, 0 }, { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS, @@ -271,6 +276,27 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg) return ppc_cpu; } +/* Parse the OPTIONS argument looking for ',' seperated cpu names. + Return the length of the current option, or 0 if there are no more. + Update OPTIONS to point to the next option, or NULL otherwise. */ + +static char * +parse_ppc_dis_option (char *cpu, const char *options) +{ + char *next = strchr (options, ','); + + if (next != NULL) + { + strncpy (cpu, options, (size_t) (next - options)); + cpu[(size_t) (next - options)] = 0; + next++; + } + else + strcpy (cpu, options); + + return next; +} + /* Determine which set of machines to disassemble for. */ static void @@ -324,29 +350,24 @@ powerpc_init_dialect (struct disassemble_info *info) break; default: dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY; + break; } arg = info->disassembler_options; while (arg != NULL) { ppc_cpu_t new_cpu = 0; - char *end = strchr (arg, ','); + char opt[64]; + arg = parse_ppc_dis_option (opt, arg); - if (end != NULL) - *end = 0; - - if ((new_cpu = ppc_parse_cpu (dialect, &sticky, arg)) != 0) - dialect = new_cpu; - else if (strcmp (arg, "32") == 0) + if (strcmp (opt, "32") == 0) dialect &= ~(ppc_cpu_t) PPC_OPCODE_64; - else if (strcmp (arg, "64") == 0) + else if (strcmp (opt, "64") == 0) dialect |= PPC_OPCODE_64; + else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0) + dialect = new_cpu; else - fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg); - - if (end != NULL) - *end++ = ','; - arg = end; + fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), opt); } info->private_data = priv; @@ -767,6 +788,24 @@ print_insn_powerpc (bfd_vma memaddr, return 4; } +const char ** +disassembler_options_names_powerpc (void) +{ + static const char **options = NULL; + + if (options == NULL) + { + size_t i; + size_t num_options = sizeof (ppc_opts) / sizeof (ppc_opts[0]); + options = XNEWVEC (const char *, num_options + 1); + for (i = 0; i < num_options; i++) + options[i] = ppc_opts[i].opt; + options[i] = NULL; + } + + return options; +} + void print_ppc_disassembler_options (FILE *stream) { @@ -785,5 +824,5 @@ the -M switch:\n")); col = 0; } } - fprintf (stream, " 32, 64\n"); + fprintf (stream, "\n"); } diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c index 328ba2d..6b455aa 100644 --- a/opcodes/s390-dis.c +++ b/opcodes/s390-dis.c @@ -25,16 +25,30 @@ #include "dis-asm.h" #include "opintl.h" #include "opcode/s390.h" +#include "libiberty.h" -static int init_flag = 0; static int opc_index[256]; static int current_arch_mask = 0; static int option_use_insn_len_bits_p = 0; +typedef struct +{ + const char *name; + const char *description; +} options_t; + +static const options_t options[] = +{ + { "esa" , "Disassemble in ESA architecture mode" }, + { "zarch", "Disassemble in z/Architecture mode" }, + { "insnlength", "Print unknown instructions according to " + "length from first two bits" } +}; + /* Set up index table for first opcode byte. */ -static void -init_disasm (struct disassemble_info *info) +void +disassemble_init_s390 (struct disassemble_info *info) { int i; const char *p; @@ -46,6 +60,9 @@ init_disasm (struct disassemble_info *info) for (i = s390_num_opcodes; i--; ) opc_index[s390_opcodes[i].opcode[0]] = i; + current_arch_mask = 1 << S390_OPCODE_ZARCH; + option_use_insn_len_bits_p = 0; + for (p = info->disassembler_options; p != NULL; ) { if (CONST_STRNEQ (p, "esa")) @@ -61,11 +78,6 @@ init_disasm (struct disassemble_info *info) if (p != NULL) p++; } - - if (!current_arch_mask) - current_arch_mask = 1 << S390_OPCODE_ZARCH; - - init_flag = 1; } /* Derive the length of an instruction from its first byte. */ @@ -266,9 +278,6 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info) unsigned int value; int status, opsize, bufsize, bytes_to_dump, i; - if (init_flag == 0) - init_disasm (info); - /* The output looks better if we put 6 bytes on a line. */ info->bytes_per_line = 6; @@ -360,15 +369,58 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info) return 0; } +const char ** +disassembler_options_names_s390 (void) +{ + static const char **opts = NULL; + + if (opts == NULL) + { + size_t i, num_options = sizeof (options) / sizeof (options[0]); + opts = XNEWVEC (const char *, num_options); + for (i = 0; i < num_options; i++) + opts[i] = options[i].name; + opts[i] = NULL; + } + + return opts; +} + +const char ** +disassembler_options_desc_s390 (void) +{ + static const char **desc = NULL; + + if (desc == NULL) + { + size_t i, num_options = sizeof (options) / sizeof (options[0]); + desc = XNEWVEC (const char *, num_options + 1); + for (i = 0; i < num_options; i++) + desc[i] = options[i].description; + desc[i] = NULL; + } + + return desc; +} + void print_s390_disassembler_options (FILE *stream) { + unsigned int i, max_len = 0; fprintf (stream, _("\n\ The following S/390 specific disassembler options are supported for use\n\ with the -M switch (multiple options should be separated by commas):\n")); - fprintf (stream, _(" esa Disassemble in ESA architecture mode\n")); - fprintf (stream, _(" zarch Disassemble in z/Architecture mode\n")); - fprintf (stream, _(" insnlength Print unknown instructions according " - "to length from first two bits\n")); + for (i = 0; sizeof (options) / sizeof (options[0]); i++) + { + unsigned int len = strlen (options[i].name); + if (max_len < len) + max_len = len; + } + + for (i = 0, max_len++; sizeof (options) / sizeof (options[0]); i++) + fprintf (stream, " %s%*c %s", + options[i].name, + (int)(max_len - strlen (options[i].name)), ' ', + options[i].description); } diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 2bdfa57..bd6fa72 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -27,6 +27,8 @@ #include "gdbcmd.h" #include "gdbcore.h" #include "dis-asm.h" /* For register styles. */ +#include "disasm.h" +#include "cli/cli-decode.h" #include "regcache.h" #include "reggroups.h" #include "doublest.h" @@ -210,14 +212,13 @@ static const char *const arm_register_names[] = /* Valid register name styles. */ static const char **valid_disassembly_styles; -/* Disassembly style to use. Default to "std" register names. */ -static const char *disassembly_style; - /* This is used to keep the bfd arch_info in sync with the disassembly style. */ static void set_disassembly_style_sfunc(char *, int, struct cmd_list_element *); -static void set_disassembly_style (void); +static void show_disassembly_style_sfunc (struct ui_file *, int, + struct cmd_list_element *, + const char *); static void convert_from_extended (const struct floatformat *, const void *, void *, int); @@ -8536,9 +8537,27 @@ arm_show_force_mode (struct ui_file *file, int from_tty, static void set_disassembly_style_sfunc (char *args, int from_tty, - struct cmd_list_element *c) + struct cmd_list_element *c) +{ + /* Convert the short style name into the long style name (eg, reg-names-*) + before calling the generic set_disassembler_options() function. */ + char long_name[256], *style = long_name; + snprintf (style, 256, "reg-names-%s", *(char **)c->var); + c->var = &style; + set_disassembler_options (args, from_tty, c); +} + +static void +show_disassembly_style_sfunc (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) { - set_disassembly_style (); + struct gdbarch *gdbarch = get_current_arch (); + const char *style = gdbarch_disassembler_options (gdbarch); + if (style == NULL) + style = "default"; + else if (CONST_STRNEQ (style, "reg-names-")) + style += strlen ("reg-names-"); + fprintf_unfiltered (file, "The disassembly style is \"%s\".\n", style); } /* Return the ARM register name corresponding to register I. */ @@ -8579,21 +8598,6 @@ arm_register_name (struct gdbarch *gdbarch, int i) return arm_register_names[i]; } -static void -set_disassembly_style (void) -{ - int current; - - /* Find the style that the user wants. */ - for (current = 0; current < num_disassembly_options; current++) - if (disassembly_style == valid_disassembly_styles[current]) - break; - gdb_assert (current < num_disassembly_options); - - /* Synchronize the disassembler. */ - set_arm_regname_option (current); -} - /* Test whether the coff symbol specific value corresponds to a Thumb function. */ @@ -9553,6 +9557,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) user_reg_add (gdbarch, arm_register_aliases[i].name, value_of_arm_user_reg, &arm_register_aliases[i].regnum); + set_gdbarch_disassembler_options (gdbarch, xstrdup ("reg-names-std")); + set_gdbarch_disassembler_options_names (gdbarch, + disassembler_options_names_arm ()); + set_gdbarch_disassembler_options_descriptions + (gdbarch, disassembler_options_desc_arm ()); + return gdbarch; } @@ -9573,6 +9583,9 @@ extern initialize_file_ftype _initialize_arm_tdep; /* -Wmissing-prototypes */ void _initialize_arm_tdep (void) { + /* Disassembly style to use. Default to "std" register names. */ + static const char *disassembly_style; + struct ui_file *stb; long length; const char *setname; @@ -9619,9 +9632,6 @@ _initialize_arm_tdep (void) _("Various ARM-specific commands."), &showarmcmdlist, "show arm ", 0, &showlist); - /* Sync the opcode insn printer with our register viewer. */ - parse_arm_disassembler_option ("reg-names-std"); - /* Initialize the array that will be passed to add_setshow_enum_cmd(). */ valid_disassembly_styles = XNEWVEC (const char *, @@ -9633,13 +9643,6 @@ _initialize_arm_tdep (void) length = snprintf (rdptr, rest, "%s - %s\n", setname, setdesc); rdptr += length; rest -= length; - /* When we find the default names, tell the disassembler to use - them. */ - if (!strcmp (setname, "std")) - { - disassembly_style = setname; - set_arm_regname_option (i); - } } /* Mark the end of valid options. */ valid_disassembly_styles[num_disassembly_options] = NULL; @@ -9659,8 +9662,7 @@ _initialize_arm_tdep (void) _("Show the disassembly style."), helptext.c_str (), set_disassembly_style_sfunc, - NULL, /* FIXME: i18n: The disassembly style is - \"%s\". */ + show_disassembly_style_sfunc, &setarmcmdlist, &showarmcmdlist); add_setshow_boolean_cmd ("apcs32", no_class, &arm_apcs_32, diff --git a/gdb/disasm.c b/gdb/disasm.c index f419501..a6355aa 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -18,13 +18,17 @@ along with this program. If not, see . */ #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 "cli/cli-decode.h" #include "source.h" +#include "safe-ctype.h" #include /* Disassemble functions. @@ -778,6 +782,7 @@ gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) di.endian = gdbarch_byte_order (gdbarch); di.endian_code = gdbarch_byte_order_for_code (gdbarch); di.application_data = gdbarch; + di.disassembler_options = gdbarch_disassembler_options (gdbarch); disassemble_init_for_target (&di); return di; } @@ -894,6 +899,8 @@ 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->application_data = gdbarch; + di->disassembler_options = gdbarch_disassembler_options (gdbarch); disassemble_init_for_target (di); } @@ -910,3 +917,226 @@ gdb_buffered_insn_length (struct gdbarch *gdbarch, return gdbarch_print_insn (gdbarch, addr, &di); } + +/* Remove whitespace and consecutive commas from OPTIONS. */ + +char * +cleanup_disassembler_options (char *options) +{ + char *str; + size_t i, len; + + if (options == NULL) + return NULL; + + /* Strip off all trailing whitespace and commas. */ + for (len = strlen (options); len > 0; len--) + { + if (!ISSPACE (options[len - 1]) && options[len - 1] != ',') + break; + options[len - 1] = '\0'; + } + + /* Convert all remaining whitespace to commas. */ + for (i = 0; options[i] != '\0'; i++) + if (ISSPACE (options[i])) + options[i] = ','; + + /* Remove consecutive commas. */ + for (str = options; *str != '\0'; str++) + if (*str == ',' && *(str + 1) == ',') + { + char *next = str++; + while (*next == ',') + next++; + len = strlen (next); + memmove (str, next, len); + next[len - (size_t)(next - str)] = '\0'; + } + return (strlen (options) != 0) ? options : NULL; +} + +/* Parse OPTIONS looking for ',' seperated disassembler options and + verify each option is valid. Return NULL if all options are valid. + Otherwise, return a pointer to the first invalid disassembler option. */ + +static char * +parse_disassembler_options (const char *options, const char **valid_names) +{ + static char opt[256]; + size_t i; + + if (options == NULL) + return NULL; + + while (*options) + { + /* Copy the current disassembler option into OPT. */ + const char *separator = strchr (options, ','); + if (separator != NULL) + { + strncpy (opt, options, (size_t) (separator - options)); + opt[(size_t) (separator - options)] = 0; + options = separator; + /* Skip to the next disassembler option. */ + while (*options == ',') + options++; + } + else + options = stpcpy (opt, options); + + /* Verify OPT is a valid disassembler option. */ + for (i = 0; valid_names[i] != NULL; i++) + if (strcmp (opt, valid_names[i]) == 0) + break; + if (valid_names[i] == NULL) + return opt; + } + + return NULL; +} + +void +set_disassembler_options (char *args, int from_tty, struct cmd_list_element *c) +{ + struct gdbarch *gdbarch = get_current_arch (); + char *options = cleanup_disassembler_options (*(char **)c->var); + + if (options == NULL) + { + free (gdbarch_disassembler_options (gdbarch)); + set_gdbarch_disassembler_options (gdbarch, NULL); + return; + } + + const char **valid_names = gdbarch_disassembler_options_names (gdbarch); + if (valid_names == NULL) + { + fprintf_filtered (gdb_stdlog, _("\ +'set disassembler-options ...' is not supported on this architecture.\n")); + return; + } + + char *opt = parse_disassembler_options (options, valid_names); + if (opt != NULL) + { + fprintf_filtered (gdb_stdlog, + _("Invalid disassembler option value: '%s'.\n"), opt); + return; + } + + free (gdbarch_disassembler_options (gdbarch)); + set_gdbarch_disassembler_options (gdbarch, xstrdup (options)); +} + +void +show_disassembler_options (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + struct gdbarch *gdbarch = get_current_arch (); + + const char *options = gdbarch_disassembler_options (gdbarch); + if (options == NULL) + options = ""; + + fprintf_filtered (file, _("The current disassembler options are '%s'\n"), + options); + + const char **names = gdbarch_disassembler_options_names (gdbarch); + const char **desc = gdbarch_disassembler_options_descriptions (gdbarch); + + if (names == NULL) + return; + + fprintf_filtered (file, _("\n\ +The following disassembler options are supported for use with\n\ +the 'set disassembler-options