forked from OSchip/llvm-project
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
This commit is contained in:
parent
60509623c4
commit
8a26ba6a02
|
@ -1003,6 +1003,9 @@ vendor: is a string that represents the vendor (apple)
|
|||
endian: is one of "little", "big", or "pdp"
|
||||
ptrsize: is a number that represents how big pointers are in bytes
|
||||
|
||||
main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows about
|
||||
main-binary-address: is the load address of the firmware type binary
|
||||
main-binary-slide: is the slide of the firmware type binary, if address isn't known
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// "qShlibInfoAddr"
|
||||
|
|
|
@ -1006,6 +1006,23 @@ GDBRemoteCommunicationClient::GetProcessArchitecture() {
|
|||
return m_process_arch;
|
||||
}
|
||||
|
||||
bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
|
||||
UUID &uuid, addr_t &value, bool &value_is_offset) {
|
||||
if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
|
||||
GetCurrentProcessInfo();
|
||||
|
||||
// Return true if we have a UUID or an address/offset of the
|
||||
// main standalone / firmware binary being used.
|
||||
if (!m_process_standalone_uuid.IsValid() &&
|
||||
m_process_standalone_value == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
|
||||
uuid = m_process_standalone_uuid;
|
||||
value = m_process_standalone_value;
|
||||
value_is_offset = m_process_standalone_value_is_offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
|
||||
if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
|
||||
m_gdb_server_name.clear();
|
||||
|
@ -2147,6 +2164,25 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
|
|||
} else if (name.equals("elf_abi")) {
|
||||
elf_abi = std::string(value);
|
||||
++num_keys_decoded;
|
||||
} else if (name.equals("main-binary-uuid")) {
|
||||
m_process_standalone_uuid.SetFromStringRef(value);
|
||||
++num_keys_decoded;
|
||||
} else if (name.equals("main-binary-slide")) {
|
||||
StringExtractor extractor(value);
|
||||
m_process_standalone_value =
|
||||
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
|
||||
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
|
||||
m_process_standalone_value_is_offset = true;
|
||||
++num_keys_decoded;
|
||||
}
|
||||
} else if (name.equals("main-binary-address")) {
|
||||
StringExtractor extractor(value);
|
||||
m_process_standalone_value =
|
||||
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
|
||||
if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
|
||||
m_process_standalone_value_is_offset = false;
|
||||
++num_keys_decoded;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_keys_decoded > 0)
|
||||
|
|
|
@ -217,6 +217,9 @@ public:
|
|||
|
||||
const ArchSpec &GetProcessArchitecture();
|
||||
|
||||
bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value,
|
||||
bool &value_is_offset);
|
||||
|
||||
void GetRemoteQSupported();
|
||||
|
||||
bool GetVContSupported(char flavor);
|
||||
|
@ -584,6 +587,9 @@ protected:
|
|||
|
||||
ArchSpec m_host_arch;
|
||||
ArchSpec m_process_arch;
|
||||
UUID m_process_standalone_uuid;
|
||||
lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS;
|
||||
bool m_process_standalone_value_is_offset = false;
|
||||
llvm::VersionTuple m_os_version;
|
||||
llvm::VersionTuple m_maccatalyst_version;
|
||||
std::string m_os_build;
|
||||
|
|
|
@ -561,6 +561,94 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) {
|
|||
}
|
||||
}
|
||||
|
||||
// The remote stub may know about the "main binary" in
|
||||
// the context of a firmware debug session, and can
|
||||
// give us a UUID and an address/slide of where the
|
||||
// binary is loaded in memory.
|
||||
UUID standalone_uuid;
|
||||
addr_t standalone_value;
|
||||
bool standalone_value_is_offset;
|
||||
if (m_gdb_comm.GetProcessStandaloneBinary(
|
||||
standalone_uuid, standalone_value, standalone_value_is_offset)) {
|
||||
ModuleSP module_sp;
|
||||
|
||||
if (standalone_uuid.IsValid()) {
|
||||
ModuleSpec module_spec;
|
||||
module_spec.GetUUID() = standalone_uuid;
|
||||
|
||||
// Look up UUID in global module cache before attempting
|
||||
// a more expensive search.
|
||||
Status error = ModuleList::GetSharedModule(module_spec, module_sp,
|
||||
nullptr, nullptr, nullptr);
|
||||
|
||||
if (!module_sp) {
|
||||
// Force a an external lookup, if that tool is available.
|
||||
if (!module_spec.GetSymbolFileSpec())
|
||||
Symbols::DownloadObjectAndSymbolFile(module_spec, true);
|
||||
|
||||
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
|
||||
module_sp = std::make_shared<Module>(module_spec);
|
||||
}
|
||||
}
|
||||
|
||||
// If we couldn't find the binary anywhere else, as a last resort,
|
||||
// read it out of memory.
|
||||
if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS &&
|
||||
!standalone_value_is_offset) {
|
||||
char namebuf[80];
|
||||
snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64,
|
||||
standalone_value);
|
||||
module_sp =
|
||||
ReadModuleFromMemory(FileSpec(namebuf), standalone_value);
|
||||
}
|
||||
|
||||
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
|
||||
LIBLLDB_LOG_DYNAMIC_LOADER));
|
||||
if (module_sp.get()) {
|
||||
target.GetImages().AppendIfNeeded(module_sp, false);
|
||||
|
||||
bool changed = false;
|
||||
if (module_sp->GetObjectFile()) {
|
||||
if (standalone_value != LLDB_INVALID_ADDRESS) {
|
||||
if (log)
|
||||
log->Printf("Loading binary UUID %s at %s 0x%" PRIx64,
|
||||
standalone_uuid.GetAsString().c_str(),
|
||||
standalone_value_is_offset ? "offset" : "address",
|
||||
standalone_value);
|
||||
module_sp->SetLoadAddress(target, standalone_value,
|
||||
standalone_value_is_offset, changed);
|
||||
} else {
|
||||
// No address/offset/slide, load the binary at file address,
|
||||
// offset 0.
|
||||
if (log)
|
||||
log->Printf("Loading binary UUID %s at file address",
|
||||
standalone_uuid.GetAsString().c_str());
|
||||
const bool value_is_slide = true;
|
||||
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
|
||||
}
|
||||
} else {
|
||||
// In-memory image, load at its true address, offset 0.
|
||||
if (log)
|
||||
log->Printf("Loading binary UUID %s from memory",
|
||||
standalone_uuid.GetAsString().c_str());
|
||||
const bool value_is_slide = true;
|
||||
module_sp->SetLoadAddress(target, 0, value_is_slide, changed);
|
||||
}
|
||||
|
||||
ModuleList added_module;
|
||||
added_module.Append(module_sp, false);
|
||||
target.ModulesDidLoad(added_module);
|
||||
} else {
|
||||
if (log)
|
||||
log->Printf("Unable to find binary with UUID %s and load it at "
|
||||
"%s 0x%" PRIx64,
|
||||
standalone_uuid.GetAsString().c_str(),
|
||||
standalone_value_is_offset ? "offset" : "address",
|
||||
standalone_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const StateType state = SetThreadStopInfo(response);
|
||||
if (state != eStateInvalid) {
|
||||
SetPrivateState(state);
|
||||
|
|
Loading…
Reference in New Issue