summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Ricci <francisjricci@gmail.com>2017-07-25 15:27:32 +0000
committerFrancis Ricci <francisjricci@gmail.com>2017-07-25 15:27:32 +0000
commit26aeaee1b40622ec7250f857078aebc765a39269 (patch)
tree48940c181c8e330a1fcd9b79a58219abf9ef4e0c
parent3fba40218b918a973d76d4281d87d0dae75c40a9 (diff)
Add address ranges for individual macho sections on darwin
Summary: This is a re-upload of the reverted commit r308644. It has changed quite a bit to reflect post-commit comments by kcc, so I'm re-uploading as a new review. Reviewers: kubamracek, alekseyshl, kcc Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35799 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@308977 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/sanitizer_common/sanitizer_procmaps.h15
-rw-r--r--lib/sanitizer_common/sanitizer_procmaps_common.cc7
-rw-r--r--lib/sanitizer_common/sanitizer_procmaps_mac.cc72
3 files changed, 82 insertions, 12 deletions
diff --git a/lib/sanitizer_common/sanitizer_procmaps.h b/lib/sanitizer_common/sanitizer_procmaps.h
index 539a53bc3..20b93c1d2 100644
--- a/lib/sanitizer_common/sanitizer_procmaps.h
+++ b/lib/sanitizer_common/sanitizer_procmaps.h
@@ -37,9 +37,12 @@ static const uptr kProtectionWrite = 2;
static const uptr kProtectionExecute = 4;
static const uptr kProtectionShared = 8;
-struct MemoryMappedSegment {
+struct MemoryMappedSegmentData;
+
+class MemoryMappedSegment {
+ public:
MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
- : filename(buff), filename_size(size) {}
+ : filename(buff), filename_size(size), data_(nullptr) {}
~MemoryMappedSegment() {}
bool IsReadable() const { return protection & kProtectionRead; }
@@ -47,6 +50,8 @@ struct MemoryMappedSegment {
bool IsExecutable() const { return protection & kProtectionExecute; }
bool IsShared() const { return protection & kProtectionShared; }
+ void AddAddressRanges(LoadedModule *module);
+
uptr start;
uptr end;
uptr offset;
@@ -55,6 +60,12 @@ struct MemoryMappedSegment {
uptr protection;
ModuleArch arch;
u8 uuid[kModuleUUIDSize];
+
+ private:
+ friend class MemoryMappingLayout;
+
+ // This field is assigned and owned by MemoryMappingLayout if needed
+ MemoryMappedSegmentData *data_;
};
class MemoryMappingLayout {
diff --git a/lib/sanitizer_common/sanitizer_procmaps_common.cc b/lib/sanitizer_common/sanitizer_procmaps_common.cc
index dac68ffe8..369b3ee1b 100644
--- a/lib/sanitizer_common/sanitizer_procmaps_common.cc
+++ b/lib/sanitizer_common/sanitizer_procmaps_common.cc
@@ -64,6 +64,10 @@ uptr ParseHex(const char **p) {
return ParseNumber(p, 16);
}
+void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
+ module->addAddressRange(start, end, IsExecutable(), IsWritable());
+}
+
MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
ReadProcMaps(&proc_self_maps_);
if (cache_enabled) {
@@ -139,8 +143,7 @@ void MemoryMappingLayout::DumpListOfModules(
uptr base_address = (i ? segment.start : 0) - segment.offset;
LoadedModule cur_module;
cur_module.set(cur_name, base_address);
- cur_module.addAddressRange(segment.start, segment.end,
- segment.IsExecutable(), segment.IsWritable());
+ segment.AddAddressRanges(&cur_module);
modules->push_back(cur_module);
}
}
diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc
index 560451a16..4b26a1f2c 100644
--- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc
+++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc
@@ -36,6 +36,48 @@
namespace __sanitizer {
+// Contains information used to iterate through sections.
+struct MemoryMappedSegmentData {
+ uptr nsects;
+ char *current_load_cmd_addr;
+ u32 lc_type;
+ uptr base_virt_addr;
+ uptr addr_mask;
+};
+
+template <typename Section>
+static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
+ bool isWritable) {
+ const Section *sc = (const Section *)data->current_load_cmd_addr;
+ data->current_load_cmd_addr += sizeof(Section);
+
+ uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;
+ uptr sec_end = sec_start + sc->size;
+ module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable);
+}
+
+void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
+ // Don't iterate over sections when the caller hasn't set up the
+ // data pointer, when there are no sections, or when the segment
+ // is executable. Avoid iterating over executable sections because
+ // it will confuse libignore, and because the extra granularity
+ // of information is not needed by any sanitizers.
+ if (!data_ || !data_->nsects || IsExecutable()) {
+ module->addAddressRange(start, end, IsExecutable(), IsWritable());
+ return;
+ }
+
+ do {
+ if (data_->lc_type == LC_SEGMENT) {
+ NextSectionLoad<struct section>(module, data_, IsWritable());
+#ifdef MH_MAGIC_64
+ } else if (data_->lc_type == LC_SEGMENT_64) {
+ NextSectionLoad<struct section_64>(module, data_, IsWritable());
+#endif
+ }
+ } while (--data_->nsects);
+}
+
MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
Reset();
}
@@ -144,19 +186,32 @@ bool MemoryMappingLayout::NextSegmentLoad(MemoryMappedSegment *segment) {
if (((const load_command *)lc)->cmd == kLCSegment) {
const SegmentCommand* sc = (const SegmentCommand *)lc;
+ uptr base_virt_addr, addr_mask;
if (current_image_ == kDyldImageIdx) {
+ base_virt_addr = (uptr)get_dyld_hdr();
// vmaddr is masked with 0xfffff because on macOS versions < 10.12,
// it contains an absolute address rather than an offset for dyld.
// To make matters even more complicated, this absolute address
// isn't actually the absolute segment address, but the offset portion
// of the address is accurate when combined with the dyld base address,
// and the mask will give just this offset.
- segment->start = (sc->vmaddr & 0xfffff) + (uptr)get_dyld_hdr();
- segment->end = (sc->vmaddr & 0xfffff) + sc->vmsize + (uptr)get_dyld_hdr();
+ addr_mask = 0xfffff;
} else {
- const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
- segment->start = sc->vmaddr + dlloff;
- segment->end = sc->vmaddr + sc->vmsize + dlloff;
+ base_virt_addr = (uptr)_dyld_get_image_vmaddr_slide(current_image_);
+ addr_mask = ~0;
+ }
+ segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;
+ segment->end = segment->start + sc->vmsize;
+
+ // Most callers don't need section information, so only fill this struct
+ // when required.
+ if (segment->data_) {
+ segment->data_->nsects = sc->nsects;
+ segment->data_->current_load_cmd_addr =
+ (char *)lc + sizeof(SegmentCommand);
+ segment->data_->lc_type = kLCSegment;
+ segment->data_->base_virt_addr = base_virt_addr;
+ segment->data_->addr_mask = addr_mask;
}
// Return the initial protection.
@@ -292,7 +347,9 @@ void MemoryMappingLayout::DumpListOfModules(
Reset();
InternalScopedString module_name(kMaxPathLength);
MemoryMappedSegment segment(module_name.data(), kMaxPathLength);
- for (uptr i = 0; Next(&segment); i++) {
+ MemoryMappedSegmentData data;
+ segment.data_ = &data;
+ while (Next(&segment)) {
if (segment.filename[0] == '\0') continue;
LoadedModule *cur_module = nullptr;
if (!modules->empty() &&
@@ -304,8 +361,7 @@ void MemoryMappingLayout::DumpListOfModules(
cur_module->set(segment.filename, segment.start, segment.arch,
segment.uuid, current_instrumented_);
}
- cur_module->addAddressRange(segment.start, segment.end,
- segment.IsExecutable(), segment.IsWritable());
+ segment.AddAddressRanges(cur_module);
}
}