• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修訂e5f4e60d4955ba94516ef91d86f0f429a2c12612 (tree)
時間2020-06-26 01:23:38
作者Luis Machado <luis.machado@lina...>
CommiterLuis Machado

Log Message

AArch64: Implement memory tagging target methods for AArch64

The patch implements the memory tagging target hooks for AArch64, so we
can handle MTE.

gdb/ChangeLog:

YYYY-MM-DD Luis Machado <luis.machado@linaro.org>

* Makefile.in (ALL_64_TARGET_OBS): Add arch/aarch64-mte-linux.o.
(HFILES_NO_SRCDIR): Add arch/aarch64-mte-linux.h and
nat/aarch64-mte-linux-ptrace.h.
* aarch64-linux-nat.c: Include nat/aarch64-mte-linux-ptrace.h.
(aarch64_linux_nat_target) <supports_memory_tagging>: New method
override.
<fetch_memtags>: New method override.
<store_memtags>: New method override.
(aarch64_linux_nat_target::supports_memory_tagging): New method.
(aarch64_linux_nat_target::fetch_memtags): New method.
(aarch64_linux_nat_target::store_memtags): New method.
* arch/aarch64-mte-linux.c: New file.
* arch/aarch64-mte-linux.h: Include gdbsupport/common-defs.h.
(MTE_GRANULE_SIZE): Define.
(get_tag_granules): New prototype.
* configure.nat (NATDEPFILES): Add nat/aarch64-mte-linux-ptrace.o.
* configure.tgt (aarch64*-*-linux*): Add arch/aarch64-mte-linux.o.
* nat/aarch64-mte-linux-ptrace.c: New file.
* nat/aarch64-mte-linux-ptrace.h: New file.

Change Summary

差異

--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -680,6 +680,7 @@ ALL_64_TARGET_OBS = \
680680 amd64-windows-tdep.o \
681681 arch/aarch64.o \
682682 arch/aarch64-insn.o \
683+ arch/aarch64-mte-linux.o \
683684 arch/amd64.o \
684685 ia64-linux-tdep.o \
685686 ia64-tdep.o \
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -52,6 +52,8 @@
5252
5353 #include "arch/aarch64-mte-linux.h"
5454
55+#include "nat/aarch64-mte-linux-ptrace.h"
56+
5557 #ifndef TRAP_HWBKPT
5658 #define TRAP_HWBKPT 0x0004
5759 #endif
@@ -102,6 +104,16 @@ public:
102104 override;
103105
104106 struct gdbarch *thread_architecture (ptid_t) override;
107+
108+ bool supports_memory_tagging () override;
109+
110+ /* Read memory allocation tags from memory via PTRACE. */
111+ int fetch_memtags (CORE_ADDR address, size_t len,
112+ gdb::byte_vector &tags) override;
113+
114+ /* Write allocation tags to memory via PTRACE. */
115+ int store_memtags (CORE_ADDR address, size_t len,
116+ const gdb::byte_vector &tags) override;
105117 };
106118
107119 static aarch64_linux_nat_target the_aarch64_linux_nat_target;
@@ -1011,6 +1023,36 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid)
10111023 return gdbarch_find_by_info (info);
10121024 }
10131025
1026+/* Implement the "supports_memory_tagging" target_ops method. */
1027+
1028+bool
1029+aarch64_linux_nat_target::supports_memory_tagging ()
1030+{
1031+ return (linux_get_hwcap2 (this) & HWCAP2_MTE) != 0;
1032+}
1033+
1034+/* Implement the "fetch_memtags" target_ops method. */
1035+
1036+int
1037+aarch64_linux_nat_target::fetch_memtags (CORE_ADDR address, size_t len,
1038+ gdb::byte_vector &tags)
1039+{
1040+ int tid = inferior_ptid.lwp ();
1041+
1042+ return aarch64_mte_fetch_memtags (tid, address, len, tags);
1043+}
1044+
1045+/* Implement the "store_memtags" target_ops method. */
1046+
1047+int
1048+aarch64_linux_nat_target::store_memtags (CORE_ADDR address, size_t len,
1049+ const gdb::byte_vector &tags)
1050+{
1051+ int tid = inferior_ptid.lwp ();
1052+
1053+ return aarch64_mte_store_memtags (tid, address, len, tags);
1054+}
1055+
10141056 /* Define AArch64 maintenance commands. */
10151057
10161058 static void
--- /dev/null
+++ b/gdb/arch/aarch64-mte-linux.c
@@ -0,0 +1,34 @@
1+/* Common Linux target-dependent functionality for AArch64 MTE
2+
3+ Copyright (C) 2020 Free Software Foundation, Inc.
4+
5+ This file is part of GDB.
6+
7+ This program is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 3 of the License, or
10+ (at your option) any later version.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
20+#include "arch/aarch64-mte-linux.h"
21+
22+/* See arch/aarch64-mte-linux.h */
23+
24+int
25+get_tag_granules (CORE_ADDR addr, size_t len, unsigned int granule_size)
26+{
27+ /* Start address */
28+ CORE_ADDR s_addr = align_down (addr, granule_size);
29+ /* End address */
30+ CORE_ADDR e_addr = align_down (addr + len, granule_size);
31+
32+ /* We always have at least 1 granule. */
33+ return 1 + (e_addr - s_addr) / granule_size;
34+}
--- a/gdb/arch/aarch64-mte-linux.h
+++ b/gdb/arch/aarch64-mte-linux.h
@@ -20,6 +20,8 @@
2020 #ifndef ARCH_AARCH64_LINUX_H
2121 #define ARCH_AARCH64_LINUX_H
2222
23+#include "gdbsupport/common-defs.h"
24+
2325 /* Feature check for Memory Tagging Extension. */
2426 #ifndef HWCAP2_MTE
2527 #define HWCAP2_MTE (1 << 18)
@@ -28,4 +30,12 @@
2830 /* The MTE regset consists of 2 registers of 64-bit size. */
2931 #define AARCH64_LINUX_SIZEOF_MTE (2 * 64)
3032
33+/* We have one tag per 16 bytes of memory. */
34+#define MTE_GRANULE_SIZE 16
35+
36+/* Return the number of tag granules in the memory range
37+ [ADDR, ADDR + LEN) given GRANULE_SIZE. */
38+extern int get_tag_granules (CORE_ADDR addr, size_t len,
39+ unsigned int granule_size);
40+
3141 #endif /* ARCH_AARCH64_LINUX_H */
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -236,7 +236,8 @@ case ${gdb_host} in
236236 NATDEPFILES="${NATDEPFILES} aarch64-linux-nat.o \
237237 aarch32-linux-nat.o nat/aarch64-linux-hw-point.o \
238238 nat/aarch64-linux.o \
239- nat/aarch64-sve-linux-ptrace.o"
239+ nat/aarch64-sve-linux-ptrace.o \
240+ nat/aarch64-mte-linux-ptrace.o"
240241 ;;
241242 arm)
242243 # Host: ARM based machine running GNU/Linux
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -124,6 +124,7 @@ aarch64*-*-freebsd*)
124124 aarch64*-*-linux*)
125125 # Target: AArch64 linux
126126 gdb_target_obs="aarch64-linux-tdep.o arch/aarch64.o\
127+ arch/aarch64-mte-linux.o \
127128 arch/arm.o arch/arm-linux.o arch/arm-get-next-pcs.o \
128129 arm-tdep.o arm-linux-tdep.o \
129130 glibc-tdep.o linux-tdep.o solib-svr4.o \
--- /dev/null
+++ b/gdb/nat/aarch64-mte-linux-ptrace.c
@@ -0,0 +1,195 @@
1+/* Common Linux native ptrace code for AArch64 MTE.
2+
3+ Copyright (C) 2020 Free Software Foundation, Inc.
4+
5+ This file is part of GDB.
6+
7+ This program is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 3 of the License, or
10+ (at your option) any later version.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
20+#include "gdbsupport/common-defs.h"
21+#include "gdbsupport/byte-vector.h"
22+
23+#include "arch/aarch64.h"
24+#include "arch/aarch64-mte-linux.h"
25+#include "nat/aarch64-linux.h"
26+#include "nat/aarch64-mte-linux-ptrace.h"
27+
28+#include "linux-ptrace.h"
29+#include <sys/uio.h>
30+
31+/* Helper function to display various possible errors when reading
32+ MTE tags. */
33+
34+static void
35+aarch64_mte_linux_peek_error (int error)
36+{
37+ switch (error)
38+ {
39+ case EIO:
40+ perror_with_name (_("PEEKMTETAGS not supported"));
41+ break;
42+ case EFAULT:
43+ perror_with_name (_("Couldn't fetch allocation tags"));
44+ break;
45+ case EOPNOTSUPP:
46+ perror_with_name (_("PROT_ME not enabled for requested address"));
47+ default:
48+ perror_with_name (_("Unknown MTE error"));
49+ break;
50+ }
51+}
52+
53+/* Helper function to display various possible errors when writing
54+ MTE tags. */
55+
56+static void
57+aarch64_mte_linux_poke_error (int error)
58+{
59+ switch (error)
60+ {
61+ case EIO:
62+ perror_with_name (_("POKEMTETAGS not supported"));
63+ break;
64+ case EFAULT:
65+ perror_with_name (_("Couldn't store allocation tags"));
66+ break;
67+ case EOPNOTSUPP:
68+ perror_with_name (_("PROT_ME not enabled for requested address"));
69+ default:
70+ perror_with_name (_("Unknown MTE error"));
71+ break;
72+ }
73+}
74+
75+/* Helper to prepare a vector of tags to be passed on to the kernel. The
76+ main purpose of this function is to optimize the number of calls to
77+ ptrace if we're writing too many tags at once, like a pattern fill
78+ request.
79+
80+ Return a vector of tags of up to MAX_SIZE size, containing the tags that
81+ must be passed on to the kernel. GRANULES is the number of tag granules to
82+ be modified. */
83+
84+static gdb::byte_vector
85+prepare_tag_vector (size_t granules, const gdb::byte_vector &tags,
86+ size_t max_size)
87+{
88+ gdb::byte_vector t (0);
89+
90+ if (granules == 0)
91+ return t;
92+
93+ gdb_assert (tags.size () > 0 && max_size > 0);
94+
95+ if (granules > TAGS_MAX_SIZE)
96+ t.resize (TAGS_MAX_SIZE);
97+ else
98+ t.resize (granules);
99+
100+ size_t tag_count = tags.size ();
101+
102+ for (size_t i = 0; i < t.size (); i++)
103+ t[i] = tags[i % tag_count];
104+
105+ return t;
106+}
107+
108+/* See nat/aarch64-mte-linux-ptrace.h */
109+
110+int
111+aarch64_mte_fetch_memtags (int tid, CORE_ADDR address, size_t len,
112+ gdb::byte_vector &tags)
113+{
114+ size_t ntags = get_tag_granules (address, len, MTE_GRANULE_SIZE);
115+ gdb_byte tagbuf[ntags];
116+
117+ struct iovec iovec;
118+ iovec.iov_base = tagbuf;
119+ iovec.iov_len = ntags;
120+
121+ tags.clear ();
122+ bool done_reading = false;
123+
124+ /* The kernel may return less tags than we requested. Loop until we've read
125+ all the requested tags or until we get an error. */
126+ while (!done_reading)
127+ {
128+ /* Attempt to read ntags allocation tags from the kernel. */
129+ if (ptrace (PTRACE_PEEKMTETAGS, tid, address, &iovec) < 0)
130+ aarch64_mte_linux_peek_error (errno);
131+
132+ /* Make sure the kernel returned at least one tag. */
133+ if (iovec.iov_len <= 0)
134+ {
135+ tags.clear ();
136+ return 1;
137+ }
138+
139+ /* Copy the tags the kernel returned. */
140+ for (size_t i = 0; i < iovec.iov_len; i++)
141+ tags.push_back (tagbuf[i]);
142+
143+ /* Are we done reading tags? */
144+ if (tags.size () == ntags)
145+ done_reading = true;
146+ else
147+ {
148+ address += iovec.iov_len * MTE_GRANULE_SIZE;
149+ iovec.iov_len = ntags - iovec.iov_len;
150+ }
151+ }
152+ return 0;
153+}
154+
155+/* See nat/aarch64-mte-linux-ptrace.h */
156+
157+int
158+aarch64_mte_store_memtags (int tid, CORE_ADDR address, size_t len,
159+ const gdb::byte_vector &tags)
160+{
161+ if (tags.size () == 0)
162+ return 0;
163+
164+ /* Get the number of tags we need to write. */
165+ size_t ntags = get_tag_granules (address, len, MTE_GRANULE_SIZE);
166+
167+ gdb::byte_vector t = prepare_tag_vector (ntags, tags, TAGS_MAX_SIZE);
168+ gdb::byte_vector tags_left = tags;
169+
170+ /* Write all the tags, TAGS_MAX_SIZE blocks at a time. */
171+ while (t.size () != 0)
172+ {
173+ struct iovec iovec;
174+ iovec.iov_base = t.data ();
175+ iovec.iov_len = t.size ();
176+
177+ /* Request the kernel to update the allocation tags. */
178+ if (ptrace (PTRACE_POKEMTETAGS, tid, address, &iovec) < 0)
179+ aarch64_mte_linux_poke_error (errno);
180+
181+ /* Make sure the kernel wrote at least one tag. */
182+ if (iovec.iov_len <= 0)
183+ return 1;
184+
185+ /* Update the tag vector based on how many tags the kernel actually
186+ wrote. */
187+ auto it = tags_left.begin ();
188+ tags_left.erase (it, it + iovec.iov_len - 1);
189+ address += iovec.iov_len * MTE_GRANULE_SIZE;
190+ ntags -= iovec.iov_len;
191+ t = prepare_tag_vector (ntags, tags_left, TAGS_MAX_SIZE);
192+ }
193+
194+ return 0;
195+}
--- a/gdb/nat/aarch64-mte-linux-ptrace.h
+++ b/gdb/nat/aarch64-mte-linux-ptrace.h
@@ -30,4 +30,21 @@
3030 #define PTRACE_POKEMTETAGS 34
3131 #endif
3232
33+/* Maximum number of tags to pass at once to the kernel. */
34+#define TAGS_MAX_SIZE 4096
35+
36+/* Read the allocation tags from memory range [ADDRESS, ADDRESS + LEN)
37+ into TAGS.
38+
39+ Return 0 if successful and non-zero otherwise. */
40+extern int aarch64_mte_fetch_memtags (int tid, CORE_ADDR address, size_t len,
41+ gdb::byte_vector &tags);
42+
43+/* Write the TAGS allocation tags to the memory range
44+ [ADDRESS, ADDRESS + LEN).
45+
46+ Return 0 if successful and non-zero otherwise. */
47+extern int aarch64_mte_store_memtags (int tid, CORE_ADDR address, size_t len,
48+ const gdb::byte_vector &tags);
49+
3350 #endif /* NAT_AARCH64_MTE_LINUX_PTRACE_H */