Add support for firmware/standalone LC_NOTE "main bin spec" corefiles

When a Mach-O corefile has an LC_NOTE "main bin spec" for a
standalone binary / firmware, with only a UUID and no load
address, try to locate the binary and dSYM by UUID and if
found, load it at offset 0 for the user.

Add a test case that tests a firmware/standalone corefile
with both the "kern ver str" and "main bin spec" LC_NOTEs.

<rdar://problem/68193804>

Differential Revision: https://reviews.llvm.org/D88282
This commit is contained in:
Jason Molenda
2020-09-25 14:08:44 -07:00
parent a83eb048cb
commit 1bec6eb3f5
9 changed files with 663 additions and 94 deletions

View File

@@ -5519,7 +5519,8 @@ std::string ObjectFileMachO::GetIdentifierString() {
return result;
}
bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &address, UUID &uuid) {
bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &address, UUID &uuid,
ObjectFile::BinaryType &type) {
address = LLDB_INVALID_ADDRESS;
uuid.Clear();
ModuleSP module_sp(GetModule());
@@ -5542,24 +5543,43 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &address, UUID &uuid) {
// "main bin spec" (main binary specification) data payload is
// formatted:
// uint32_t version [currently 1]
// uint32_t type [0 == unspecified, 1 == kernel, 2 == user
// process] uint64_t address [ UINT64_MAX if address not
// specified ] uuid_t uuid [ all zero's if uuid not
// specified ] uint32_t log2_pagesize [ process page size in log base
// 2, e.g. 4k pages are 12. 0 for unspecified ]
// uint32_t type [0 == unspecified, 1 == kernel,
// 2 == user process, 3 == firmware ]
// uint64_t address [ UINT64_MAX if address not specified ]
// uuid_t uuid [ all zero's if uuid not specified ]
// uint32_t log2_pagesize [ process page size in log base
// 2, e.g. 4k pages are 12.
// 0 for unspecified ]
// uint32_t unused [ for alignment ]
if (strcmp("main bin spec", data_owner) == 0 && size >= 32) {
offset = fileoff;
uint32_t version;
if (m_data.GetU32(&offset, &version, 1) != nullptr && version == 1) {
uint32_t type = 0;
uint32_t binspec_type = 0;
uuid_t raw_uuid;
memset(raw_uuid, 0, sizeof(uuid_t));
if (m_data.GetU32(&offset, &type, 1) &&
if (m_data.GetU32(&offset, &binspec_type, 1) &&
m_data.GetU64(&offset, &address, 1) &&
m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) {
uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t));
// convert the "main bin spec" type into our
// ObjectFile::BinaryType enum
switch (binspec_type) {
case 0:
type = eBinaryTypeUnknown;
break;
case 1:
type = eBinaryTypeKernel;
break;
case 2:
type = eBinaryTypeUser;
break;
case 3:
type = eBinaryTypeStandalone;
break;
}
return true;
}
}