This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5ea091a8174b: [lldb][AArch64] Add memory tag writing to lldb
(authored by DavidSpickett).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D105181/new/
https://reviews.llvm.org/D105181
Files:
lldb/include/lldb/Target/Process.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
lldb/source/Target/Process.cpp
lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
Index: lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
===================================================================
--- lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -17,6 +17,7 @@
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include <future>
+#include <limits>
using namespace lldb_private::process_gdb_remote;
using namespace lldb_private;
@@ -531,3 +532,51 @@
check_qmemtags(client, server, 32, "qMemTags:def0,20:1", "m01020",
llvm::None);
}
+
+static void check_Qmemtags(TestClient &client, MockServer &server,
+ lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags, const char *packet,
+ llvm::StringRef response, bool should_succeed) {
+ const auto &WriteMemoryTags = [&]() {
+ std::future<Status> result = std::async(std::launch::async, [&] {
+ return client.WriteMemoryTags(addr, len, type, tags);
+ });
+
+ HandlePacket(server, packet, response);
+ return result.get();
+ };
+
+ auto result = WriteMemoryTags();
+ if (should_succeed)
+ ASSERT_TRUE(result.Success());
+ else
+ ASSERT_TRUE(result.Fail());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, WriteMemoryTags) {
+ check_Qmemtags(client, server, 0xABCD, 0x20, 1,
+ std::vector<uint8_t>{0x12, 0x34}, "QMemTags:abcd,20:1:1234",
+ "OK", true);
+
+ // The GDB layer doesn't care that the number of tags !=
+ // the length of the write.
+ check_Qmemtags(client, server, 0x4321, 0x20, 9, std::vector<uint8_t>{},
+ "QMemTags:4321,20:9:", "OK", true);
+
+ check_Qmemtags(client, server, 0x8877, 0x123, 0x34,
+ std::vector<uint8_t>{0x55, 0x66, 0x77},
+ "QMemTags:8877,123:34:556677", "E01", false);
+
+ // Type is a signed integer but is packed as its raw bytes,
+ // instead of having a +/-.
+ check_Qmemtags(client, server, 0x456789, 0, -1, std::vector<uint8_t>{0x99},
+ "QMemTags:456789,0:ffffffff:99", "E03", false);
+ check_Qmemtags(client, server, 0x456789, 0,
+ std::numeric_limits<int32_t>::max(),
+ std::vector<uint8_t>{0x99}, "QMemTags:456789,0:7fffffff:99",
+ "E03", false);
+ check_Qmemtags(client, server, 0x456789, 0,
+ std::numeric_limits<int32_t>::min(),
+ std::vector<uint8_t>{0x99}, "QMemTags:456789,0:80000000:99",
+ "E03", false);
+}
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -6102,3 +6102,21 @@
return tag_manager->UnpackTagsData(*tag_data,
len / tag_manager->GetGranuleSize());
}
+
+Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len,
+ const std::vector<lldb::addr_t> &tags) {
+ llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
+ GetMemoryTagManager();
+ if (!tag_manager_or_err)
+ return Status(tag_manager_or_err.takeError());
+
+ const MemoryTagManager *tag_manager = *tag_manager_or_err;
+ llvm::Expected<std::vector<uint8_t>> packed_tags =
+ tag_manager->PackTags(tags);
+ if (!packed_tags) {
+ return Status(packed_tags.takeError());
+ }
+
+ return DoWriteMemoryTags(addr, len, tag_manager->GetAllocationTagType(),
+ *packed_tags);
+}
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -411,6 +411,9 @@
llvm::Expected<std::vector<uint8_t>>
DoReadMemoryTags(lldb::addr_t addr, size_t len, int32_t type) override;
+ Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) override;
+
private:
// For ProcessGDBRemote only
std::string m_partial_profile_data;
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -2791,6 +2791,14 @@
return got;
}
+Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // By now WriteMemoryTags should have validated that tagging is enabled
+ // for this target/process.
+ return m_gdb_comm.WriteMemoryTags(addr, len, type, tags);
+}
+
Status ProcessGDBRemote::WriteObjectFile(
std::vector<ObjectFile::LoadableData> entries) {
Status error;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -468,6 +468,9 @@
lldb::DataBufferSP ReadMemoryTags(lldb::addr_t addr, size_t len,
int32_t type);
+ Status WriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags);
+
/// Use qOffsets to query the offset used when relocating the target
/// executable. If successful, the returned structure will contain at least
/// one value in the offsets field.
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -628,6 +628,24 @@
return buffer_sp;
}
+Status GDBRemoteCommunicationClient::WriteMemoryTags(
+ lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // Format QMemTags:address,length:type:tags
+ StreamString packet;
+ packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
+ packet.PutBytesAsRawHex8(tags.data(), tags.size());
+
+ Status status;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ PacketResult::Success ||
+ !response.IsOKResponse()) {
+ status.SetErrorString("QMemTags packet failed");
+ }
+ return status;
+}
+
bool GDBRemoteCommunicationClient::GetxPacketSupported() {
if (m_supports_x == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -1737,6 +1737,29 @@
llvm::Expected<std::vector<lldb::addr_t>> ReadMemoryTags(lldb::addr_t addr,
size_t len);
+ /// Write memory tags for a range of memory.
+ /// (calls DoWriteMemoryTags to do the target specific work)
+ ///
+ /// \param[in] addr
+ /// The address to start writing tags from. It is assumed that this
+ /// address is granule aligned.
+ ///
+ /// \param[in] len
+ /// The size of the range to write tags for. It is assumed that this
+ /// is some multiple of the granule size. This len can be different
+ /// from (number of tags * granule size) in the case where you want
+ /// lldb-server to repeat tags across the range.
+ ///
+ /// \param[in] tags
+ /// Allocation tags to be written. Since lldb-server can repeat tags for a
+ /// range, the number of tags doesn't have to match the number of granules
+ /// in the range. (though most of the time it will)
+ ///
+ /// \return
+ /// A Status telling you if the write succeeded or not.
+ Status WriteMemoryTags(lldb::addr_t addr, size_t len,
+ const std::vector<lldb::addr_t> &tags);
+
/// Resolve dynamically loaded indirect functions.
///
/// \param[in] address
@@ -2777,6 +2800,30 @@
GetPluginName().GetCString());
}
+ /// Does the final operation to write memory tags. E.g. sending a GDB packet.
+ /// It assumes that WriteMemoryTags has checked that memory tagging is enabled
+ /// and has packed the tag data.
+ ///
+ /// \param[in] addr
+ /// Start of address range to write memory tags for.
+ ///
+ /// \param[in] len
+ /// Length of the memory range to write tags for (in bytes).
+ ///
+ /// \param[in] type
+ /// Type of tags to read (get this from a MemoryTagManager)
+ ///
+ /// \param[in] tags
+ /// Packed tags to be written.
+ ///
+ /// \return
+ /// Status telling you whether the write succeeded.
+ virtual Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) {
+ return Status("%s does not support writing memory tags",
+ GetPluginName().GetCString());
+ }
+
// Type definitions
typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP>
LanguageRuntimeCollection;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits