labath updated this revision to Diff 246401.
labath added a comment.
Update the unit test for the function rename (GetExecutableOffset->GetQOffsets)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74598/new/
https://reviews.llvm.org/D74598
Files:
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/test/API/functionalities/gdb_remote_client/TestqOffsets.py
lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
lldb/test/API/functionalities/gdb_remote_client/qOffsets.yaml
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
@@ -552,3 +552,29 @@
incorrect_custom_params2);
ASSERT_FALSE(result4.get().Success());
}
+
+TEST_F(GDBRemoteCommunicationClientTest, GetQOffsets) {
+ const auto &GetQOffsets = [&](llvm::StringRef response) {
+ std::future<Optional<QOffsets>> result = std::async(
+ std::launch::async, [&] { return client.GetQOffsets(); });
+
+ HandlePacket(server, "qOffsets", response);
+ return result.get();
+ };
+ EXPECT_EQ((QOffsets{false, {0x1234, 0x1234}}),
+ GetQOffsets("Text=1234;Data=1234"));
+ EXPECT_EQ((QOffsets{false, {0x1234, 0x1234, 0x1234}}),
+ GetQOffsets("Text=1234;Data=1234;Bss=1234"));
+ EXPECT_EQ((QOffsets{true, {0x1234}}), GetQOffsets("TextSeg=1234"));
+ EXPECT_EQ((QOffsets{true, {0x1234, 0x2345}}),
+ GetQOffsets("TextSeg=1234;DataSeg=2345"));
+
+ EXPECT_EQ(llvm::None, GetQOffsets("E05"));
+ EXPECT_EQ(llvm::None, GetQOffsets("Text=bogus"));
+ EXPECT_EQ(llvm::None, GetQOffsets("Text=1234"));
+ EXPECT_EQ(llvm::None, GetQOffsets("Text=1234;Data=1234;"));
+ EXPECT_EQ(llvm::None, GetQOffsets("Text=1234;Data=1234;Bss=1234;"));
+ EXPECT_EQ(llvm::None, GetQOffsets("TEXTSEG=1234"));
+ EXPECT_EQ(llvm::None, GetQOffsets("TextSeg=0x1234"));
+ EXPECT_EQ(llvm::None, GetQOffsets("TextSeg=12345678123456789"));
+}
Index: lldb/test/API/functionalities/gdb_remote_client/qOffsets.yaml
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/qOffsets.yaml
@@ -0,0 +1,19 @@
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_AARCH64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: "c3c3c3c3"
+ - Name: .note.ABI-tag
+ Type: SHT_NOTE
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1004
+ AddressAlign: 0x4
+ Content: 040000001000000001000000474e550000000000030000000700000000000000
Index: lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
+++ lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
@@ -172,6 +172,8 @@
return self.qHostInfo()
if packet == "qGetWorkingDir":
return self.qGetWorkingDir()
+ if packet == "qOffsets":
+ return self.qOffsets();
if packet == "qsProcessInfo":
return self.qsProcessInfo()
if packet.startswith("qfProcessInfo"):
@@ -188,6 +190,9 @@
def qGetWorkingDir(self):
return "2f"
+ def qOffsets(self):
+ return ""
+
def qHostInfo(self):
return "ptrsize:8;endian:little;"
Index: lldb/test/API/functionalities/gdb_remote_client/TestqOffsets.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/TestqOffsets.py
@@ -0,0 +1,28 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestqOffsets(GDBRemoteTestBase):
+
+ class Responder(MockGDBServerResponder):
+ def qOffsets(self):
+ return 'Text=470000;Data=470000'
+
+ def setUp(self):
+ super(TestqOffsets, self).setUp()
+ self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ def tearDown(self):
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
+ super(TestqOffsets, self).tearDown()
+
+ def test(self):
+ self.server.responder = TestqOffsets.Responder()
+ target = self.createTarget("qOffsets.yaml")
+ text = target.modules[0].FindSection(".text")
+ self.assertEquals(text.GetLoadAddress(target), lldb.LLDB_INVALID_ADDRESS)
+
+ process = self.connect(target)
+ self.assertEquals(text.GetLoadAddress(target), 0x471000)
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
@@ -377,6 +377,7 @@
bool UpdateThreadIDList();
void DidLaunchOrAttach(ArchSpec &process_arch);
+ void MaybeLoadExecutableModule();
Status ConnectToDebugserver(llvm::StringRef host_port);
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
@@ -1102,6 +1102,8 @@
}
}
+ MaybeLoadExecutableModule();
+
// Find out which StructuredDataPlugins are supported by the debug monitor.
// These plugins transmit data over async $J packets.
if (StructuredData::Array *supported_packets =
@@ -1109,6 +1111,31 @@
MapSupportedStructuredDataPlugins(*supported_packets);
}
+void ProcessGDBRemote::MaybeLoadExecutableModule() {
+ ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (!module_sp)
+ return;
+
+ llvm::Optional<QOffsets> offsets = m_gdb_comm.GetQOffsets();
+ if (!offsets)
+ return;
+
+ bool is_uniform =
+ size_t(llvm::count(offsets->offsets, offsets->offsets[0])) ==
+ offsets->offsets.size();
+ if (!is_uniform)
+ return; // TODO: Handle non-uniform responses.
+
+ bool changed = false;
+ module_sp->SetLoadAddress(GetTarget(), offsets->offsets[0],
+ /*value_is_offset=*/true, changed);
+ if (changed) {
+ ModuleList list;
+ list.Append(module_sp);
+ m_process->GetTarget().ModulesDidLoad(list);
+ }
+}
+
void ProcessGDBRemote::DidLaunch() {
ArchSpec process_arch;
DidLaunchOrAttach(process_arch);
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
@@ -31,6 +31,22 @@
namespace lldb_private {
namespace process_gdb_remote {
+/// The offsets used by the target when relocating the executable. Decoded from
+/// qOffsets packet response.
+struct QOffsets {
+ /// If true, the offsets field describes segments. Otherwise, it describes
+ /// sections.
+ bool segments;
+
+ /// The individual offsets. Section offsets have two or three members.
+ /// Segment offsets have either one of two.
+ std::vector<uint64_t> offsets;
+};
+inline bool operator==(const QOffsets &a, const QOffsets &b) {
+ return a.segments == b.segments && a.offsets == b.offsets;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets);
+
class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
public:
GDBRemoteCommunicationClient();
@@ -425,6 +441,11 @@
bool GetSharedCacheInfoSupported();
+ /// 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.
+ llvm::Optional<QOffsets> GetQOffsets();
+
bool GetModuleInfo(const FileSpec &module_file_spec,
const ArchSpec &arch_spec, ModuleSpec &module_spec);
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
@@ -45,6 +45,13 @@
using namespace lldb_private;
using namespace std::chrono;
+llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os,
+ const QOffsets &offsets) {
+ return os << llvm::formatv(
+ "QOffsets({0}, [{1:@[x]}])", offsets.segments,
+ llvm::make_range(offsets.offsets.begin(), offsets.offsets.end()));
+}
+
// GDBRemoteCommunicationClient constructor
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
: GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
@@ -3531,6 +3538,46 @@
return error;
}
+llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(
+ "qOffsets", response, /*send_async=*/false) != PacketResult::Success)
+ return llvm::None;
+ if (!response.IsNormalResponse())
+ return llvm::None;
+
+ QOffsets result;
+ llvm::StringRef ref = response.GetStringRef();
+ const auto &GetOffset = [&] {
+ addr_t offset;
+ if (ref.consumeInteger(16, offset))
+ return false;
+ result.offsets.push_back(offset);
+ return true;
+ };
+
+ if (ref.consume_front("Text=")) {
+ result.segments = false;
+ if (!GetOffset())
+ return llvm::None;
+ if (!ref.consume_front(";Data=") || !GetOffset())
+ return llvm::None;
+ if (ref.empty())
+ return result;
+ if (ref.consume_front(";Bss=") && GetOffset() && ref.empty())
+ return result;
+ } else if (ref.consume_front("TextSeg=")) {
+ result.segments = true;
+ if (!GetOffset())
+ return llvm::None;
+ if (ref.empty())
+ return result;
+ if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty())
+ return result;
+ }
+ return llvm::None;
+}
+
bool GDBRemoteCommunicationClient::GetModuleInfo(
const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
ModuleSpec &module_spec) {
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits