Index: lib/sanitizer_common/sanitizer_procmaps.h =================================================================== --- lib/sanitizer_common/sanitizer_procmaps.h +++ lib/sanitizer_common/sanitizer_procmaps.h @@ -65,6 +65,18 @@ ModuleArch arch; u8 uuid[kModuleUUIDSize]; bool has_sections; + + private: +#if SANITIZER_MAC + friend class MemoryMappingLayout; + + template + bool NextSectionLoad(MemoryMappedSection *section); + uptr nsects_; + char *current_load_cmd_addr_; + u32 lc_type_; + uptr base_virt_addr_; +#endif }; class MemoryMappingLayout { Index: lib/sanitizer_common/sanitizer_procmaps_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -35,8 +35,31 @@ #endif namespace __sanitizer { +template +bool MemoryMappedSegment::NextSectionLoad(MemoryMappedSection *section) { + const Section *sc = (const Section *)current_load_cmd_addr_; + current_load_cmd_addr_ += sizeof(Section); + + section->start = sc->addr + base_virt_addr_; + section->end = section->start + sc->size; + section->offset = sc->offset; + + nsects_--; + return true; +} + bool MemoryMappedSegment::Next(MemoryMappedSection *section) { - return false; + if (nsects_ == 0) return false; + + bool ret = false; + if (lc_type_ == LC_SEGMENT) { + ret = NextSectionLoad(section); +#ifdef MH_MAGIC_64 + } else if (lc_type_ == LC_SEGMENT_64) { + ret = NextSectionLoad(section); +#endif + } + return ret; } MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { @@ -146,22 +169,28 @@ current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize; if (((const load_command *)lc)->cmd == kLCSegment) { const SegmentCommand* sc = (const SegmentCommand *)lc; - segment->has_sections = false; + segment->current_load_cmd_addr_ = (char *)lc + sizeof(SegmentCommand); + segment->lc_type_ = kLCSegment; + segment->nsects_ = sc->nsects; + + // Some macho segments don't contain sections + segment->has_sections = segment->nsects_; if (current_image_ == kDyldImageIdx) { + segment->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(); + segment->start = (sc->vmaddr & 0xfffff) + segment->base_virt_addr_; } else { - const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_); - segment->start = sc->vmaddr + dlloff; - segment->end = sc->vmaddr + sc->vmsize + dlloff; + segment->base_virt_addr_ = + (uptr)_dyld_get_image_vmaddr_slide(current_image_); + segment->start = sc->vmaddr + segment->base_virt_addr_; } + segment->end = segment->start + sc->vmsize; // Return the initial protection. segment->protection = sc->initprot;