From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 127885 invoked by alias); 20 Jun 2017 17:50:42 -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 127027 invoked by uid 89); 20 Jun 2017 17:50:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=engineers X-HELO: aserp1040.oracle.com Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Jun 2017 17:50:37 +0000 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v5KHoYaI030871 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 20 Jun 2017 17:50:34 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id v5KHoY2J024972 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 20 Jun 2017 17:50:34 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id v5KHoXnq013846; Tue, 20 Jun 2017 17:50:33 GMT Received: from [192.168.1.74] (/108.88.88.153) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 20 Jun 2017 10:50:33 -0700 Message-ID: <59496067.5040008@oracle.com> Date: Tue, 20 Jun 2017 17:50:00 -0000 From: Wei-min Pan User-Agent: Thunderbird 2.0.0.24 (Windows/20100228) MIME-Version: 1.0 To: Yao Qi CC: gdb-patches@sourceware.org Subject: Re: [PATCH v2] gdb: ADI support References: <1497655802-111684-1-git-send-email-weimin.pan@oracle.com> <86o9ti4wa1.fsf@gmail.com> In-Reply-To: <86o9ti4wa1.fsf@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2017-06/txt/msg00577.txt.bz2 Yao Qi wrote: > Weimin Pan 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. > OK, will do the cross build and address your concern of likely breaking it as you commented below. >> gdb/ChangeLog: >> 2017-06-16 Weimin Pan >> >> * 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 . >> (sparc64_linux_handle_segmentation_fault): New function. >> (sparc64_linux_init_abi): Register sparc64_linux_handle_segmentation_fault >> > > Likewise. > OK. > >> * sparc64-tdep.c: (sparc64_pstate_type): Replace PID1 with MCDE. >> gdb/doc/ChangeLog: >> 2017-06-16 Weimin Pan >> * 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 >> + >> + * 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 . >> + (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 >> >> * 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 >> + * 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 >> >> * gdb.texinfo (Starting) : 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.c >> new 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 . */ >> + >> +#include >> > > 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. >> +} >> + >> +/* 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. > It's nice to know. Will look into it. BTW is there any document that specifies/defines these rules for *-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 */ >> + >> +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] ")); >> + >> + 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 = */ >> + >> +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] = ")); >> + >> + char *q = (char *) strchr (exp, '='); >> + if (q) >> + *q++ = 0; >> + else >> + error (_("Usage: adi assign|a[/count] = ")); >> + >> + 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] = ")); >> + >> + 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.c >> index 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 >> >> /* 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. > >> + 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.c >> index 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? > This change, which indicated that the TSTATE reigster contained the "mcde" value, was requested by our kernel engineers. Thanks very much for your comments.