From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 96864 invoked by alias); 20 Jun 2017 13:35: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 96418 invoked by uid 89); 20 Jun 2017 13:35:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=displays, sk:contrib, HTo:D*oracle.com, Pan X-HELO: mail-pf0-f170.google.com Received: from mail-pf0-f170.google.com (HELO mail-pf0-f170.google.com) (209.85.192.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Jun 2017 13:35:26 +0000 Received: by mail-pf0-f170.google.com with SMTP id c73so9151471pfk.2 for ; Tue, 20 Jun 2017 06:35:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-transfer-encoding; bh=8h4lAftRxY5bvtUn+A6oTEcZuf7Jeau9RmV4p6c5JNY=; b=ZIpI+oktY1bYbkDuJ9RlviOh/8W+VqJVtl2xWORaNOgjdXJU3wepn3vSKPZIj0fsC+ qUI5IOv6zjEOlvmpwCQALrDYLcKLPLBBB4XAcEvDtWwTPCwaT23ZrZJlN/zC7FBIX2qV R2U3Z4vB/xIoLa1VLWNl3wGJH4wnQCB+HQ0Pt8qPiWvDw70HaPydReqZkjTmfnTZJsbW HfanGHB7owzuRHsjoG+IYz/WHjcXYgs2rI1tqlekT2cd8QOniAHmb3meBlE1dPmTzbiT hx9fjaLS8dWUwwPpG4utpf4GOkfFLuRuwNEuMCVK+SPohAnfHhANG1zKz6kN3h7Lnrdt VZgA== X-Gm-Message-State: AKS2vOzFWQX0OiuooFUdnNKxJXgHz4UifzfjD3P5Mypn6GT0Ivnsy7Ss SlKozwi0Es1UnbtF X-Received: by 10.84.232.69 with SMTP id f5mr15908205pln.249.1497965724260; Tue, 20 Jun 2017 06:35:24 -0700 (PDT) Received: from E107787-LIN (gcc114.osuosl.org. [140.211.9.72]) by smtp.gmail.com with ESMTPSA id k192sm26216025pgc.31.2017.06.20.06.35.22 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 20 Jun 2017 06:35:23 -0700 (PDT) From: Yao Qi To: Weimin Pan Cc: gdb-patches@sourceware.org Subject: Re: [PATCH v2] gdb: ADI support References: <1497655802-111684-1-git-send-email-weimin.pan@oracle.com> Date: Tue, 20 Jun 2017 13:35:00 -0000 In-Reply-To: <1497655802-111684-1-git-send-email-weimin.pan@oracle.com> (Weimin Pan's message of "Fri, 16 Jun 2017 18:30:02 -0500") Message-ID: <86o9ti4wa1.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2017-06/txt/msg00571.txt.bz2 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. > 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_Formatte= d_GNU_ChangeLog > * sparc64-linux-tdep.c: Include . > (sparc64_linux_handle_segmentation_fault): New function. > (sparc64_linux_init_abi): Register sparc64_linux_handle_segmentation_fau= lt Likewise. > * 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 s= upport. > --- > 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:=20 > + (sparc64_linux_watchpoint_addr_within_range): New function. > + (_initialize_sparc64_linux_nat): Register sparc64_linux_watchpoint_addr= _within_range. > + * sparc64-linux-tdep.c: Include .=20 > + (sparc64_linux_handle_segmentation_fault): New function. > + (sparc64_linux_init_abi): Register sparc64_linux_handle_segmentation_fa= ult > + * sparc64-tdep.c: (sparc64_pstate_type): Replace PID1 with MCDE. > + > 2017-06-08 Sergio Durigan Junior >=20=20 > * common/common-utils.c (stringify_argv): Check for "arg[0] !=3D > 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 =3D \ > 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 =3D \ > 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=3D"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=3Dyes > ;; > 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 >=20=20 > * 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, b= oth native and cross. > * SPU:: Cell Broadband Engine SPU architecture > * PowerPC:: > * Nios II:: > +* Sparc64:: > @end menu >=20=20 > @node AArch64 > @@ -22849,6 +22850,90 @@ target code in @value{GDBN}. > Show the current setting of Nios II debugging messages. > @end table >=20=20 > +@node Sparc64 > +@subsection Sparc64 > +@cindex Sparc64 support > +@cindex Application Data Integrity > +@subsubsection ADI Support > + > +The M7 processor supports an Application Data Integrity (ADI) feature th= at=20 > +detects invalid data accesses. When software allocates memory and enabl= es=20 > +ADI on the allocated memory, it chooses a 4-bit version number, sets the= =20 > +version in the upper 4 bits of the 64-bit pointer to that data, and stor= es=20 > +the 4-bit version in every cacheline of that data. Hardware saves the l= atter=20 > +in spare bits in the cache and memory hierarchy. On each load and store= ,=20 > +the processor compares the upper 4 VA (virtual address) bits to the=20 > +cacheline's version. If there is a mismatch, the processor generates a= =20 > +version mismatch trap which can be either precise or disrupting. The tr= ap=20 > +is an error condition which the kernel delivers to the process as a SIGS= EGV=20 > +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=20 > +cacheline (64 bytes), can be viewed or modified.=20 > + > + > +@table @code > +@kindex adi examine > +@item adi examine > + > +The @code{adi examine} command displays the value of one ADI version tag= per=20 > +cacheline. It has the following command syntax:=20 > + > +@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 defau= lt=20 > +is 1. It specifies how much ADI version information, at the ratio of 1:= ADI=20 > +block size, to display.=20 > + > +@var{addr}, starting display address > +@var{addr} is the address in user address space where you want @value{GD= BN}=20 > +to begin displaying the ADI version tags.=20 > + > +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=20 > +to an address. It has the following command syntax: > + > +@table @code > +@itemx adi (assign | a) [ / @var{n} ] @var{addr} =3D @var{tag} > +@end table > + > +@var{n}, the byte count > +The count is a decimal integer specifying the number in bytes; the defau= lt=20 > +is 1. It specifies how much ADI version information, at the ratio of 1:= ADI=20 > +block size, to modify.=20 > + > +@var{addr}, starting display address > +@var{addr} is the address in user address space where you want @value{GD= BN}=20 > +to begin modifying the ADI version tags.=20 > + > +@var{tag}, the new ADI version tag > + > +For example, do the following to modify then verify ADI versions of=20 > +variable "shmaddr": > + > +@smallexample > +(@value{GDBP}) adi a/100 shmaddr =3D 7 > +(@value{GDBP}) adi x/100 shmaddr > + 0xfff800010002c000: 7 7 > +@end smallexample > + > +@end table > + > @node Controlling GDB > @chapter Controlling @value{GDBN} >=20=20 > 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 > + > + 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 a= nd=20 > + enables ADI on the allocated memory, it chooses a 4-bit version numbe= r,=20 > + sets the version in the upper 4 bits of the 64-bit pointer to that da= ta,=20 > + and stores the 4-bit version in every cacheline of the object. Hardw= are=20 > + saves the latter in spare bits in the cache and memory hierarchy. On = each=20 > + load and store, the processor compares the upper 4 VA (virtual addres= s) bits=20 > + to the cacheline's version. If there is a mismatch, the processor gen= erates > + a version mismatch trap which can be either precise or disrupting. > + The trap is an error condition which the kernel delivers to the proce= ss > + 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. > + > + > +#define MAX_PROC_NAME_SIZE sizeof("/proc/99999/lwp/9999/adi/lstatus") > + > +/* ADI command list. */ > +static struct cmd_list_element *sparc64adilist =3D 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. > + > + > +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 =3D get_frame_arch (get_current_frame ()); > + return gdbarch_bfd_arch_info (gdbarch)->bits_per_word =3D=3D 64; > + > +} > + > +static int > +parse_byte_count (const char **sptr) > +{ > + const char *p =3D *sptr; > + int cnt =3D 1; > + if (*p =3D=3D '-') > + { > + cnt =3D -1; > + p++; > + } > + if (*p >=3D '0' && *p <=3D '9') > + cnt *=3D atoi (p); > + while (*p >=3D '0' && *p <=3D '9') > + p++; > + while (*p =3D=3D ' ' || *p =3D=3D '\t') > + p++; > + *sptr =3D p; > + > + if (cnt <=3D 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. > + > +/* 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 =3D line; > + > + *addr =3D strtoulst (p, &p, 16); > + if (*p =3D=3D '-') > + p++; > + > + *endaddr =3D 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 =3D true; > + if (!arch_is_64bit ()) > + return false; > + if (target_auxv_search (¤t_target, AT_ADI_BLKSZ, &adi_stat.blksi= ze) <=3D 0) If kernel doesn't support ADI for 32-bit application, why don't we fetch AT_ADI_BLKSZ unconditionally? > + return false; > + target_auxv_search (¤t_target, AT_ADI_NBITS, &adi_stat.nbits); > + adi_stat.max_version =3D (1 << adi_stat.nbits) - 2; > + adi_stat.is_avail =3D 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. > + > +/* 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.=20=20 > +} > + > +/* 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. > +} > + > +/* 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 !=3D 0) > + return adi_stat.tag_fd; > + > + char cl_name[MAX_PROC_NAME_SIZE]; > + pid_t pid =3D ptid_get_pid (inferior_ptid); > + snprintf (cl_name, sizeof(cl_name), "/proc/%d/adi/tag", pid); > + adi_stat.tag_fd =3D 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. > + > + 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 =3D 0; > + > + pid_t pid =3D ptid_get_pid (inferior_ptid); > + snprintf (filename, sizeof filename, "/proc/%d/adi/maps", pid); > + char *data =3D 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. > + if (data) > + { > + struct cleanup *cleanup =3D make_cleanup (xfree, data); > + char *line; > + for (line =3D strtok (data, "\n"); line; line =3D strtok (NULL, "\= n")) > + { > + ULONGEST addr, endaddr; > + > + read_maps_entry (line, &addr, &endaddr); > + > + while (((vaddr + i) * adi_stat.blksize) >=3D addr > + && ((vaddr + i) * adi_stat.blksize) < endaddr) > + { > + if (++i =3D=3D 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 =3D 0; > + const int maxelts =3D 8; /* # of elements per line */ > + > + while (cnt > 0) > + { > + QUIT; > + printf_filtered ("0x%016lx:\t", vaddr * adi_stat.blksize); > + for (int i =3D maxelts; i > 0 && cnt > 0; i--, cnt--) > + { > + if (tags[v_idx] =3D=3D 0xff) /* no version tag */ > + printf_filtered ("- "); > + else > + printf_filtered ("%1X ", tags[v_idx]); > + ++v_idx; > + } > + printf_filtered ("\n"); > + gdb_flush (gdb_stdout); > + vaddr +=3D maxelts; > + } > +} > + > +static void > +do_examine (CORE_ADDR start, int bcnt) > +{ > + CORE_ADDR vaddr =3D adi_normalize_address (start); > + struct cleanup *cleanup; > + > + CORE_ADDR vstart =3D adi_align_address (vaddr); > + int cnt =3D adi_convert_byte_count (vaddr, bcnt, vstart); > + unsigned char *buf =3D (unsigned char *) xmalloc (cnt); > + cleanup =3D make_cleanup (xfree, buf); > + int read_cnt =3D adi_read_versions (vstart, cnt, buf); > + if (read_cnt =3D=3D -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 =3D adi_normalize_address (start); > + > + CORE_ADDR vstart =3D adi_align_address (vaddr); > + int cnt =3D adi_convert_byte_count (vaddr, bcnt, vstart); > + unsigned char *buf =3D (unsigned char *) xmalloc (cnt); > + memset(buf, version, cnt); > + > + int set_cnt =3D adi_write_versions (vstart, cnt, buf); > + xfree (buf); > + > + if (set_cnt =3D=3D -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 =3D adi_stat.last_cnt? adi_stat.last_cnt : 1; > + const char *p =3D args; > + if (p && *p =3D=3D '/') > + { > + p++; > + cnt =3D parse_byte_count (&p); > + } > + > + CORE_ADDR next_address =3D adi_stat.last_vaddr ? adi_stat.last_vaddr := 0; > + if (p !=3D 0 && *p !=3D 0) > + next_address =3D 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 =3D cnt; > + adi_stat.last_vaddr =3D next_address + adi_stat.blksize * cnt; > +} > + > +/* ADI assign version tag command. > + > + Command syntax: > + > + adi (assign|a)/count =3D */ > + > +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 =3D args; > + if (exp =3D=3D 0) > + error_no_arg (_("Usage: adi assign|a[/count] =3D ")); > + > + char *q =3D (char *) strchr (exp, '=3D'); > + if (q) > + *q++ =3D 0; > + else > + error (_("Usage: adi assign|a[/count] =3D ")); > + > + size_t cnt =3D 1; > + const char *p =3D exp; > + if (exp && *exp =3D=3D '/') > + { > + p =3D exp + 1; > + cnt =3D parse_byte_count (&p); > + } > + > + CORE_ADDR next_address =3D 0; > + if (p !=3D 0 && *p !=3D 0) > + next_address =3D parse_and_eval_address (p); > + else > + error (_("Usage: adi assign|a[/count] =3D ")); > + > + int version =3D 0; > + if (q) /* parse version tag */ > + { > + version =3D 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. > +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, fpr= egs); > } >=20=20 > +/* 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 =3D adi_normalize_address (start); > + addr =3D adi_normalize_address (addr); > + return (start <=3D addr) && (start + length - 1 >=3D addr); I suppose once you implement gdbarch_addr_bits_remove, you don't need this change. > +} > + > /* Provide a prototype to silence -Wmissing-prototypes. */ > void _initialize_sparc64_linux_nat (void); >=20=20 > @@ -86,6 +98,9 @@ _initialize_sparc64_linux_nat (void) > t->to_fetch_registers =3D sparc_fetch_inferior_registers; > t->to_store_registers =3D sparc_store_inferior_registers; >=20=20 > + t->to_watchpoint_addr_within_range =3D > + sparc64_linux_watchpoint_addr_within_range; > + > /* Register the target. */ > linux_nat_add_target (t); >=20=20 > 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 >=20=20 > /* 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_fram= e *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 !=3D 64) > + return; > + Do you need to return if some sparc64 processor doesn't have adi? > + CORE_ADDR addr =3D 0; > + long si_code =3D 0; > + > + TRY > + { > + /* Evaluate si_code to see if the segfault is ADI related. */ > + si_code =3D parse_and_eval_long ("$_siginfo.si_code\n"); > + > + if (si_code >=3D SEGV_ACCADI && si_code <=3D SEGV_ADIPERR) > + addr =3D 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_fau= lt. > + break; > + default: > + break; > + } > +} > + > =0C > /* Return the address of a system call's alternative return > address. */ > @@ -338,6 +385,8 @@ sparc64_linux_init_abi (struct gdbarch_info info, str= uct 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); > } > =0C >=20=20 > 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"); >=20=20 Why do you do this change? --=20 Yao (=E9=BD=90=E5=B0=A7)