From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 104638 invoked by alias); 10 Oct 2016 23:28:32 -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 104614 invoked by uid 89); 10 Oct 2016 23:28:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW,RCVD_IN_SEMBACKSCATTER,SPF_PASS autolearn=ham version=3.3.2 spammy=Prototype, INFO, priv, power9 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Oct 2016 23:28:21 +0000 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id u9ANO97r073441 for ; Mon, 10 Oct 2016 19:28:19 -0400 Received: from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158]) by mx0b-001b2d01.pphosted.com with ESMTP id 260g7uspc8-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 10 Oct 2016 19:28:19 -0400 Received: from localhost by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 10 Oct 2016 17:28:18 -0600 Received: from d03dlp02.boulder.ibm.com (9.17.202.178) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 10 Oct 2016 17:28:16 -0600 Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id 15B4D3E40030; Mon, 10 Oct 2016 17:28:16 -0600 (MDT) Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u9ANSG7e14877068; Mon, 10 Oct 2016 16:28:16 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B0335C6037; Mon, 10 Oct 2016 17:28:15 -0600 (MDT) Received: from otta.local (unknown [9.85.164.102]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id A9A18C603E; Mon, 10 Oct 2016 17:28:14 -0600 (MDT) Subject: Re: [PATCH, RFC] Add support for choosing disassembler cpu in GDB for POWER. To: Ulrich Weigand References: <20161007192106.D516E10C1FE@oc8523832656.ibm.com> Cc: Pedro Alves , Alan Modra , gdb-patches@sourceware.org, binutils From: Peter Bergner Date: Mon, 10 Oct 2016 23:28:00 -0000 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <20161007192106.D516E10C1FE@oc8523832656.ibm.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16101023-0024-0000-0000-000014C0F7A0 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00005888; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000186; SDB=6.00766648; UDB=6.00366714; IPR=6.00542782; BA=6.00004799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00012941; XFM=3.00000011; UTC=2016-10-10 23:28:18 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16101023-0025-0000-0000-00004534577E Message-Id: <25537872-c66e-f92d-aa28-cedb9df0f1a6@vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2016-10-10_11:,, 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-1609300000 definitions=main-1610100391 X-IsSubscribed: yes X-SW-Source: 2016-10/txt/msg00239.txt.bz2 On 10/7/16 2:21 PM, Ulrich Weigand wrote: > There's a second use of disassemble_init_for_target, which probably needs > the same treatment. In fact, maybe the nicest way would be to call the > callback "gdbarch_disassemble_init_for_target", with a default of simply > disassemble_init_for_target, but which targets can override to do extra > stuff before (or after) calling disassemble_init_for_target in there. > GDB common code would then just call gdbarch_disassemble_init_for_target > everywhere it currently calls disassemble_init_for_target. Ok, I think this resolves all of your last suggestions. Is this better? Peter include/ * dis-asm.h (ppc_verify_disassembler_options): New prototype. opcodes/ * ppc-dis.c (parse_ppc_dis_option): New function. (ppc_verify_disassembler_options): Likewise. (powerpc_init_dialect): Use parse_ppc_dis_option(). gdb/ * gdbarch.sh (gdbarch_disassemble_init_for_target): New function. * gdbarch.c: Regenerate. * gdbarch.h: Likewise. * disasm.c (gdb_disassemble_info): Use it. (gdb_buffered_insn_length_init_dis): Likewise. * rs6000-tdep.c: (gdb_disassembler_cpu): New static declaration. (prospective_cpu): Likewise. (gdb_disassemble_init_for_ppc): New function. (set_disassembler_cpu): Likewise. (show_disassembler_cpu): Likewise. (rs6000_gdbarch_init): Setup callback for gdb_disassemble_init_for_ppc. (_initialize_rs6000_tdep): Setup callbacks for set_disassembler_cpu() and show_disassembler_cpu(). * arch-utils.c: Include "dis-asm.h". (default_disassemble_init_for_target): New function. * arch-utils.h (default_disassemble_init_for_target): New Prototype. diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 776dabc..68fc610 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -32,6 +32,7 @@ #include "objfiles.h" #include "language.h" #include "symtab.h" +#include "dis-asm.h" #include "version.h" @@ -931,6 +932,15 @@ default_addressable_memory_unit_size (struct gdbarch *gdbarch) return 1; } +/* Default method for gdbarch_disassemble_init_for_target. */ + +void +default_disassemble_init_for_target (struct gdbarch *gdbarch, + struct disassemble_info *info) +{ + disassemble_init_for_target (info); +} + void default_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index bbb0878..94da918 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -211,6 +211,8 @@ extern void default_infcall_munmap (CORE_ADDR addr, CORE_ADDR size); extern char *default_gcc_target_options (struct gdbarch *gdbarch); extern const char *default_gnu_triplet_regexp (struct gdbarch *gdbarch); extern int default_addressable_memory_unit_size (struct gdbarch *gdbarch); +extern void default_disassemble_init_for_target (struct gdbarch *, + struct disassemble_info *); extern void default_guess_tracepoint_registers (struct gdbarch *gdbarch, struct regcache *regcache, diff --git a/gdb/disasm.c b/gdb/disasm.c index 07c3abe..b6d573e 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -785,7 +785,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; - disassemble_init_for_target (&di); + gdbarch_disassemble_init_for_target (gdbarch, &di); return di; } @@ -901,7 +901,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); - disassemble_init_for_target (di); + gdbarch_disassemble_init_for_target (gdbarch, di); } /* Return the length in bytes of INSN. MAX_LEN is the size of the diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 4d8ef18..c0ff86b 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -337,6 +337,7 @@ 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; + gdbarch_disassemble_init_for_target_ftype *disassemble_init_for_target; }; /* Create a new ``struct gdbarch'' based on information provided by @@ -443,6 +444,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->gcc_target_options = default_gcc_target_options; gdbarch->gnu_triplet_regexp = default_gnu_triplet_regexp; gdbarch->addressable_memory_unit_size = default_addressable_memory_unit_size; + gdbarch->disassemble_init_for_target = default_disassemble_init_for_target; /* gdbarch_alloc() */ return gdbarch; @@ -691,6 +693,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 disassemble_init_for_target, invalid_p == 0 */ buf = ui_file_xstrdup (log, &length); make_cleanup (xfree, buf); if (length > 0) @@ -871,6 +874,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: deprecated_function_start_offset = %s\n", core_addr_to_string_nz (gdbarch->deprecated_function_start_offset)); fprintf_unfiltered (file, + "gdbarch_dump: disassemble_init_for_target = <%s>\n", + host_address_to_string (gdbarch->disassemble_init_for_target)); + fprintf_unfiltered (file, "gdbarch_dump: gdbarch_displaced_step_copy_insn_p() = %d\n", gdbarch_displaced_step_copy_insn_p (gdbarch)); fprintf_unfiltered (file, @@ -4918,6 +4924,23 @@ set_gdbarch_addressable_memory_unit_size (struct gdbarch *gdbarch, gdbarch->addressable_memory_unit_size = addressable_memory_unit_size; } +void +gdbarch_disassemble_init_for_target (struct gdbarch *gdbarch, struct disassemble_info *info) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->disassemble_init_for_target != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_disassemble_init_for_target called\n"); + gdbarch->disassemble_init_for_target (gdbarch, info); +} + +void +set_gdbarch_disassemble_init_for_target (struct gdbarch *gdbarch, + gdbarch_disassemble_init_for_target_ftype disassemble_init_for_target) +{ + gdbarch->disassemble_init_for_target = disassemble_init_for_target; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index cd01718..e90931d 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1530,6 +1530,12 @@ typedef int (gdbarch_addressable_memory_unit_size_ftype) (struct gdbarch *gdbarc extern int gdbarch_addressable_memory_unit_size (struct gdbarch *gdbarch); extern void set_gdbarch_addressable_memory_unit_size (struct gdbarch *gdbarch, gdbarch_addressable_memory_unit_size_ftype *addressable_memory_unit_size); +/* Function for allowing a target to modify its disassembler options. */ + +typedef void (gdbarch_disassemble_init_for_target_ftype) (struct gdbarch *gdbarch, struct disassemble_info *info); +extern void gdbarch_disassemble_init_for_target (struct gdbarch *gdbarch, struct disassemble_info *info); +extern void set_gdbarch_disassemble_init_for_target (struct gdbarch *gdbarch, gdbarch_disassemble_init_for_target_ftype *disassemble_init_for_target); + /* Definition for an unknown syscall, used basically in error-cases. */ #define UNKNOWN_SYSCALL (-1) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 1663156..d0234c1 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -1152,6 +1152,9 @@ m:const char *:gnu_triplet_regexp:void:::default_gnu_triplet_regexp::0 # each address in memory. m:int:addressable_memory_unit_size:void:::default_addressable_memory_unit_size::0 +# Function for allowing a target to modify its disassembler options. +m:void:disassemble_init_for_target:struct disassemble_info *info:info:0:default_disassemble_init_for_target::0 + EOF } diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index ca4d668..a52e7a9 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -127,6 +127,10 @@ static const char *const powerpc_vector_strings[] = static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO; static const char *powerpc_vector_abi_string = "auto"; +/* This is the variable that is set with "set powerpc disassembler". */ +static char *gdb_disassembler_cpu; +static char *prospective_cpu; + /* To be used by skip_prologue. */ struct rs6000_framedata @@ -5924,6 +5928,14 @@ UNKNOWN_OP: return 0; } +static void +gdb_disassemble_init_for_ppc (struct gdbarch *gdbarch, + disassemble_info *info) +{ + info->disassembler_options = gdb_disassembler_cpu; + disassemble_init_for_target (info); +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -6597,6 +6609,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else register_ppc_ravenscar_ops (gdbarch); + set_gdbarch_disassemble_init_for_target (gdbarch, gdb_disassemble_init_for_ppc); + return gdbarch; } @@ -6676,6 +6690,32 @@ show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value); } +static void +set_disassembler_cpu (char *args, int from_tty, struct cmd_list_element *c) +{ + char *opt; + if ((opt = ppc_verify_disassembler_options (prospective_cpu)) != NULL) + { + fprintf_filtered (gdb_stdlog, + _("Invalid disasembler-cpu value: '%s'.\n"), opt); + return; + } + if (gdb_disassembler_cpu) + free (gdb_disassembler_cpu); + gdb_disassembler_cpu = strdup (prospective_cpu); +} + +static void +show_disassembler_cpu (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + const char *cpu = (gdb_disassembler_cpu) ? gdb_disassembler_cpu : "default"; + fprintf_filtered (file, _("\ +The current disassembler cpu is '%s'\n\n\ +See objdump's -M option for the list of supported PPC specific\n\ +disassembler options.\n"), cpu); +} + /* Read a PPC instruction from memory. */ static unsigned int @@ -6796,6 +6836,17 @@ _initialize_rs6000_tdep (void) powerpc_set_soft_float, NULL, &setpowerpccmdlist, &showpowerpccmdlist); + /* Add the command that controls the disassembler cpu. */ + add_setshow_string_cmd ("disassembler", no_class, + &prospective_cpu, _("\ +Set the disassembler cpu.\n\ +Usage: set powerpc disassembler [,]*\n\ +See objdump's -M option for the valid names."), _("\ +Show the disassembler cpu."), NULL, + set_disassembler_cpu, + show_disassembler_cpu, + &setpowerpccmdlist, &showpowerpccmdlist); + add_setshow_enum_cmd ("vector-abi", class_support, powerpc_vector_strings, &powerpc_vector_abi_string, _("Set the vector ABI."), diff --git a/include/dis-asm.h b/include/dis-asm.h index 05bfa37..15573d9 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -337,6 +337,7 @@ extern int get_arm_regnames (int, const char **, const char **, const char *con 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 char *ppc_verify_disassembler_options (char *); /* Fetch the disassembler for a given BFD, if that support is available. */ extern disassembler_ftype disassembler (bfd *); diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index da1301e..feac2bf 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -271,6 +271,50 @@ 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. + The first cpu name is copied into CPU and a pointer to the + next name is returned or NULL if there are no more cpu names. + CPU must contain enough space to hold the cpu name. */ + +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; +} + +/* Parse OPTIONS looking for ',' seperated cpu names and verify each name + is valid. Return NULL if all names are valid. Otherwise, return a + pointer to the first invalid cpu name. */ + +char * +ppc_verify_disassembler_options (char *options) +{ + static char opt[32]; + while (options != NULL) + { + unsigned int i; + options = parse_ppc_dis_option (opt, options); + + for (i = 0; ppc_opts[i].opt; i++) + if (strcmp (ppc_opts[i].opt, opt) == 0) + break; + if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0])) + return opt; + } + return NULL; +} + /* Determine which set of machines to disassemble for. */ static void @@ -324,29 +368,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) + if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0) dialect = new_cpu; - else if (strcmp (arg, "32") == 0) + else 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 - 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;