DavidSpickett updated this revision to Diff 358541. DavidSpickett added a comment.
Rebase onto the earlier refactoring patch. Now GetMemoryTagManager just deals with the manager, no range handling. So this patch just adds WriteMemoryTags. "memory tag write" will use MakeTaggedRange from the memory tag manager instead of relying on the methods I had here before. 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; @@ -530,3 +531,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 @@ -6101,3 +6101,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 @@ -2790,6 +2790,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 @@ -467,6 +467,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 @@ -630,6 +630,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, false) != + 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 @@ -1736,6 +1736,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 @@ -2778,6 +2801,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 lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits