From patchwork Thu Jun 16 06:02:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 13128 Received: (qmail 19123 invoked by alias); 16 Jun 2016 06:11:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 19000 invoked by uid 89); 16 Jun 2016 06:11:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.0 required=5.0 tests=AWL, BAYES_50, SPF_HELO_PASS, SPF_SOFTFAIL autolearn=no version=3.3.2 spammy=Effective, auxiliary, Frequency, fbsdnatc X-Spam-User: qpsmtpd, 2 recipients X-HELO: bigwig.baldwin.cx Received: from bigwig.baldwin.cx (HELO bigwig.baldwin.cx) (96.47.65.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 16 Jun 2016 06:11:21 +0000 Received: from ralph.baldwin.cx.net (c-73-231-226-104.hsd1.ca.comcast.net [73.231.226.104]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 8F101B9C0; Thu, 16 Jun 2016 02:02:19 -0400 (EDT) From: John Baldwin To: gdb-patches@sourceware.org, binutils@sourceware.org Subject: [PATCH 5/6] Add a new gdbarch method to print a single AUXV entry. Date: Wed, 15 Jun 2016 23:02:01 -0700 Message-Id: <20160616060202.63470-6-jhb@FreeBSD.org> In-Reply-To: <20160616060202.63470-1-jhb@FreeBSD.org> References: <20160616060202.63470-1-jhb@FreeBSD.org> X-IsSubscribed: yes Different platforms have different meanings for auxiliary vector entries. The 'print_auxv' gdbarch method allows an architecture to output a suitable description for platform-specific entries. A fprint_single_auxv function is split out of fprint_target_auxv. This function outputs the description of a single auxiliary vector entry to the specified file using caller-supplied formatting and strings to describe the vector type. The existing switch on auxiliary vector types is moved out of fprint_target_auxv into a new default_print_auxv function. default_print_auxv chooses an appropriate format and description and calls fprint_single_auxv to describe a single vector entry. fprint_target_auxv now invokes the gdbarch 'print_auxv' function on each vector entry. If the function is not present or returns zero, default_printf_auxv is called to output a description for the vector. gdb/ChangeLog: * auxv.c (fprint_single_auxv): New function. (default_print_auxv): New function. (fprint_target_auxv): Use gdbarch_print_auxv and default_print_auxv. * auxv.h (enum auxv_format): New enum. (fprint_single_auxv): Declare. * gdbarch.sh (print_auxv): New. * gdbarch.c, gdbarch.h: Re-generated. --- gdb/ChangeLog | 10 +++ gdb/auxv.c | 191 +++++++++++++++++++++++++++++++-------------------------- gdb/auxv.h | 8 +++ gdb/gdbarch.c | 32 ++++++++++ gdb/gdbarch.h | 11 ++++ gdb/gdbarch.sh | 6 ++ 6 files changed, 172 insertions(+), 86 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b11174c..2426a2f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2016-06-15 John Baldwin + * auxv.c (fprint_single_auxv): New function. + (default_print_auxv): New function. + (fprint_target_auxv): Use gdbarch_print_auxv and default_print_auxv. + * auxv.h (enum auxv_format): New enum. + (fprint_single_auxv): Declare. + * gdbarch.sh (print_auxv): New. + * gdbarch.c, gdbarch.h: Re-generated. + +2016-06-15 John Baldwin + * fbsd-nat.c [KERN_PROC_AUXV] New variable super_xfer_partial. (fbsd_xfer_partial): New function. (fbsd_nat_add_target) [KERN_PROC_AUXV] Set "to_xfer_partial" to diff --git a/gdb/auxv.c b/gdb/auxv.c index 396862e..275c23e 100644 --- a/gdb/auxv.c +++ b/gdb/auxv.c @@ -407,10 +407,112 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) } +/* Print a description of a single AUXV entry on the specified file. */ +void +fprint_single_auxv (struct ui_file *file, const char *name, + const char *description, enum auxv_format flavor, + CORE_ADDR type, CORE_ADDR val) +{ + fprintf_filtered (file, "%-4s %-20s %-30s ", + plongest (type), name, description); + switch (flavor) + { + case dec: + fprintf_filtered (file, "%s\n", plongest (val)); + break; + case hex: + fprintf_filtered (file, "%s\n", paddress (target_gdbarch (), val)); + break; + case str: + { + struct value_print_options opts; + + get_user_print_options (&opts); + if (opts.addressprint) + fprintf_filtered (file, "%s ", paddress (target_gdbarch (), val)); + val_print_string (builtin_type (target_gdbarch ())->builtin_char, + NULL, val, -1, file, &opts); + fprintf_filtered (file, "\n"); + } + break; + } +} + +static void +default_print_auxv (struct ui_file *file, CORE_ADDR type, CORE_ADDR val) +{ + const char *name = "???"; + const char *description = ""; + enum auxv_format flavor = hex; + + switch (type) + { +#define TAG(tag, text, kind) \ + case tag: name = #tag; description = text; flavor = kind; break + TAG (AT_NULL, _("End of vector"), hex); + TAG (AT_IGNORE, _("Entry should be ignored"), hex); + TAG (AT_EXECFD, _("File descriptor of program"), dec); + TAG (AT_PHDR, _("Program headers for program"), hex); + TAG (AT_PHENT, _("Size of program header entry"), dec); + TAG (AT_PHNUM, _("Number of program headers"), dec); + TAG (AT_PAGESZ, _("System page size"), dec); + TAG (AT_BASE, _("Base address of interpreter"), hex); + TAG (AT_FLAGS, _("Flags"), hex); + TAG (AT_ENTRY, _("Entry point of program"), hex); + TAG (AT_NOTELF, _("Program is not ELF"), dec); + TAG (AT_UID, _("Real user ID"), dec); + TAG (AT_EUID, _("Effective user ID"), dec); + TAG (AT_GID, _("Real group ID"), dec); + TAG (AT_EGID, _("Effective group ID"), dec); + TAG (AT_CLKTCK, _("Frequency of times()"), dec); + TAG (AT_PLATFORM, _("String identifying platform"), str); + TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex); + TAG (AT_FPUCW, _("Used FPU control word"), dec); + TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec); + TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec); + TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec); + TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec); + TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str); + TAG (AT_RANDOM, _("Address of 16 random bytes"), hex); + TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex); + TAG (AT_EXECFN, _("File name of executable"), str); + TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec); + TAG (AT_SYSINFO, _("Special system info/entry points"), hex); + TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex); + TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"), hex); + TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), hex); + TAG (AT_L2_CACHESHAPE, _("L2 cache information"), hex); + TAG (AT_L3_CACHESHAPE, _("L3 cache information"), hex); + TAG (AT_SUN_UID, _("Effective user ID"), dec); + TAG (AT_SUN_RUID, _("Real user ID"), dec); + TAG (AT_SUN_GID, _("Effective group ID"), dec); + TAG (AT_SUN_RGID, _("Real group ID"), dec); + TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex); + TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex); + TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str); + TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec); + TAG (AT_SUN_PLATFORM, _("Platform name string"), str); + TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex); + TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec); + TAG (AT_SUN_CPU, _("CPU name string"), str); + TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex); + TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec); + TAG (AT_SUN_EXECNAME, + _("Canonicalized file name given to execve"), str); + TAG (AT_SUN_MMU, _("String for name of MMU module"), str); + TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex); + TAG (AT_SUN_AUXFLAGS, + _("AF_SUN_ flags passed from the kernel"), hex); + } + + fprint_single_auxv (file, name, description, flavor, type, val); +} + /* Print the contents of the target's AUXV on the specified file. */ int fprint_target_auxv (struct ui_file *file, struct target_ops *ops) { + struct gdbarch *gdbarch = target_gdbarch(); CORE_ADDR type, val; gdb_byte *data; gdb_byte *ptr; @@ -426,93 +528,10 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0) { - const char *name = "???"; - const char *description = ""; - enum { dec, hex, str } flavor = hex; - - switch (type) - { -#define TAG(tag, text, kind) \ - case tag: name = #tag; description = text; flavor = kind; break - TAG (AT_NULL, _("End of vector"), hex); - TAG (AT_IGNORE, _("Entry should be ignored"), hex); - TAG (AT_EXECFD, _("File descriptor of program"), dec); - TAG (AT_PHDR, _("Program headers for program"), hex); - TAG (AT_PHENT, _("Size of program header entry"), dec); - TAG (AT_PHNUM, _("Number of program headers"), dec); - TAG (AT_PAGESZ, _("System page size"), dec); - TAG (AT_BASE, _("Base address of interpreter"), hex); - TAG (AT_FLAGS, _("Flags"), hex); - TAG (AT_ENTRY, _("Entry point of program"), hex); - TAG (AT_NOTELF, _("Program is not ELF"), dec); - TAG (AT_UID, _("Real user ID"), dec); - TAG (AT_EUID, _("Effective user ID"), dec); - TAG (AT_GID, _("Real group ID"), dec); - TAG (AT_EGID, _("Effective group ID"), dec); - TAG (AT_CLKTCK, _("Frequency of times()"), dec); - TAG (AT_PLATFORM, _("String identifying platform"), str); - TAG (AT_HWCAP, _("Machine-dependent CPU capability hints"), hex); - TAG (AT_FPUCW, _("Used FPU control word"), dec); - TAG (AT_DCACHEBSIZE, _("Data cache block size"), dec); - TAG (AT_ICACHEBSIZE, _("Instruction cache block size"), dec); - TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec); - TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec); - TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str); - TAG (AT_RANDOM, _("Address of 16 random bytes"), hex); - TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex); - TAG (AT_EXECFN, _("File name of executable"), str); - TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec); - TAG (AT_SYSINFO, _("Special system info/entry points"), hex); - TAG (AT_SYSINFO_EHDR, _("System-supplied DSO's ELF header"), hex); - TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"), hex); - TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), hex); - TAG (AT_L2_CACHESHAPE, _("L2 cache information"), hex); - TAG (AT_L3_CACHESHAPE, _("L3 cache information"), hex); - TAG (AT_SUN_UID, _("Effective user ID"), dec); - TAG (AT_SUN_RUID, _("Real user ID"), dec); - TAG (AT_SUN_GID, _("Effective group ID"), dec); - TAG (AT_SUN_RGID, _("Real group ID"), dec); - TAG (AT_SUN_LDELF, _("Dynamic linker's ELF header"), hex); - TAG (AT_SUN_LDSHDR, _("Dynamic linker's section headers"), hex); - TAG (AT_SUN_LDNAME, _("String giving name of dynamic linker"), str); - TAG (AT_SUN_LPAGESZ, _("Large pagesize"), dec); - TAG (AT_SUN_PLATFORM, _("Platform name string"), str); - TAG (AT_SUN_HWCAP, _("Machine-dependent CPU capability hints"), hex); - TAG (AT_SUN_IFLUSH, _("Should flush icache?"), dec); - TAG (AT_SUN_CPU, _("CPU name string"), str); - TAG (AT_SUN_EMUL_ENTRY, _("COFF entry point address"), hex); - TAG (AT_SUN_EMUL_EXECFD, _("COFF executable file descriptor"), dec); - TAG (AT_SUN_EXECNAME, - _("Canonicalized file name given to execve"), str); - TAG (AT_SUN_MMU, _("String for name of MMU module"), str); - TAG (AT_SUN_LDDATA, _("Dynamic linker's data segment address"), hex); - TAG (AT_SUN_AUXFLAGS, - _("AF_SUN_ flags passed from the kernel"), hex); - } + if (!gdbarch_print_auxv_p (gdbarch) + || gdbarch_print_auxv (gdbarch, file, type, val) == 0) + default_print_auxv (file, type, val); - fprintf_filtered (file, "%-4s %-20s %-30s ", - plongest (type), name, description); - switch (flavor) - { - case dec: - fprintf_filtered (file, "%s\n", plongest (val)); - break; - case hex: - fprintf_filtered (file, "%s\n", paddress (target_gdbarch (), val)); - break; - case str: - { - struct value_print_options opts; - - get_user_print_options (&opts); - if (opts.addressprint) - fprintf_filtered (file, "%s ", paddress (target_gdbarch (), val)); - val_print_string (builtin_type (target_gdbarch ())->builtin_char, - NULL, val, -1, file, &opts); - fprintf_filtered (file, "\n"); - } - break; - } ++ents; if (type == AT_NULL) break; diff --git a/gdb/auxv.h b/gdb/auxv.h index 9efe604..91d94f9 100644 --- a/gdb/auxv.h +++ b/gdb/auxv.h @@ -46,6 +46,14 @@ extern int target_auxv_parse (struct target_ops *ops, extern int target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp); +/* Print a description of a single AUXV entry on the specified file. */ +enum auxv_format { dec, hex, str }; + +extern void fprint_single_auxv (struct ui_file *file, const char *name, + const char *description, + enum auxv_format flavor, CORE_ADDR type, + CORE_ADDR val); + /* Print the contents of the target's AUXV on the specified file. */ extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 313502b..15a4a98 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -328,6 +328,7 @@ struct gdbarch gdbarch_insn_is_ret_ftype *insn_is_ret; gdbarch_insn_is_jump_ftype *insn_is_jump; gdbarch_auxv_parse_ftype *auxv_parse; + gdbarch_print_auxv_ftype *print_auxv; gdbarch_vsyscall_range_ftype *vsyscall_range; gdbarch_infcall_mmap_ftype *infcall_mmap; gdbarch_infcall_munmap_ftype *infcall_munmap; @@ -678,6 +679,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of insn_is_ret, invalid_p == 0 */ /* Skip verify of insn_is_jump, invalid_p == 0 */ /* Skip verify of auxv_parse, has predicate. */ + /* Skip verify of print_auxv, has predicate. */ /* Skip verify of vsyscall_range, invalid_p == 0 */ /* Skip verify of infcall_mmap, invalid_p == 0 */ /* Skip verify of infcall_munmap, invalid_p == 0 */ @@ -1167,6 +1169,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: pointer_to_address = <%s>\n", host_address_to_string (gdbarch->pointer_to_address)); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_print_auxv_p() = %d\n", + gdbarch_print_auxv_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: print_auxv = <%s>\n", + host_address_to_string (gdbarch->print_auxv)); + fprintf_unfiltered (file, "gdbarch_dump: print_float_info = <%s>\n", host_address_to_string (gdbarch->print_float_info)); fprintf_unfiltered (file, @@ -4770,6 +4778,30 @@ set_gdbarch_auxv_parse (struct gdbarch *gdbarch, } int +gdbarch_print_auxv_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->print_auxv != NULL; +} + +int +gdbarch_print_auxv (struct gdbarch *gdbarch, struct ui_file *file, CORE_ADDR type, CORE_ADDR val) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->print_auxv != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_print_auxv called\n"); + return gdbarch->print_auxv (gdbarch, file, type, val); +} + +void +set_gdbarch_print_auxv (struct gdbarch *gdbarch, + gdbarch_print_auxv_ftype print_auxv) +{ + gdbarch->print_auxv = print_auxv; +} + +int gdbarch_vsyscall_range (struct gdbarch *gdbarch, struct mem_range *range) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index a6366fc..9cd1175 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1464,6 +1464,17 @@ typedef int (gdbarch_auxv_parse_ftype) (struct gdbarch *gdbarch, gdb_byte **read extern int gdbarch_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp); extern void set_gdbarch_auxv_parse (struct gdbarch *gdbarch, gdbarch_auxv_parse_ftype *auxv_parse); +/* Print the description of a single auxv entry described by TYPE and VAL + to FILE. Return 0 and output no description if the TYPE is unknown. + Return 0 if the TYPE of the auxv entry is unknown. + Return 1 if a description was output. */ + +extern int gdbarch_print_auxv_p (struct gdbarch *gdbarch); + +typedef int (gdbarch_print_auxv_ftype) (struct gdbarch *gdbarch, struct ui_file *file, CORE_ADDR type, CORE_ADDR val); +extern int gdbarch_print_auxv (struct gdbarch *gdbarch, struct ui_file *file, CORE_ADDR type, CORE_ADDR val); +extern void set_gdbarch_print_auxv (struct gdbarch *gdbarch, gdbarch_print_auxv_ftype *print_auxv); + /* Find the address range of the current inferior's vsyscall/vDSO, and write it to *RANGE. If the vsyscall's length can't be determined, a range with zero length is returned. Returns true if the vsyscall is diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index f170c10..1b4342f 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -1110,6 +1110,12 @@ m:int:insn_is_jump:CORE_ADDR addr:addr::default_insn_is_jump::0 # Return 1 if an entry was read into *TYPEP and *VALP. M:int:auxv_parse:gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp:readptr, endptr, typep, valp +# Print the description of a single auxv entry described by TYPE and VAL +# to FILE. Return 0 and output no description if the TYPE is unknown. +# Return 0 if the TYPE of the auxv entry is unknown. +# Return 1 if a description was output. +M:int:print_auxv:struct ui_file *file, CORE_ADDR type, CORE_ADDR val:file, type, val + # Find the address range of the current inferior's vsyscall/vDSO, and # write it to *RANGE. If the vsyscall's length can't be determined, a # range with zero length is returned. Returns true if the vsyscall is