Some old mach-o core files have an LC_IDENT load command
and there's a string in there that can be helpful in locating the kernel binary. Use it. <rdar://problem/31444711> llvm-svn: 299612
This commit is contained in:
parent
0b2331b5e7
commit
3533cec58b
|
@ -563,6 +563,19 @@ public:
|
|||
|
||||
virtual uint32_t GetNumThreadContexts() { return 0; }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Some object files may have an identifier string embedded in them,
|
||||
/// e.g. in a Mach-O core file using the LC_IDENT load command (which
|
||||
/// is obsolete, but can still be found in some old files)
|
||||
///
|
||||
/// @return
|
||||
/// Returns the identifier string if one exists, else an empty
|
||||
/// string.
|
||||
//------------------------------------------------------------------
|
||||
virtual std::string GetIdentifierString () {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
virtual lldb::RegisterContextSP
|
||||
GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) {
|
||||
return lldb::RegisterContextSP();
|
||||
|
|
|
@ -5353,6 +5353,37 @@ uint32_t ObjectFileMachO::GetNumThreadContexts() {
|
|||
return m_thread_context_offsets.GetSize();
|
||||
}
|
||||
|
||||
// The LC_IDENT load command has been obsoleted for a very
|
||||
// long time and it should not occur in Mach-O files. But
|
||||
// if it is there, it may contain a hint about where to find
|
||||
// the main binary in a core file, so we'll use it.
|
||||
std::string ObjectFileMachO::GetIdentifierString() {
|
||||
std::string result;
|
||||
ModuleSP module_sp(GetModule());
|
||||
if (module_sp) {
|
||||
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
|
||||
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
|
||||
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
|
||||
const uint32_t cmd_offset = offset;
|
||||
struct ident_command ident_command;
|
||||
if (m_data.GetU32(&offset, &ident_command, 2) == NULL)
|
||||
break;
|
||||
if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
|
||||
char *buf = (char *)malloc (ident_command.cmdsize);
|
||||
if (buf != nullptr
|
||||
&& m_data.CopyData (offset, ident_command.cmdsize, buf) == ident_command.cmdsize) {
|
||||
buf[ident_command.cmdsize - 1] = '\0';
|
||||
result = buf;
|
||||
}
|
||||
if (buf)
|
||||
free (buf);
|
||||
}
|
||||
offset = cmd_offset + ident_command.cmdsize;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
lldb::RegisterContextSP
|
||||
ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx,
|
||||
lldb_private::Thread &thread) {
|
||||
|
|
|
@ -111,6 +111,8 @@ public:
|
|||
|
||||
uint32_t GetNumThreadContexts() override;
|
||||
|
||||
std::string GetIdentifierString() override;
|
||||
|
||||
lldb::RegisterContextSP
|
||||
GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override;
|
||||
|
||||
|
|
|
@ -291,8 +291,42 @@ Error ProcessMachCore::DoLoadCore() {
|
|||
m_core_range_infos.Sort();
|
||||
}
|
||||
|
||||
if (m_dyld_addr == LLDB_INVALID_ADDRESS ||
|
||||
m_mach_kernel_addr == LLDB_INVALID_ADDRESS) {
|
||||
|
||||
bool found_main_binary_definitively = false;
|
||||
|
||||
// This checks for the presence of an LC_IDENT string in a core file;
|
||||
// LC_IDENT is very obsolete and should not be used in new code, but
|
||||
// if the load command is present, let's use the contents.
|
||||
std::string corefile_identifier = core_objfile->GetIdentifierString();
|
||||
if (corefile_identifier.find("Darwin Kernel") != std::string::npos) {
|
||||
UUID uuid;
|
||||
addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
if (corefile_identifier.find("UUID=") != std::string::npos) {
|
||||
size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
|
||||
std::string uuid_str = corefile_identifier.substr(p, 36);
|
||||
uuid.SetFromCString(uuid_str.c_str());
|
||||
}
|
||||
if (corefile_identifier.find("stext=") != std::string::npos) {
|
||||
size_t p = corefile_identifier.find("stext=") + strlen("stext=");
|
||||
if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
|
||||
errno = 0;
|
||||
addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16);
|
||||
if (errno != 0 || addr == 0)
|
||||
addr = LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) {
|
||||
m_mach_kernel_addr = addr;
|
||||
found_main_binary_definitively = true;
|
||||
if (log)
|
||||
log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
|
||||
"from LC_IDENT string '%s'", addr, corefile_identifier.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (found_main_binary_definitively == false &&
|
||||
(m_dyld_addr == LLDB_INVALID_ADDRESS ||
|
||||
m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
|
||||
// We need to locate the main executable in the memory ranges
|
||||
// we have in the core file. We need to search for both a user-process dyld
|
||||
// binary
|
||||
|
@ -317,7 +351,8 @@ Error ProcessMachCore::DoLoadCore() {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
|
||||
if (found_main_binary_definitively == false
|
||||
&& m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
|
||||
// In the case of multiple kernel images found in the core file via
|
||||
// exhaustive
|
||||
// search, we may not pick the correct one. See if the
|
||||
|
|
Loading…
Reference in New Issue