summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_procmaps_mac.cc
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2016-12-02 21:27:14 +0000
committerKuba Mracek <mracek@apple.com>2016-12-02 21:27:14 +0000
commit74c8f498fa128f0cd4eb97d603c017f250dd3694 (patch)
treea568579c59198d668eb06237a8483c0cf9cbd2d0 /lib/sanitizer_common/sanitizer_procmaps_mac.cc
parent4ca6e75ef3a392468b39bd7d99238580859228ce (diff)
[sanitizer] Track architecture and UUID of modules in LoadedModule
When we enumerate loaded modules, we only track the module name and base address, which then has several problems on macOS. Dylibs and executables often have several architecture slices and not storing which architecture/UUID is actually loaded creates problems with symbolication: A file path + offset isn't enough to correctly symbolicate, since the offset can be valid in multiple slices. This is especially common for Haswell+ X86_64 machines, where x86_64h slices are preferred, but if one is not available, a regular x86_64 is loaded instead. But the same issue exists for i386 vs. x86_64 as well. This patch adds tracking of arch and UUID for each LoadedModule. At this point, this information isn't used in reports, but this is the first step. The goal is to correctly identify which slice is loaded in symbolication, and also to output this information in reports so that we can tell which exact slices were loaded in post-mortem analysis. Differential Revision: https://reviews.llvm.org/D26632 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@288537 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_procmaps_mac.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_procmaps_mac.cc77
1 files changed, 67 insertions, 10 deletions
diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc
index 417cc908e..2b4ad5cbb 100644
--- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc
+++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc
@@ -53,6 +53,8 @@ void MemoryMappingLayout::Reset() {
current_load_cmd_addr_ = 0;
current_magic_ = 0;
current_filetype_ = 0;
+ current_arch_ = kModuleArchUnknown;
+ internal_memset(current_uuid_, 0, kModuleUUIDSize);
}
// static
@@ -71,11 +73,12 @@ void MemoryMappingLayout::LoadFromCache() {
// and returns the start and end addresses and file offset of the corresponding
// segment.
// Note that the segment addresses are not necessarily sorted.
-template<u32 kLCSegment, typename SegmentCommand>
-bool MemoryMappingLayout::NextSegmentLoad(
- uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size, uptr *protection) {
- const char* lc = current_load_cmd_addr_;
+template <u32 kLCSegment, typename SegmentCommand>
+bool MemoryMappingLayout::NextSegmentLoad(uptr *start, uptr *end, uptr *offset,
+ char filename[], uptr filename_size,
+ ModuleArch *arch, u8 *uuid,
+ uptr *protection) {
+ const char *lc = current_load_cmd_addr_;
current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
if (((const load_command *)lc)->cmd == kLCSegment) {
const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
@@ -97,14 +100,61 @@ bool MemoryMappingLayout::NextSegmentLoad(
internal_strncpy(filename, _dyld_get_image_name(current_image_),
filename_size);
}
+ if (arch) {
+ *arch = current_arch_;
+ }
+ if (uuid) {
+ internal_memcpy(uuid, current_uuid_, kModuleUUIDSize);
+ }
return true;
}
return false;
}
+ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {
+ cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK;
+ switch (cputype) {
+ case CPU_TYPE_I386:
+ return kModuleArchI386;
+ case CPU_TYPE_X86_64:
+ if (cpusubtype == CPU_SUBTYPE_X86_64_ALL) return kModuleArchX86_64;
+ if (cpusubtype == CPU_SUBTYPE_X86_64_H) return kModuleArchX86_64H;
+ CHECK(0 && "Invalid subtype of x86_64");
+ return kModuleArchUnknown;
+ case CPU_TYPE_ARM:
+ if (cpusubtype == CPU_SUBTYPE_ARM_V6) return kModuleArchARMV6;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7) return kModuleArchARMV7;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7S) return kModuleArchARMV7S;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7K) return kModuleArchARMV7K;
+ CHECK(0 && "Invalid subtype of ARM");
+ return kModuleArchUnknown;
+ case CPU_TYPE_ARM64:
+ return kModuleArchARM64;
+ default:
+ CHECK(0 && "Invalid CPU type");
+ return kModuleArchUnknown;
+ }
+}
+
+static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
+ const load_command *current_lc = first_lc;
+ while (1) {
+ if (current_lc->cmd == 0) return;
+ if (current_lc->cmd == LC_UUID) {
+ const uuid_command *uuid_lc = (const uuid_command *)current_lc;
+ const uint8_t *uuid = &uuid_lc->uuid[0];
+ internal_memcpy(uuid_output, uuid, kModuleUUIDSize);
+ return;
+ }
+
+ current_lc =
+ (const load_command *)(((char *)current_lc) + current_lc->cmdsize);
+ }
+}
+
bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
char filename[], uptr filename_size,
- uptr *protection) {
+ uptr *protection, ModuleArch *arch, u8 *uuid) {
for (; current_image_ >= 0; current_image_--) {
const mach_header* hdr = _dyld_get_image_header(current_image_);
if (!hdr) continue;
@@ -113,6 +163,7 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
current_load_cmd_count_ = hdr->ncmds;
current_magic_ = hdr->magic;
current_filetype_ = hdr->filetype;
+ current_arch_ = ModuleArchFromCpuType(hdr->cputype, hdr->cpusubtype);
switch (current_magic_) {
#ifdef MH_MAGIC_64
case MH_MAGIC_64: {
@@ -130,20 +181,24 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
}
}
+ FindUUID((const load_command *)current_load_cmd_addr_, &current_uuid_[0]);
+
for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
switch (current_magic_) {
// current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
#ifdef MH_MAGIC_64
case MH_MAGIC_64: {
if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
- start, end, offset, filename, filename_size, protection))
+ start, end, offset, filename, filename_size, arch, uuid,
+ protection))
return true;
break;
}
#endif
case MH_MAGIC: {
if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
- start, end, offset, filename, filename_size, protection))
+ start, end, offset, filename, filename_size, arch, uuid,
+ protection))
return true;
break;
}
@@ -159,9 +214,11 @@ void MemoryMappingLayout::DumpListOfModules(
InternalMmapVector<LoadedModule> *modules) {
Reset();
uptr cur_beg, cur_end, prot;
+ ModuleArch cur_arch;
+ u8 cur_uuid[kModuleUUIDSize];
InternalScopedString module_name(kMaxPathLength);
for (uptr i = 0; Next(&cur_beg, &cur_end, 0, module_name.data(),
- module_name.size(), &prot);
+ module_name.size(), &prot, &cur_arch, &cur_uuid[0]);
i++) {
const char *cur_name = module_name.data();
if (cur_name[0] == '\0')
@@ -173,7 +230,7 @@ void MemoryMappingLayout::DumpListOfModules(
} else {
modules->push_back(LoadedModule());
cur_module = &modules->back();
- cur_module->set(cur_name, cur_beg);
+ cur_module->set(cur_name, cur_beg, cur_arch, cur_uuid);
}
cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute);
}