aboutsummaryrefslogtreecommitdiff
path: root/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
diff options
context:
space:
mode:
authorDavid Spickett <david.spickett@linaro.org>2021-02-19 15:57:29 +0000
committerDavid Spickett <david.spickett@linaro.org>2021-06-24 17:17:10 +0100
commit5d3436200147a999670f754288a03c4ac5a15aeb (patch)
treeda76b9ce3b2c8713516a424623760a42bb7d10b4 /lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
parenta224c5199b327ed0efcdcd87b6dbf950cf4d9ee1 (diff)
downloadllvm-5d3436200147a999670f754288a03c4ac5a15aeb.zip
llvm-5d3436200147a999670f754288a03c4ac5a15aeb.tar.gz
llvm-5d3436200147a999670f754288a03c4ac5a15aeb.tar.bz2
[lldb][AArch64] Add MTE memory tag reading to lldb
This adds GDB client support for the qMemTags packet which reads memory tags. Following the design which was recently committed to GDB. https://sourceware.org/gdb/current/onlinedocs/gdb/General-Query-Packets.html#General-Query-Packets (look for qMemTags) lldb commands will use the new Process methods GetMemoryTagManager and ReadMemoryTags. The former takes a range and checks that: * The current process architecture has an architecture plugin * That plugin provides a MemoryTagManager * That the range of memory requested lies in a tagged range (it will expand it to granules for you) If all that was true you get a MemoryTagManager you can give to ReadMemoryTags. This two step process is done to allow commands to get the tag manager without having to read tags as well. For example you might just want to remove a logical tag, or error early if a range with tagged addresses is inverted. Note that getting a MemoryTagManager doesn't mean that the process or a specific memory range is tagged. Those are seperate checks. Having a tag manager just means this architecture *could* have a tagging feature enabled. An architecture plugin has been added for AArch64 which will return a MemoryTagManagerAArch64MTE, which was added in a previous patch. Reviewed By: omjavaid Differential Revision: https://reviews.llvm.org/D95602
Diffstat (limited to 'lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp')
-rw-r--r--lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index cf5a1a5..b9fc107 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -465,3 +465,68 @@ TEST_F(GDBRemoteCommunicationClientTest, GetQOffsets) {
EXPECT_EQ(llvm::None, GetQOffsets("TextSeg=0x1234"));
EXPECT_EQ(llvm::None, GetQOffsets("TextSeg=12345678123456789"));
}
+
+static void
+check_qmemtags(TestClient &client, MockServer &server, size_t read_len,
+ const char *packet, llvm::StringRef response,
+ llvm::Optional<std::vector<uint8_t>> expected_tag_data) {
+ const auto &ReadMemoryTags = [&](size_t len, const char *packet,
+ llvm::StringRef response) {
+ std::future<DataBufferSP> result = std::async(std::launch::async, [&] {
+ return client.ReadMemoryTags(0xDEF0, read_len, 1);
+ });
+
+ HandlePacket(server, packet, response);
+ return result.get();
+ };
+
+ auto result = ReadMemoryTags(0, packet, response);
+ if (expected_tag_data) {
+ ASSERT_TRUE(result);
+ llvm::ArrayRef<uint8_t> expected(*expected_tag_data);
+ llvm::ArrayRef<uint8_t> got = result->GetData();
+ ASSERT_THAT(expected, testing::ContainerEq(got));
+ } else {
+ ASSERT_FALSE(result);
+ }
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, ReadMemoryTags) {
+ // Zero length reads are valid
+ check_qmemtags(client, server, 0, "qMemTags:def0,0:1", "m",
+ std::vector<uint8_t>{});
+
+ // The client layer does not check the length of the received data.
+ // All we need is the "m" and for the decode to use all of the chars
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m09",
+ std::vector<uint8_t>{0x9});
+
+ // Zero length response is fine as long as the "m" is present
+ check_qmemtags(client, server, 0, "qMemTags:def0,0:1", "m",
+ std::vector<uint8_t>{});
+
+ // Normal responses
+ check_qmemtags(client, server, 16, "qMemTags:def0,10:1", "m66",
+ std::vector<uint8_t>{0x66});
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m0102",
+ std::vector<uint8_t>{0x1, 0x2});
+
+ // Empty response is an error
+ check_qmemtags(client, server, 17, "qMemTags:def0,11:1", "", llvm::None);
+ // Usual error response
+ check_qmemtags(client, server, 17, "qMemTags:def0,11:1", "E01", llvm::None);
+ // Leading m missing
+ check_qmemtags(client, server, 17, "qMemTags:def0,11:1", "01", llvm::None);
+ // Anything other than m is an error
+ check_qmemtags(client, server, 17, "qMemTags:def0,11:1", "z01", llvm::None);
+ // Decoding tag data doesn't use all the chars in the packet
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m09zz", llvm::None);
+ // Data that is not hex bytes
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "mhello",
+ llvm::None);
+ // Data is not a complete hex char
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m9", llvm::None);
+ // Data has a trailing hex char
+ check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m01020",
+ llvm::None);
+}