This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Yao Qi wrote:
OK, will do the cross build and address your concern of <adi.h> likely breaking it as you commented below.Weimin Pan <weimin.pan@oracle.com> writes:Tested in sparc64-linux-gnu. No regressions.Could you build a cross gdb with your patch applied? That is, host and build is x86_64-linux and target is sparc64-linux, for example.
gdb/ChangeLog: 2017-06-16 Weimin Pan <weimin.pan@oracle.com> * sparc64-tdep.h: (adi_normalize_address): New export. * sparc64-adi-tdep.c: New file. * Makefile.in (ALLDEPFILES): Add sparc64-adi-tdep.c. * configure.tgt: Add sparc64-adi-tdep.o. * sparc64-linux-nat.c: (sparc64_linux_watchpoint_addr_within_range): New function. (_initialize_sparc64_linux_nat): Register sparc64_linux_watchpoint_addr_within_range.This line is too long. See https://sourceware.org/gdb/wiki/ContributionChecklist#Properly_Formatted_GNU_ChangeLog
Will split it.
* sparc64-linux-tdep.c: Include <adi.h>. (sparc64_linux_handle_segmentation_fault): New function. (sparc64_linux_init_abi): Register sparc64_linux_handle_segmentation_faultLikewise.
OK.
* sparc64-tdep.c: (sparc64_pstate_type): Replace PID1 with MCDE. gdb/doc/ChangeLog: 2017-06-16 Weimin Pan <weimin.pan@oracle.com> * gdb.texinfo (Architectures): Add new Sparc64 section to document ADI support. --- gdb/ChangeLog | 14 ++ gdb/Makefile.in | 2 + gdb/configure.tgt | 1 + gdb/doc/ChangeLog | 4 + gdb/doc/gdb.texinfo | 85 +++++++++ gdb/sparc64-adi-tdep.c | 460 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/sparc64-linux-nat.c | 15 ++ gdb/sparc64-linux-tdep.c | 49 +++++ gdb/sparc64-tdep.c | 2 +- gdb/sparc64-tdep.h | 2 + 10 files changed, 633 insertions(+), 1 deletions(-) create mode 100644 gdb/sparc64-adi-tdep.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5ebc7f8..8126a47 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2017-06-16 Weimin Pan <weimin.pan@oracle.com> + + * sparc64-tdep.h: (adi_normalize_address): New export. + * sparc64-adi-tdep.c: New file. + * Makefile.in (ALLDEPFILES): Add sparc64-adi-tdep.c. + * configure.tgt: Add sparc64-adi-tdep.o.+ * sparc64-linux-nat.c: + (sparc64_linux_watchpoint_addr_within_range): New function.+ (_initialize_sparc64_linux_nat): Register sparc64_linux_watchpoint_addr_within_range.+ * sparc64-linux-tdep.c: Include <adi.h>. + (sparc64_linux_handle_segmentation_fault): New function.+ (sparc64_linux_init_abi): Register sparc64_linux_handle_segmentation_fault + * sparc64-tdep.c: (sparc64_pstate_type): Replace PID1 with MCDE. + 2017-06-08 Sergio Durigan Junior <sergiodj@redhat.com>* common/common-utils.c (stringify_argv): Check for "arg[0] !=diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5e5fcaa..a6b0d99 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -772,6 +772,7 @@ ALL_64_TARGET_OBS = \ ia64-tdep.o \ ia64-vms-tdep.o \ mips64-obsd-tdep.o \ + sparc64-adi-tdep.o \ sparc64-fbsd-tdep.o \ sparc64-linux-tdep.o \ sparc64-nbsd-tdep.o \ @@ -2660,6 +2661,7 @@ ALLDEPFILES = \ sparc-sol2-nat.c \ sparc-sol2-tdep.c \ sparc-tdep.c \ + sparc64-adi-tdep.c \ sparc64-fbsd-nat.c \ sparc64-fbsd-tdep.c \ sparc64-linux-nat.c \ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index fdcb7b1..0519c62 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -548,6 +548,7 @@ sparc64-*-linux*) gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \ sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \ sparc-linux-tdep.o solib-svr4.o linux-tdep.o \ + sparc64-adi-tdep.o \ ravenscar-thread.o sparc-ravenscar-thread.o" build_gdbserver=yes ;; diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 868cde9..a411d64 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2017-06-16 Weimin Pan <weimin.pan@oracle.com> + * gdb.texinfo (Architectures): Add new Sparc64 section to document ADI support. + * NEWS: Add "adi examine" and "adi assign" commands. + 2017-06-07 Sergio Durigan Junior <sergiodj@redhat.com>* gdb.texinfo (Starting) <startup-with-shell>: Add @anchor.diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 8d7a1c9..843c1bf 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -22465,6 +22465,7 @@ all uses of @value{GDBN} with the architecture, both native and cross. * SPU:: Cell Broadband Engine SPU architecture * PowerPC:: * Nios II:: +* Sparc64:: @end menu@node AArch64@@ -22849,6 +22850,90 @@ target code in @value{GDBN}. Show the current setting of Nios II debugging messages. @end table+@node Sparc64+@subsection Sparc64 +@cindex Sparc64 support +@cindex Application Data Integrity +@subsubsection ADI Support ++The M7 processor supports an Application Data Integrity (ADI) feature that +detects invalid data accesses. When software allocates memory and enables +ADI on the allocated memory, it chooses a 4-bit version number, sets the +version in the upper 4 bits of the 64-bit pointer to that data, and stores +the 4-bit version in every cacheline of that data. Hardware saves the latter +in spare bits in the cache and memory hierarchy. On each load and store, +the processor compares the upper 4 VA (virtual address) bits to the +cacheline's version. If there is a mismatch, the processor generates a +version mismatch trap which can be either precise or disrupting. The trap +is an error condition which the kernel delivers to the process as a SIGSEGV +signal.+ +Note that only 64-bit applications can use ADI and need to be built with +ADI-enabled. ++Values of the ADI version tags, which are in granularity of a +cacheline (64 bytes), can be viewed or modified. ++ +@table @code +@kindex adi examine +@item adi examine ++The @code{adi examine} command displays the value of one ADI version tag per +cacheline. It has the following command syntax: ++@table @code +@itemx adi (examine | x) [ / @var{n} ] @var{addr} +@end table + +@var{n}, the byte count+The count is a decimal integer specifying the number in bytes; the default +is 1. It specifies how much ADI version information, at the ratio of 1:ADI +block size, to display. ++@var{addr}, starting display address+@var{addr} is the address in user address space where you want @value{GDBN} +to begin displaying the ADI version tags. ++Below is an example of displaying ADI versions of variable "shmaddr". + +@smallexample +(@value{GDBP}) adi x/100 shmaddr + 0xfff800010002c000: 0 0 +@end smallexample + +@kindex adi assign +@item adi assign ++The @code{adi assign} command is used to assign new ADI version tag +to an address. It has the following command syntax:+ +@table @code +@itemx adi (assign | a) [ / @var{n} ] @var{addr} = @var{tag} +@end table + +@var{n}, the byte count+The count is a decimal integer specifying the number in bytes; the default +is 1. It specifies how much ADI version information, at the ratio of 1:ADI +block size, to modify. ++@var{addr}, starting display address+@var{addr} is the address in user address space where you want @value{GDBN} +to begin modifying the ADI version tags. ++@var{tag}, the new ADI version tag ++For example, do the following to modify then verify ADI versions of +variable "shmaddr":+ +@smallexample +(@value{GDBP}) adi a/100 shmaddr = 7 +(@value{GDBP}) adi x/100 shmaddr + 0xfff800010002c000: 7 7 +@end smallexample + +@end table + @node Controlling GDB @chapter Controlling @value{GDBN}diff --git a/gdb/sparc64-adi-tdep.c b/gdb/sparc64-adi-tdep.cnew file mode 100644 index 0000000..9c9d0ae --- /dev/null +++ b/gdb/sparc64-adi-tdep.c @@ -0,0 +1,460 @@ +/* Target-dependent code for Sparc64.The new file sparc64-adi-tdep.c should be merged into the existing sparc64-tdep.c. The file name schema in GDB is ARCH-OSABI-tdep.c. Since adi is a new hardware feature rather than an OSABI, it should be put in sparc64-tdep.c
Originally it was part of sparc64-tdep.c. But our engineer thought it's cleaner to make it a separate source file. Being new to the gnu world, I believe following the file name schema
is the way to go. Thanks.
+ + Copyright (C) 2017 Free Software Foundation, Inc. + + This file is part of GDB. + + 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/>. */ + +#include <adi.h>I am afraid this will break the gdb cross build.+#include "defs.h" +#include "inferior.h" +#include "gdbcmd.h" +#include "auxv.h" + +/* The M7 processor supports an Application Data Integrity (ADI) feature+ that detects invalid data accesses. When software allocates memory and + enables ADI on the allocated memory, it chooses a 4-bit version number, + sets the version in the upper 4 bits of the 64-bit pointer to that data, + and stores the 4-bit version in every cacheline of the object. Hardware + saves the latter in spare bits in the cache and memory hierarchy. On each + load and store, the processor compares the upper 4 VA (virtual address) bits + to the cacheline's version. If there is a mismatch, the processor generates+ a version mismatch trap which can be either precise or disrupting. + The trap is an error condition which the kernel delivers to the process + as a SIGSEGV signal. + + The upper 4 bits of the VA represent a version and are not part of the + true address. The processor clears these bits and sign extends bit 59 + to generate the true address. + + Note that 32-bit applications cannot use ADI. */due to lack of hardware support or kernel support? I ask this because it is related to my comment to the following function arch_is_64bit.
Yes.
+ + +#define MAX_PROC_NAME_SIZE sizeof("/proc/99999/lwp/9999/adi/lstatus") + +/* ADI command list. */ +static struct cmd_list_element *sparc64adilist = NULL; + +/* Current ADI stat settings. */ +static struct +{ + /* The ADI block size. */ + unsigned long blksize; + + /* Number of bits used for an ADI version tag which can be + * used together with the shift value for an ADI version tag + * to encode or extract the ADI version value in a pointer. */ + unsigned long nbits; + + /* The maximum ADI version tag value supported. */ + int max_version; + + /* ADI version tag file. */ + int tag_fd; + + /* Last ADI address examined. */ + CORE_ADDR last_vaddr; + + /* Last specified examination count. */ + int last_cnt; + + /* ADI availability check has been done. */ + bool checked_avail; + + /* ADI is available. */ + bool is_avail; + +} adi_stat;It is a global data, but as I read the rest of the patch, looks like adi data should be per-process.
You're right. Will investigate.
+ + +static void +info_adi_command (char *args, int from_tty) +{ + printf_unfiltered ("\"adi\" must be followed by \"examine\" " + "or \"assign\".\n"); + help_list (sparc64adilist, "adi ", all_commands, gdb_stdout); +} + +static bool +arch_is_64bit (void) +{ + struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); + return gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64; + +} + +static int +parse_byte_count (const char **sptr) +{ + const char *p = *sptr; + int cnt = 1; + if (*p == '-') + { + cnt = -1; + p++; + } + if (*p >= '0' && *p <= '9') + cnt *= atoi (p); + while (*p >= '0' && *p <= '9') + p++; + while (*p == ' ' || *p == '\t') + p++; + *sptr = p; + + if (cnt <= 0) + error (_("Byte count should have a positive value.")); + + return cnt; +}You can use get_number or other apis declared in in gdb/cli-utils.h.
It's nice to know. Will do.
+ +/* Read attributes of a maps entry in /proc/[pid]/adi/maps. */ + +static void +read_maps_entry (const char *line, + ULONGEST *addr, ULONGEST *endaddr) +{ + const char *p = line; + + *addr = strtoulst (p, &p, 16); + if (*p == '-') + p++; + + *endaddr = strtoulst (p, &p, 16); +} + +/* Check if ADI is available. */ + +static bool +adi_available (void) +{ + if (adi_stat.checked_avail) + return adi_stat.is_avail; + + adi_stat.checked_avail = true; + if (!arch_is_64bit ()) + return false; + if (target_auxv_search (¤t_target, AT_ADI_BLKSZ, &adi_stat.blksize) <= 0)If kernel doesn't support ADI for 32-bit application, why don't we fetch AT_ADI_BLKSZ unconditionally?
Yes, we could do that. Will get rid of the arch_is_64bit() call.
+ return false; + target_auxv_search (¤t_target, AT_ADI_NBITS, &adi_stat.nbits); + adi_stat.max_version = (1 << adi_stat.nbits) - 2; + adi_stat.is_avail = true; + + return adi_stat.is_avail; +} + +#if 0 +/* Extract version tag from a versioned address. */ + +int adi_extract_version (CORE_ADDR versioned_addr) +{ + return ((unsigned long)versioned_addr) >> (64 - adi_stat.nbits); +} +#endif + +/* Normalize a versioned address - a VA with ADI bits (63-60) set. */ + +CORE_ADDR +adi_normalize_address (CORE_ADDR addr) +{ + if (adi_stat.nbits) + return ((CORE_ADDR)(((long)addr << adi_stat.nbits) >> adi_stat.nbits)); + return addr; +}I think the right approach is to implement gdbarch_addr_bits_remove for sparc64-linux, which remove these unused bits.
I suspect keeping this little function whose name implies clearly to normalize a VA might be OK. Will look into it.
+ +/* Align a normalized address - a VA with bit 59 sign extended into ADI bits. */ + +static CORE_ADDR +adi_align_address (CORE_ADDR naddr) +{ + return (naddr - (naddr % adi_stat.blksize)) / adi_stat.blksize;Indentation is wrong.
Will check/correct.
+} + +/* Convert a byte count to count at a ratio of 1:adi_blksz. */ + +static int +adi_convert_byte_count (CORE_ADDR naddr, int nbytes, CORE_ADDR locl) +{ + return ((naddr + nbytes + adi_stat.blksize - 1) / adi_stat.blksize) - locl;This line is too long.
Will correct.
It's nice to know. Will look into it. BTW is there any document that specifies/defines these rules for+} + +/* The /proc/[pid]/adi/tag file, which allows gdb to get/set ADI + version in a target process, maps linearly to the address space + of the target process at a ratio of 1:adi_blksz. + + A read (or write) at offset K in the file returns (or modifies) + the ADI version tag stored in the cacheline containing address + K * adi_blksz, encoded as 1 version tag per byte. The allowed + version tag values are between 0 and adi_stat.max_version. */ + +static int +adi_tag_fd (void) +{ + if (adi_stat.tag_fd != 0) + return adi_stat.tag_fd; + + char cl_name[MAX_PROC_NAME_SIZE]; + pid_t pid = ptid_get_pid (inferior_ptid); + snprintf (cl_name, sizeof(cl_name), "/proc/%d/adi/tag", pid); + adi_stat.tag_fd = open (cl_name, O_RDWR|O_EXCL|O_CLOEXEC);You can't access /proc in *-tdep.c file, because it is also compiled for cross-debugger. The rule in general is to move it to sparc64-linux-nat.c.
*-tdep.c and *-nat.c files?
+ + return adi_stat.tag_fd; +} + +/* Check if an address set is ADI enabled, using /proc/[pid]/adi/maps + which was exported by the kernel and contains the currently ADI + mapped memory regions and their access permissions. */ + +static bool +adi_is_addr_mapped (CORE_ADDR vaddr, size_t cnt) +{ + char filename[MAX_PROC_NAME_SIZE]; + size_t i = 0; + + pid_t pid = ptid_get_pid (inferior_ptid); + snprintf (filename, sizeof filename, "/proc/%d/adi/maps", pid); + char *data = target_fileio_read_stralloc (NULL, filename);It is better to define adi as a qXfer object, which can be read and written through target layer.
OK, will take a look.
+ if (data) + { + struct cleanup *cleanup = make_cleanup (xfree, data); + char *line; + for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n")) + { + ULONGEST addr, endaddr; + + read_maps_entry (line, &addr, &endaddr); + + while (((vaddr + i) * adi_stat.blksize) >= addr + && ((vaddr + i) * adi_stat.blksize) < endaddr) + { + if (++i == cnt) + { + do_cleanups (cleanup); + return true; + } + } + } + do_cleanups (cleanup); + } + else + warning (_("unable to open /proc file '%s'"), filename); + + return false; +} ++ +/* Print ADI version tag value in "tags" for memory locations starting + at "vaddr" with number of "cnt". */ + +static void +adi_print_versions (CORE_ADDR vaddr, size_t cnt, unsigned char *tags) +{ + int v_idx = 0; + const int maxelts = 8; /* # of elements per line */ + + while (cnt > 0) + { + QUIT; + printf_filtered ("0x%016lx:\t", vaddr * adi_stat.blksize); + for (int i = maxelts; i > 0 && cnt > 0; i--, cnt--) + { + if (tags[v_idx] == 0xff) /* no version tag */ + printf_filtered ("- "); + else + printf_filtered ("%1X ", tags[v_idx]); + ++v_idx; + } + printf_filtered ("\n"); + gdb_flush (gdb_stdout); + vaddr += maxelts; + } +} + +static void +do_examine (CORE_ADDR start, int bcnt) +{ + CORE_ADDR vaddr = adi_normalize_address (start); + struct cleanup *cleanup; + + CORE_ADDR vstart = adi_align_address (vaddr); + int cnt = adi_convert_byte_count (vaddr, bcnt, vstart); + unsigned char *buf = (unsigned char *) xmalloc (cnt); + cleanup = make_cleanup (xfree, buf); + int read_cnt = adi_read_versions (vstart, cnt, buf); + if (read_cnt == -1) + error (_("No ADI information")); + else if (read_cnt < cnt) + error(_("No ADI information at 0x%lx"), vaddr); + + adi_print_versions(vstart, cnt, buf); + + do_cleanups (cleanup); +} + +static void +do_assign (CORE_ADDR start, size_t bcnt, int version) +{ + CORE_ADDR vaddr = adi_normalize_address (start); + + CORE_ADDR vstart = adi_align_address (vaddr); + int cnt = adi_convert_byte_count (vaddr, bcnt, vstart); + unsigned char *buf = (unsigned char *) xmalloc (cnt); + memset(buf, version, cnt); + + int set_cnt = adi_write_versions (vstart, cnt, buf); + xfree (buf); + + if (set_cnt == -1) + error (_("No ADI information")); + else if (set_cnt < cnt) + error(_("No ADI information at 0x%lx"), vaddr); + +} + +/* ADI examine version tag command. + + Command syntax: + + adi (examine|x)/count <addr> */ + +static void +adi_examine_command (char *args, int from_tty) +{ + /* make sure program is active and adi is available */ + if (!target_has_execution) + error (_("ADI command requires a live process/thread")); + + if (!adi_available ()) + error (_("No ADI information")); + + int cnt = adi_stat.last_cnt? adi_stat.last_cnt : 1; + const char *p = args; + if (p && *p == '/') + { + p++; + cnt = parse_byte_count (&p); + } + + CORE_ADDR next_address = adi_stat.last_vaddr ? adi_stat.last_vaddr : 0; + if (p != 0 && *p != 0) + next_address = parse_and_eval_address (p); + else if (!adi_stat.last_cnt) + error (_("Usage: adi examine|x[/count] <addr>")); + + if (next_address) + do_examine(next_address, cnt); + + adi_stat.last_cnt = cnt; + adi_stat.last_vaddr = next_address + adi_stat.blksize * cnt; +} + +/* ADI assign version tag command. + + Command syntax: + + adi (assign|a)/count <addr> = <version> */ + +static void +adi_assign_command (char *args, int from_tty) +{ + /* make sure program is active and adi is available */ + if (!target_has_execution) + error (_("ADI command requires a live process/thread")); + + if (!adi_available ()) + error (_("No ADI information")); + + const char *exp = args; + if (exp == 0) + error_no_arg (_("Usage: adi assign|a[/count] <addr> = <version>")); + + char *q = (char *) strchr (exp, '='); + if (q) + *q++ = 0; + else + error (_("Usage: adi assign|a[/count] <addr> = <version>")); + + size_t cnt = 1; + const char *p = exp; + if (exp && *exp == '/') + { + p = exp + 1; + cnt = parse_byte_count (&p); + } + + CORE_ADDR next_address = 0; + if (p != 0 && *p != 0) + next_address = parse_and_eval_address (p); + else + error (_("Usage: adi assign|a[/count] <addr> = <version>")); + + int version = 0; + if (q) /* parse version tag */ + { + version = parse_and_eval_long (q); + if (version < 0 || version > adi_stat.max_version) + error (_("Invalid ADI version tag %d"), version); + } + + do_assign(next_address, cnt, version); +} + +extern initialize_file_ftype _initialize_sparc64_adi_tdep; /* -Wmissing-prototypes */ +This line is not needed.
I thought "lint" would need this line so it can be added to init.c?
+void +_initialize_sparc64_adi_tdep (void) +{ + + add_prefix_cmd ("adi", class_support, info_adi_command, + _("ADI version related commands."), + &sparc64adilist, "adi ", 0, &cmdlist); + add_cmd ("examine", class_support, adi_examine_command, + _("Examine ADI versions."), &sparc64adilist); + add_alias_cmd ("x", "examine", no_class, 1, &sparc64adilist); + add_cmd ("assign", class_support, adi_assign_command, + _("Assign ADI versions."), &sparc64adilist); + +} + diff --git a/gdb/sparc64-linux-nat.c b/gdb/sparc64-linux-nat.c index 638aa29..01adcd6 100644 --- a/gdb/sparc64-linux-nat.c +++ b/gdb/sparc64-linux-nat.c @@ -69,6 +69,18 @@ fill_fpregset (const struct regcache *regcache, sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); }+/* Implement the "to_watchpoint_addr_within_range" target_ops method. */+ +static int +sparc64_linux_watchpoint_addr_within_range (struct target_ops *target, + CORE_ADDR addr, + CORE_ADDR start, int length) +{ + start = adi_normalize_address (start); + addr = adi_normalize_address (addr); + return (start <= addr) && (start + length - 1 >= addr);I suppose once you implement gdbarch_addr_bits_remove, you don't need this change.
OK. Will check that.
+} + /* Provide a prototype to silence -Wmissing-prototypes. */ void _initialize_sparc64_linux_nat (void);@@ -86,6 +98,9 @@ _initialize_sparc64_linux_nat (void)t->to_fetch_registers = sparc_fetch_inferior_registers; t->to_store_registers = sparc_store_inferior_registers;+ t->to_watchpoint_addr_within_range =+ sparc64_linux_watchpoint_addr_within_range; + /* Register the target. */ linux_nat_add_target (t);diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.cindex 814bc29..17eb8c5 100644 --- a/gdb/sparc64-linux-tdep.c +++ b/gdb/sparc64-linux-tdep.c @@ -32,6 +32,7 @@ #include "tramp-frame.h" #include "xml-syscall.h" #include "linux-tdep.h" +#include <adi.h>/* The syscall's XML filename for sparc 64-bit. */#define XML_SYSCALL_FILENAME_SPARC64 "syscalls/sparc64-linux.xml" @@ -104,6 +105,52 @@ sparc64_linux_sigframe_init (const struct tramp_frame *self, } trad_frame_set_id (this_cache, frame_id_build (base, func)); } + +/* sparc64 GNU/Linux implementation of the handle_segmentation_fault + gdbarch hook. + Displays information related to ADI memory corruptions. */ + +void +sparc64_linux_handle_segmentation_fault (struct gdbarch *gdbarch, + struct ui_out *uiout) +{ + if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word != 64) + return; +Do you need to return if some sparc64 processor doesn't have adi?
No. The code that followed will check for the si_code bit which would signal if the segfault is caused by adi.
+ CORE_ADDR addr = 0; + long si_code = 0; + + TRY + { + /* Evaluate si_code to see if the segfault is ADI related. */ + si_code = parse_and_eval_long ("$_siginfo.si_code\n"); + + if (si_code >= SEGV_ACCADI && si_code <= SEGV_ADIPERR) + addr = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr"); + } + CATCH (exception, RETURN_MASK_ALL) + { + return; + } + END_CATCH + + /* Print out ADI event based on sig_code value */ + switch (si_code) + { + case SEGV_ACCADI: /* adi not enabled */ + printf_unfiltered (" (ADI disabled at address 0x%lx)\n", addr); + break; + case SEGV_ADIDERR: /* disrupting mismatch */ + printf_unfiltered (" (ADI deferred mismatch at address 0x%lx)\n", addr); + break; + case SEGV_ADIPERR: /* precise mismatch */ + printf_unfiltered (" (ADI precise mismatch at address 0x%lx)\n", addr);Use uiout instead print_unfiltered. See i386_linux_handle_segmentation_fault.
OK.
This change, which indicated that the TSTATE reigster contained the "mcde" value, was requested by our kernel engineers.+ break; + default: + break; + } +} + /* Return the address of a system call's alternative return address. */ @@ -338,6 +385,8 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_SPARC64); set_gdbarch_get_syscall_number (gdbarch, sparc64_linux_get_syscall_number); + set_gdbarch_handle_segmentation_fault (gdbarch, + sparc64_linux_handle_segmentation_fault); }diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.cindex 9e0e6b5..e8c5a63 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -165,7 +165,7 @@ sparc64_pstate_type (struct gdbarch *gdbarch) append_flags_type_flag (type, 8, "TLE"); append_flags_type_flag (type, 9, "CLE"); append_flags_type_flag (type, 10, "PID0"); - append_flags_type_flag (type, 11, "PID1"); + append_flags_type_flag (type, 11, "MCDE");Why do you do this change?
Thanks very much for your comments.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |