From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 82922 invoked by alias); 26 Oct 2017 08:30:00 -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 82820 invoked by uid 89); 26 Oct 2017 08:30:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS,UNSUBSCRIBE_BODY autolearn=ham version=3.3.2 spammy=temple, Temple, Hx-spam-relays-external:209.85.128.195, 30046 X-HELO: mail-wr0-f195.google.com Received: from mail-wr0-f195.google.com (HELO mail-wr0-f195.google.com) (209.85.128.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 26 Oct 2017 08:29:57 +0000 Received: by mail-wr0-f195.google.com with SMTP id r79so2341044wrb.13 for ; Thu, 26 Oct 2017 01:29:57 -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:subject:date:message-id:in-reply-to :references; bh=ZE1ByVHKaik3GK2QbKd8qQkc6Vn8g/bEn59LiZlOZRM=; b=K7sQDsUEhU/H4o5IqWZ4vQlv6A+RR3X8BWdOGk05ERligfRmpIyUQi+XTXl99Azyyu FQBONdYSJ/1lx264k4w8oQumGm9s/05nCJ61aPQ7iEZVDLOGp4xzoFO3ljqrOv1vqfOa 4csfr38bUQygSfxOV434VN3V7HpwitdPWcgqIevWHzVHm33fIcSVmBSpbjdDZcnLcEEU 9F8tr1NgdftzWQNG1GS0dF6N4zbVDBLCoVfBiV+RA3omvI7/1eD40n30x8+67JUcaJ6C ekSNKalFHaFfPLgILchyDXtqmBT+JB0fMjTCEcuEFPrxiDxDijkT262SFXkAR8LA0XJ2 JWiQ== X-Gm-Message-State: AMCzsaUOG5Ln5jGOK1ZR/6xc3FdtoWg4tISCADXF5Pf1mn9rvOioAhh1 HVzZrmcicFoCGU43mjtKOhFkgg== X-Google-Smtp-Source: ABhQp+STuX7Nu1T7foeTJKERcFO4uSn/bECxbPQFrT/K0Y0yrmWMD5J1Dy1i26NaonXISQrQt+PJug== X-Received: by 10.223.148.38 with SMTP id 35mr4910828wrq.49.1509006595245; Thu, 26 Oct 2017 01:29:55 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id k19sm4058506wrg.32.2017.10.26.01.29.54 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Oct 2017 01:29:54 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 1/3] [AArch64 Linux] Get rid of top byte from tagged address on memory access Date: Thu, 26 Oct 2017 08:30:00 -0000 Message-Id: <1509006590-9401-2-git-send-email-yao.qi@linaro.org> In-Reply-To: <1509006590-9401-1-git-send-email-yao.qi@linaro.org> References: <1509006590-9401-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes X-SW-Source: 2017-10/txt/msg00795.txt.bz2 ARMv8 supports tagged address, that is, the top one byte in address is ignored. It is always enabled on aarch64-linux. See https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt The patch clear the top byte of the virtual address, at the point before GDB/GDBserver pass the address to /proc or ptrace syscall on memory access. The top byte of address is still retained in the rest of GDB, because these bits can be used by different applications in different ways. That is reason I didn't implement gdbarch method addr_bits_remove to get rid of them. Before this patch, (gdb) x/x 0x0000000000411030 0x411030 : 0x00000000 (gdb) x/x 0xf000000000411030 0xf000000000411030: Cannot access memory at address 0xf000000000411030 After this patch, (gdb) x/x 0x0000000000411030 0x411030 : 0x00000000 (gdb) x/x 0xf000000000411030 0xf000000000411030: 0x00000000 With the tagged address, the variables/memory can be access via different addresses (or tags), but GDB uses cache for stack variable access and code access to speed up remote debugging. Fortunately, tagged address and GDB stack/code cache can coexist, because, - 'x' command doesn't go through cache, so we don't have to worry, - gdb only uses stack cache when it believes the variable is on stack, int i; int *p = &i; when print 'i' or 'p', gdb uses stack caches, but when print '*p', gdb only uses stack caches to get 'p', and get '*p' without cache, because gdb doesn't know the address p points to is on stack or not. - gdb uses code caches to access code, do disassembly for example, when gdb does disassembly for a function (without tag) and a tagged function pointer, gdb creates thinks they are different addresses, and creates two different cache lines, but we only have cache when inferior stops, and code caches are regarded read-only. gdb: 2017-10-19 Yao Qi * aarch64-linux-nat.c (super_xfer_partial): New function pointer. (aarch64_linux_xfer_partial): New function. (_initialize_aarch64_linux_nat): Initialize super_xfer_partial, and update to_xfer_partial. gdb/gdbserver: 2017-10-19 Yao Qi * linux-aarch64-low.c (super_read_memory): New function pointer. (super_write_memory): Likewise. (aarch64_linux_read_memory): New function. (aarch64_linux_write_memory): New function. (initialize_low_arch): Initialize super_read_memory and super_write_memory. Update read_memory and write_memory. 2017-10-19 Yao Qi gdb/testsuite: * gdb.arch/aarch64-tagged-pointer.c: New file. * gdb.arch/aarch64-tagged-pointer.exp: New file. --- gdb/aarch64-linux-nat.c | 25 +++++++++ gdb/gdbserver/linux-aarch64-low.c | 33 +++++++++++ gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c | 48 ++++++++++++++++ gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp | 68 +++++++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index de18edd..78c038b 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -780,6 +780,27 @@ aarch64_linux_can_do_single_step (struct target_ops *target) return 1; } +static target_xfer_partial_ftype *super_xfer_partial; + +/* Implement the "to_xfer_partial" target_ops method. */ + +static enum target_xfer_status +aarch64_linux_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, + ULONGEST len, ULONGEST *xfered_len) +{ + if (object == TARGET_OBJECT_MEMORY) + { + /* ARMv8 supports tagged address, that is, the top one byte in + virtual address is ignored. */ + offset &= 0x0fffffffffffffffULL; + } + + return super_xfer_partial (ops, object, annex, readbuf, writebuf, + offset, len, xfered_len); +} + /* Define AArch64 maintenance commands. */ static void @@ -834,6 +855,10 @@ _initialize_aarch64_linux_nat (void) super_post_startup_inferior = t->to_post_startup_inferior; t->to_post_startup_inferior = aarch64_linux_child_post_startup_inferior; + /* Override the default to_xfer_partial. */ + super_xfer_partial = t->to_xfer_partial; + t->to_xfer_partial = aarch64_linux_xfer_partial; + /* Register the target. */ linux_nat_add_target (t); linux_nat_set_new_thread (t, aarch64_linux_new_thread); diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index b00d5c5..bc44092 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -3004,6 +3004,31 @@ struct linux_target_ops the_low_target = aarch64_get_syscall_trapinfo, }; +static int (*super_read_memory) (CORE_ADDR memaddr, unsigned char *myaddr, + int len); + +static int (*super_write_memory) (CORE_ADDR memaddr, + const unsigned char *myaddr, int len); + +static int +aarch64_linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) +{ + /* ARMv8 supports tagged address, that is, the top one byte in + virtual address is ignored. */ + memaddr &= 0x0fffffffffffffffULL; + return super_read_memory (memaddr, myaddr, len); +} + +static int +aarch64_linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, + int len) +{ + /* ARMv8 supports tagged address, that is, the top one byte in + virtual address is ignored. */ + memaddr &= 0x0fffffffffffffffULL; + return super_write_memory (memaddr, myaddr, len); +} + void initialize_low_arch (void) { @@ -3012,4 +3037,12 @@ initialize_low_arch (void) initialize_low_arch_aarch32 (); initialize_regsets_info (&aarch64_regsets_info); + + /* Override the default read_memory. */ + super_read_memory = the_target->read_memory; + the_target->read_memory = aarch64_linux_read_memory; + + /* Override the default write_memory. */ + super_write_memory = the_target->write_memory; + the_target->write_memory = aarch64_linux_write_memory; } diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c new file mode 100644 index 0000000..7c90132 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c @@ -0,0 +1,48 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2017 Free Software Foundation, Inc. + + 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 + +struct s +{ + int i; +}; + +static void +foo (void) +{ +} + +int +main (void) +{ + struct s s1; + struct s *sp1, *sp2; + int i = 1234; + int *p1, *p2; + + s1.i = 1234; + sp1 = &s1; + p1 = &i; + /* SP1 and SP2 have different tags, but point to the same address. */ + sp2 = (struct s *) ((uintptr_t) sp1 | 0xf000000000000000ULL); + p2 = (int *) ((uintptr_t) p1 | 0xf000000000000000ULL); + + void (*func_ptr) (void) = foo; + func_ptr = (void (*) (void)) ((uintptr_t) func_ptr | 0xf000000000000000ULL); + sp2->i = 4321; /* breakpoint here. */ +} diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp new file mode 100644 index 0000000..4d36d09 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp @@ -0,0 +1,68 @@ +# Copyright 2017 Free Software Foundation, Inc. +# +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This file is part of the gdb testsuite. + +if {![is_aarch64_target]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +if ![runto_main] { + untested "could not run to main" + return -1 +} + +gdb_breakpoint [gdb_get_line_number "breakpoint here"] +gdb_continue_to_breakpoint "breakpoint here" + +# Test that GDB manages caches correctly for tagged address. +# Read from P2, +gdb_test "x p2" "$hex:\[\t \]+0x000004d2" +gdb_test_no_output "set variable i = 5678" +# Test that *P2 is updated. +gdb_test "x p2" "$hex:\[\t \]+0x0000162e" + +# Read from SP1->i, +gdb_test "print sp1->i" " = 1234" +# Write to SP2->i, +gdb_test_no_output "set variable sp2->i = 5678" +# Test that SP1->i is updated. +gdb_test "print sp1->i" " = 5678" + +gdb_test "x/d &sp2->i" "$hex:\[\t \]+5678" +gdb_test "x/d &sp1->i" "$hex:\[\t \]+5678" + +# Test that the same disassembly is got when disassembling function vs +# tagged function pointer. +set insn1 "" +set insn2 "" +set test "disassemble foo,+8" +gdb_test_multiple $test $test { + -re ":\[\t \]+(\[a-z\]*)\[ \r\n\]+.*:\[\t \]+(\[a-z\]*).*$gdb_prompt $" { + set insn1 $expect_out(1,string) + set insn2 $expect_out(2,string) + pass $test + } +} + +gdb_test "disassemble func_ptr,+8" \ + ":\[\t \]+$insn1\[ \r\n\]+.*:\[\t \]+$insn2.*" -- 1.9.1