Skip to content

Commit 8a26ba6

Browse files
committed
Load binary by UUID from qProcessInfo packet fields
Support three new keys in the qProcessInfo response from the remote gdb stub to handle the case of attaching to a core running some type of standalone/firmware code and the stub knows the UUID and load address-or-slide for the binary. There will be no proper DynamicLoader plugin in this scenario, but we can try to locate and load the binary into lldb at the correct offset. Differential Revision: https://reviews.llvm.org/D116211 rdar://75191077
1 parent 6050962 commit 8a26ba6

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

lldb/docs/lldb-gdb-remote.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,9 @@ vendor: is a string that represents the vendor (apple)
10031003
endian: is one of "little", "big", or "pdp"
10041004
ptrsize: is a number that represents how big pointers are in bytes
10051005

1006+
main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows about
1007+
main-binary-address: is the load address of the firmware type binary
1008+
main-binary-slide: is the slide of the firmware type binary, if address isn't known
10061009

10071010
//----------------------------------------------------------------------
10081011
// "qShlibInfoAddr"

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,23 @@ GDBRemoteCommunicationClient::GetProcessArchitecture() {
10061006
return m_process_arch;
10071007
}
10081008

1009+
bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
1010+
UUID &uuid, addr_t &value, bool &value_is_offset) {
1011+
if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
1012+
GetCurrentProcessInfo();
1013+
1014+
// Return true if we have a UUID or an address/offset of the
1015+
// main standalone / firmware binary being used.
1016+
if (!m_process_standalone_uuid.IsValid() &&
1017+
m_process_standalone_value == LLDB_INVALID_ADDRESS)
1018+
return false;
1019+
1020+
uuid = m_process_standalone_uuid;
1021+
value = m_process_standalone_value;
1022+
value_is_offset = m_process_standalone_value_is_offset;
1023+
return true;
1024+
}
1025+
10091026
bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
10101027
if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
10111028
m_gdb_server_name.clear();
@@ -2147,6 +2164,25 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
21472164
} else if (name.equals("elf_abi")) {
21482165
elf_abi = std::string(value);
21492166
++num_keys_decoded;
2167+
} else if (name.equals("main-binary-uuid")) {
2168+
m_process_standalone_uuid.SetFromStringRef(value);
2169+
++num_keys_decoded;
2170+
} else if (name.equals("main-binary-slide")) {
2171+
StringExtractor extractor(value);
2172+
m_process_standalone_value =
2173+
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2174+
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2175+
m_process_standalone_value_is_offset = true;
2176+
++num_keys_decoded;
2177+
}
2178+
} else if (name.equals("main-binary-address")) {
2179+
StringExtractor extractor(value);
2180+
m_process_standalone_value =
2181+
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2182+
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2183+
m_process_standalone_value_is_offset = false;
2184+
++num_keys_decoded;
2185+
}
21502186
}
21512187
}
21522188
if (num_keys_decoded > 0)

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
217217

218218
const ArchSpec &GetProcessArchitecture();
219219

220+
bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value,
221+
bool &value_is_offset);
222+
220223
void GetRemoteQSupported();
221224

222225
bool GetVContSupported(char flavor);
@@ -584,6 +587,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
584587

585588
ArchSpec m_host_arch;
586589
ArchSpec m_process_arch;
590+
UUID m_process_standalone_uuid;
591+
lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS;
592+
bool m_process_standalone_value_is_offset = false;
587593
llvm::VersionTuple m_os_version;
588594
llvm::VersionTuple m_maccatalyst_version;
589595
std::string m_os_build;

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,94 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
561561
}
562562
}
563563

564+
// The remote stub may know about the "main binary" in
565+
// the context of a firmware debug session, and can
566+
// give us a UUID and an address/slide of where the
567+
// binary is loaded in memory.
568+
UUID standalone_uuid;
569+
addr_t standalone_value;
570+
bool standalone_value_is_offset;
571+
if (m_gdb_comm.GetProcessStandaloneBinary(
572+
standalone_uuid, standalone_value, standalone_value_is_offset)) {
573+
ModuleSP module_sp;
574+
575+
if (standalone_uuid.IsValid()) {
576+
ModuleSpec module_spec;
577+
module_spec.GetUUID() = standalone_uuid;
578+
579+
// Look up UUID in global module cache before attempting
580+
// a more expensive search.
581+
Status error = ModuleList::GetSharedModule(module_spec, module_sp,
582+
nullptr, nullptr, nullptr);
583+
584+
if (!module_sp) {
585+
// Force a an external lookup, if that tool is available.
586+
if (!module_spec.GetSymbolFileSpec())
587+
Symbols::DownloadObjectAndSymbolFile(module_spec, true);
588+
589+
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
590+
module_sp = std::make_shared<Module>(module_spec);
591+
}
592+
}
593+
594+
// If we couldn't find the binary anywhere else, as a last resort,
595+
// read it out of memory.
596+
if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS &&
597+
!standalone_value_is_offset) {
598+
char namebuf[80];
599+
snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64,
600+
standalone_value);
601+
module_sp =
602+
ReadModuleFromMemory(FileSpec(namebuf), standalone_value);
603+
}
604+
605+
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
606+
LIBLLDB_LOG_DYNAMIC_LOADER));
607+
if (module_sp.get()) {
608+
target.GetImages().AppendIfNeeded(module_sp, false);
609+
610+
bool changed = false;
611+
if (module_sp->GetObjectFile()) {
612+
if (standalone_value != LLDB_INVALID_ADDRESS) {
613+
if (log)
614+
log->Printf("Loading binary UUID %s at %s 0x%" PRIx64,
615+
standalone_uuid.GetAsString().c_str(),
616+
standalone_value_is_offset ? "offset" : "address",
617+
standalone_value);
618+
module_sp->SetLoadAddress(target, standalone_value,
619+
standalone_value_is_offset, changed);
620+
} else {
621+
// No address/offset/slide, load the binary at file address,
622+
// offset 0.
623+
if (log)
624+
log->Printf("Loading binary UUID %s at file address",
625+
standalone_uuid.GetAsString().c_str());
626+
const bool value_is_slide = true;
627+
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
628+
}
629+
} else {
630+
// In-memory image, load at its true address, offset 0.
631+
if (log)
632+
log->Printf("Loading binary UUID %s from memory",
633+
standalone_uuid.GetAsString().c_str());
634+
const bool value_is_slide = true;
635+
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
636+
}
637+
638+
ModuleList added_module;
639+
added_module.Append(module_sp, false);
640+
target.ModulesDidLoad(added_module);
641+
} else {
642+
if (log)
643+
log->Printf("Unable to find binary with UUID %s and load it at "
644+
"%s 0x%" PRIx64,
645+
standalone_uuid.GetAsString().c_str(),
646+
standalone_value_is_offset ? "offset" : "address",
647+
standalone_value);
648+
}
649+
}
650+
}
651+
564652
const StateType state = SetThreadStopInfo(response);
565653
if (state != eStateInvalid) {
566654
SetPrivateState(state);

0 commit comments

Comments
 (0)