Skip to content

Commit 6bbb63f

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 (cherry picked from commit 8a26ba6)
1 parent eaee47c commit 6bbb63f

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
@@ -977,6 +977,23 @@ GDBRemoteCommunicationClient::GetProcessArchitecture() {
977977
return m_process_arch;
978978
}
979979

980+
bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
981+
UUID &uuid, addr_t &value, bool &value_is_offset) {
982+
if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
983+
GetCurrentProcessInfo();
984+
985+
// Return true if we have a UUID or an address/offset of the
986+
// main standalone / firmware binary being used.
987+
if (!m_process_standalone_uuid.IsValid() &&
988+
m_process_standalone_value == LLDB_INVALID_ADDRESS)
989+
return false;
990+
991+
uuid = m_process_standalone_uuid;
992+
value = m_process_standalone_value;
993+
value_is_offset = m_process_standalone_value_is_offset;
994+
return true;
995+
}
996+
980997
bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
981998
if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
982999
m_gdb_server_name.clear();
@@ -2136,6 +2153,25 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
21362153
} else if (name.equals("elf_abi")) {
21372154
elf_abi = std::string(value);
21382155
++num_keys_decoded;
2156+
} else if (name.equals("main-binary-uuid")) {
2157+
m_process_standalone_uuid.SetFromStringRef(value);
2158+
++num_keys_decoded;
2159+
} else if (name.equals("main-binary-slide")) {
2160+
StringExtractor extractor(value);
2161+
m_process_standalone_value =
2162+
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2163+
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2164+
m_process_standalone_value_is_offset = true;
2165+
++num_keys_decoded;
2166+
}
2167+
} else if (name.equals("main-binary-address")) {
2168+
StringExtractor extractor(value);
2169+
m_process_standalone_value =
2170+
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2171+
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2172+
m_process_standalone_value_is_offset = false;
2173+
++num_keys_decoded;
2174+
}
21392175
}
21402176
}
21412177
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
@@ -253,6 +253,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
253253

254254
const ArchSpec &GetProcessArchitecture();
255255

256+
bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value,
257+
bool &value_is_offset);
258+
256259
void GetRemoteQSupported();
257260

258261
bool GetVContSupported(char flavor);
@@ -606,6 +609,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
606609

607610
ArchSpec m_host_arch;
608611
ArchSpec m_process_arch;
612+
UUID m_process_standalone_uuid;
613+
lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS;
614+
bool m_process_standalone_value_is_offset = false;
609615
llvm::VersionTuple m_os_version;
610616
llvm::VersionTuple m_maccatalyst_version;
611617
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
@@ -678,6 +678,94 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
678678
}
679679
}
680680

681+
// The remote stub may know about the "main binary" in
682+
// the context of a firmware debug session, and can
683+
// give us a UUID and an address/slide of where the
684+
// binary is loaded in memory.
685+
UUID standalone_uuid;
686+
addr_t standalone_value;
687+
bool standalone_value_is_offset;
688+
if (m_gdb_comm.GetProcessStandaloneBinary(
689+
standalone_uuid, standalone_value, standalone_value_is_offset)) {
690+
ModuleSP module_sp;
691+
692+
if (standalone_uuid.IsValid()) {
693+
ModuleSpec module_spec;
694+
module_spec.GetUUID() = standalone_uuid;
695+
696+
// Look up UUID in global module cache before attempting
697+
// a more expensive search.
698+
Status error = ModuleList::GetSharedModule(module_spec, module_sp,
699+
nullptr, nullptr, nullptr);
700+
701+
if (!module_sp) {
702+
// Force a an external lookup, if that tool is available.
703+
if (!module_spec.GetSymbolFileSpec())
704+
Symbols::DownloadObjectAndSymbolFile(module_spec, true);
705+
706+
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
707+
module_sp = std::make_shared<Module>(module_spec);
708+
}
709+
}
710+
711+
// If we couldn't find the binary anywhere else, as a last resort,
712+
// read it out of memory.
713+
if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS &&
714+
!standalone_value_is_offset) {
715+
char namebuf[80];
716+
snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64,
717+
standalone_value);
718+
module_sp =
719+
ReadModuleFromMemory(FileSpec(namebuf), standalone_value);
720+
}
721+
722+
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
723+
LIBLLDB_LOG_DYNAMIC_LOADER));
724+
if (module_sp.get()) {
725+
target.GetImages().AppendIfNeeded(module_sp, false);
726+
727+
bool changed = false;
728+
if (module_sp->GetObjectFile()) {
729+
if (standalone_value != LLDB_INVALID_ADDRESS) {
730+
if (log)
731+
log->Printf("Loading binary UUID %s at %s 0x%" PRIx64,
732+
standalone_uuid.GetAsString().c_str(),
733+
standalone_value_is_offset ? "offset" : "address",
734+
standalone_value);
735+
module_sp->SetLoadAddress(target, standalone_value,
736+
standalone_value_is_offset, changed);
737+
} else {
738+
// No address/offset/slide, load the binary at file address,
739+
// offset 0.
740+
if (log)
741+
log->Printf("Loading binary UUID %s at file address",
742+
standalone_uuid.GetAsString().c_str());
743+
const bool value_is_slide = true;
744+
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
745+
}
746+
} else {
747+
// In-memory image, load at its true address, offset 0.
748+
if (log)
749+
log->Printf("Loading binary UUID %s from memory",
750+
standalone_uuid.GetAsString().c_str());
751+
const bool value_is_slide = true;
752+
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
753+
}
754+
755+
ModuleList added_module;
756+
added_module.Append(module_sp, false);
757+
target.ModulesDidLoad(added_module);
758+
} else {
759+
if (log)
760+
log->Printf("Unable to find binary with UUID %s and load it at "
761+
"%s 0x%" PRIx64,
762+
standalone_uuid.GetAsString().c_str(),
763+
standalone_value_is_offset ? "offset" : "address",
764+
standalone_value);
765+
}
766+
}
767+
}
768+
681769
const StateType state = SetThreadStopInfo(response);
682770
if (state != eStateInvalid) {
683771
SetPrivateState(state);

0 commit comments

Comments
 (0)