diff options
17 files changed, 165 insertions, 216 deletions
| diff --git a/compiler-rt/lib/asan/asan_errors.cc b/compiler-rt/lib/asan/asan_errors.cc index 57490ad180b..b7a38eb7cec 100644 --- a/compiler-rt/lib/asan/asan_errors.cc +++ b/compiler-rt/lib/asan/asan_errors.cc @@ -61,10 +61,9 @@ static void MaybeDumpRegisters(void *context) {  static void MaybeReportNonExecRegion(uptr pc) {  #if SANITIZER_FREEBSD || SANITIZER_LINUX    MemoryMappingLayout proc_maps(/*cache_enabled*/ true); -  uptr start, end, protection; -  while (proc_maps.Next(&start, &end, nullptr, nullptr, 0, &protection)) { -    if (pc >= start && pc < end && -        !(protection & MemoryMappingLayout::kProtectionExecute)) +  MemoryMappedSegment segment; +  while (proc_maps.Next(&segment)) { +    if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())        Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");    }  #endif diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index 50ef84c39a6..b546bc1a65e 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -140,9 +140,9 @@ void AsanCheckIncompatibleRT() {        // system libraries, causing crashes later in ASan initialization.        MemoryMappingLayout proc_maps(/*cache_enabled*/true);        char filename[128]; -      while (proc_maps.Next(nullptr, nullptr, nullptr, filename, -                            sizeof(filename), nullptr)) { -        if (IsDynamicRTName(filename)) { +      MemoryMappedSegment segment(filename, sizeof(filename)); +      while (proc_maps.Next(&segment)) { +        if (IsDynamicRTName(segment.filename)) {            Report("Your application is linked against "                   "incompatible ASan runtimes.\n");            Die(); diff --git a/compiler-rt/lib/esan/working_set.cpp b/compiler-rt/lib/esan/working_set.cpp index f39111993c3..e56902c8f32 100644 --- a/compiler-rt/lib/esan/working_set.cpp +++ b/compiler-rt/lib/esan/working_set.cpp @@ -160,15 +160,16 @@ static u32 countAndClearShadowValues(u32 BitIdx, uptr ShadowStart,  static u32 computeWorkingSizeAndReset(u32 BitIdx) {    u32 WorkingSetSize = 0;    MemoryMappingLayout MemIter(true/*cache*/); -  uptr Start, End, Prot; -  while (MemIter.Next(&Start, &End, nullptr/*offs*/, nullptr/*file*/, -                      0/*file size*/, &Prot)) { -    VPrintf(4, "%s: considering %p-%p app=%d shadow=%d prot=%u\n", -            __FUNCTION__, Start, End, Prot, isAppMem(Start), -            isShadowMem(Start)); -    if (isShadowMem(Start) && (Prot & MemoryMappingLayout::kProtectionWrite)) { -      VPrintf(3, "%s: walking %p-%p\n", __FUNCTION__, Start, End); -      WorkingSetSize += countAndClearShadowValues(BitIdx, Start, End); +  MemoryMappedSegment Segment; +  while (MemIter.Next(&Segment)) { +    VPrintf(4, "%s: considering %p-%p app=%d shadow=%d prot=%u\n", __FUNCTION__, +            Segment.start, Segment.end, Segment.protection, +            isAppMem(Segment.start), isShadowMem(Segment.start)); +    if (isShadowMem(Segment.start) && Segment.IsWritable()) { +      VPrintf(3, "%s: walking %p-%p\n", __FUNCTION__, Segment.start, +              Segment.end); +      WorkingSetSize += +          countAndClearShadowValues(BitIdx, Segment.start, Segment.end);      }    }    return WorkingSetSize; diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index db42ead83ad..4ffa91568cc 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -305,11 +305,10 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,  }  void ScanRootRegion(Frontier *frontier, const RootRegion &root_region, -                    uptr region_begin, uptr region_end, uptr prot) { +                    uptr region_begin, uptr region_end, bool is_readable) {    uptr intersection_begin = Max(root_region.begin, region_begin);    uptr intersection_end = Min(region_end, root_region.begin + root_region.size);    if (intersection_begin >= intersection_end) return; -  bool is_readable = prot & MemoryMappingLayout::kProtectionRead;    LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",                 root_region.begin, root_region.begin + root_region.size,                 region_begin, region_end, @@ -322,11 +321,10 @@ void ScanRootRegion(Frontier *frontier, const RootRegion &root_region,  static void ProcessRootRegion(Frontier *frontier,                                const RootRegion &root_region) {    MemoryMappingLayout proc_maps(/*cache_enabled*/ true); -  uptr begin, end, prot; -  while (proc_maps.Next(&begin, &end, -                        /*offset*/ nullptr, /*filename*/ nullptr, -                        /*filename_size*/ 0, &prot)) { -    ScanRootRegion(frontier, root_region, begin, end, prot); +  MemoryMappedSegment segment; +  while (proc_maps.Next(&segment)) { +    ScanRootRegion(frontier, root_region, segment.start, segment.end, +                   segment.IsReadable());    }  } diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index beb31d6f40e..d93ac1b1091 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -127,7 +127,7 @@ struct RootRegion {  InternalMmapVector<RootRegion> const *GetRootRegions();  void ScanRootRegion(Frontier *frontier, RootRegion const ®ion, -                    uptr region_begin, uptr region_end, uptr prot); +                    uptr region_begin, uptr region_end, bool is_readable);  // Run stoptheworld while holding any platform-specific locks.  void DoStopTheWorld(StopTheWorldCallback callback, void* argument); diff --git a/compiler-rt/lib/lsan/lsan_common_mac.cc b/compiler-rt/lib/lsan/lsan_common_mac.cc index adde3a1b403..f87c6b7e042 100644 --- a/compiler-rt/lib/lsan/lsan_common_mac.cc +++ b/compiler-rt/lib/lsan/lsan_common_mac.cc @@ -156,7 +156,7 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {      if (flags()->use_root_regions) {        for (uptr i = 0; i < root_regions->size(); i++) {          ScanRootRegion(frontier, (*root_regions)[i], address, end_address, -                       info.protection); +                       info.protection & kProtectionRead);        }      } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index c72fa436be1..4f3845f005d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -830,13 +830,9 @@ static uptr GetKernelAreaSize() {    // Firstly check if there are writable segments    // mapped to top gigabyte (e.g. stack).    MemoryMappingLayout proc_maps(/*cache_enabled*/true); -  uptr end, prot; -  while (proc_maps.Next(/*start*/nullptr, &end, -                        /*offset*/nullptr, /*filename*/nullptr, -                        /*filename_size*/0, &prot)) { -    if ((end >= 3 * gbyte) -        && (prot & MemoryMappingLayout::kProtectionWrite) != 0) -      return 0; +  MemoryMappedSegment segment; +  while (proc_maps.Next(&segment)) { +    if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;    }  #if !SANITIZER_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index b9a48a1e496..52196db1273 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -81,28 +81,25 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,      // Find the mapping that contains a stack variable.      MemoryMappingLayout proc_maps(/*cache_enabled*/true); -    uptr start, end, offset; +    MemoryMappedSegment segment;      uptr prev_end = 0; -    while (proc_maps.Next(&start, &end, &offset, nullptr, 0, -          /* protection */nullptr)) { -      if ((uptr)&rl < end) -        break; -      prev_end = end; +    while (proc_maps.Next(&segment)) { +      if ((uptr)&rl < segment.end) break; +      prev_end = segment.end;      } -    CHECK((uptr)&rl >= start && (uptr)&rl < end); +    CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);      // Get stacksize from rlimit, but clip it so that it does not overlap      // with other mappings.      uptr stacksize = rl.rlim_cur; -    if (stacksize > end - prev_end) -      stacksize = end - prev_end; +    if (stacksize > segment.end - prev_end) stacksize = segment.end - prev_end;      // When running with unlimited stack size, we still want to set some limit.      // The unlimited stack size is caused by 'ulimit -s unlimited'.      // Also, for some reason, GNU make spawns subprocesses with unlimited stack.      if (stacksize > kMaxThreadStackSize)        stacksize = kMaxThreadStackSize; -    *stack_top = end; -    *stack_bottom = end - stacksize; +    *stack_top = segment.end; +    *stack_bottom = segment.end - stacksize;      return;    }    pthread_attr_t attr; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index 4abc9d16dcb..8d3128ae199 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -231,13 +231,12 @@ static inline bool IntervalsAreSeparate(uptr start1, uptr end1,  // memory).  bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {    MemoryMappingLayout proc_maps(/*cache_enabled*/true); -  uptr start, end; -  while (proc_maps.Next(&start, &end, -                        /*offset*/nullptr, /*filename*/nullptr, -                        /*filename_size*/0, /*protection*/nullptr)) { -    if (start == end) continue;  // Empty range. -    CHECK_NE(0, end); -    if (!IntervalsAreSeparate(start, end - 1, range_start, range_end)) +  MemoryMappedSegment segment; +  while (proc_maps.Next(&segment)) { +    if (segment.start == segment.end) continue;  // Empty range. +    CHECK_NE(0, segment.end); +    if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start, +                              range_end))        return false;    }    return true; @@ -245,13 +244,13 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {  void DumpProcessMap() {    MemoryMappingLayout proc_maps(/*cache_enabled*/true); -  uptr start, end;    const sptr kBufSize = 4095;    char *filename = (char*)MmapOrDie(kBufSize, __func__); +  MemoryMappedSegment segment(filename, kBufSize);    Report("Process memory map follows:\n"); -  while (proc_maps.Next(&start, &end, /* file_offset */nullptr, -                        filename, kBufSize, /* protection */nullptr)) { -    Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); +  while (proc_maps.Next(&segment)) { +    Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end, +           segment.filename);    }    Report("End of process memory map.\n");    UnmapOrDie(filename, kBufSize); @@ -281,14 +280,14 @@ void ReportFile::Write(const char *buffer, uptr length) {  }  bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { -  uptr s, e, off, prot; -  InternalScopedString buff(kMaxPathLength);    MemoryMappingLayout proc_maps(/*cache_enabled*/false); -  while (proc_maps.Next(&s, &e, &off, buff.data(), buff.size(), &prot)) { -    if ((prot & MemoryMappingLayout::kProtectionExecute) != 0 -        && internal_strcmp(module, buff.data()) == 0) { -      *start = s; -      *end = e; +  InternalScopedString buff(kMaxPathLength); +  MemoryMappedSegment segment(buff.data(), kMaxPathLength); +  while (proc_maps.Next(&segment)) { +    if (segment.IsExecutable() && +        internal_strcmp(module, segment.filename) == 0) { +      *start = segment.start; +      *end = segment.end;        return true;      }    } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h index 5aad6b959ad..a0ac0b9196c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h @@ -31,13 +31,37 @@ struct ProcSelfMapsBuff {  void ReadProcMaps(ProcSelfMapsBuff *proc_maps);  #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX +// Memory protection masks. +static const uptr kProtectionRead = 1; +static const uptr kProtectionWrite = 2; +static const uptr kProtectionExecute = 4; +static const uptr kProtectionShared = 8; + +struct MemoryMappedSegment { +  MemoryMappedSegment(char *buff = nullptr, uptr size = 0) +      : filename(buff), filename_size(size) {} +  ~MemoryMappedSegment() {} + +  bool IsReadable() { return protection & kProtectionRead; } +  bool IsWritable() { return protection & kProtectionWrite; } +  bool IsExecutable() { return protection & kProtectionExecute; } +  bool IsShared() { return protection & kProtectionShared; } + +  uptr start; +  uptr end; +  uptr offset; +  char *filename;  // owned by caller +  uptr filename_size; +  uptr protection; +  ModuleArch arch; +  u8 uuid[kModuleUUIDSize]; +}; +  class MemoryMappingLayout {   public:    explicit MemoryMappingLayout(bool cache_enabled);    ~MemoryMappingLayout(); -  bool Next(uptr *start, uptr *end, uptr *offset, char filename[], -            uptr filename_size, uptr *protection, ModuleArch *arch = nullptr, -            u8 *uuid = nullptr); +  bool Next(MemoryMappedSegment *segment);    void Reset();    // In some cases, e.g. when running under a sandbox on Linux, ASan is unable    // to obtain the memory mappings. It should fall back to pre-cached data @@ -47,12 +71,6 @@ class MemoryMappingLayout {    // Adds all mapped objects into a vector.    void DumpListOfModules(InternalMmapVector<LoadedModule> *modules); -  // Memory protection masks. -  static const uptr kProtectionRead = 1; -  static const uptr kProtectionWrite = 2; -  static const uptr kProtectionExecute = 4; -  static const uptr kProtectionShared = 8; -   private:    void LoadFromCache(); @@ -67,10 +85,9 @@ class MemoryMappingLayout {    static StaticSpinMutex cache_lock_;  // protects cached_proc_self_maps_.  # elif SANITIZER_MAC    template <u32 kLCSegment, typename SegmentCommand> -  bool NextSegmentLoad(uptr *start, uptr *end, uptr *offset, char filename[], -                       uptr filename_size, ModuleArch *arch, u8 *uuid, -                       uptr *protection); -  void GetSegmentAddrRange(uptr *start, uptr *end, uptr vmaddr, uptr vmsize); +  bool NextSegmentLoad(MemoryMappedSegment *segment); +  void GetSegmentAddrRange(MemoryMappedSegment *segment, uptr vmaddr, +                           uptr vmsize);    int current_image_;    u32 current_magic_;    u32 current_filetype_; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc index c583f42f25d..b95f301a437 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc @@ -119,12 +119,10 @@ void MemoryMappingLayout::LoadFromCache() {  void MemoryMappingLayout::DumpListOfModules(      InternalMmapVector<LoadedModule> *modules) {    Reset(); -  uptr cur_beg, cur_end, cur_offset, prot;    InternalScopedString module_name(kMaxPathLength); -  for (uptr i = 0; Next(&cur_beg, &cur_end, &cur_offset, module_name.data(), -                        module_name.size(), &prot); -       i++) { -    const char *cur_name = module_name.data(); +  MemoryMappedSegment segment(module_name.data(), module_name.size()); +  for (uptr i = 0; Next(&segment); i++) { +    const char *cur_name = segment.filename;      if (cur_name[0] == '\0')        continue;      // Don't subtract 'cur_beg' from the first entry: @@ -138,11 +136,11 @@ void MemoryMappingLayout::DumpListOfModules(      //   mapped high at address space (in particular, higher than      //   shadow memory of the tool), so the module can't be the      //   first entry. -    uptr base_address = (i ? cur_beg : 0) - cur_offset; +    uptr base_address = (i ? segment.start : 0) - segment.offset;      LoadedModule cur_module;      cur_module.set(cur_name, base_address); -    cur_module.addAddressRange(cur_beg, cur_end, prot & kProtectionExecute, -                               prot & kProtectionWrite); +    cur_module.addAddressRange(segment.start, segment.end, +                               segment.IsExecutable(), segment.IsWritable());      modules->push_back(cur_module);    }  } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc index 30216456330..f0cdbeb4483 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_freebsd.cc @@ -48,36 +48,27 @@ void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {    proc_maps->len = Size;  } -bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, -                               char filename[], uptr filename_size, -                               uptr *protection, ModuleArch *arch, u8 *uuid) { -  CHECK(!arch && "not implemented"); -  CHECK(!uuid && "not implemented"); +bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {    char *last = proc_self_maps_.data + proc_self_maps_.len;    if (current_ >= last) return false; -  uptr dummy; -  if (!start) start = &dummy; -  if (!end) end = &dummy; -  if (!offset) offset = &dummy; -  if (!protection) protection = &dummy;    struct kinfo_vmentry *VmEntry = (struct kinfo_vmentry*)current_; -  *start = (uptr)VmEntry->kve_start; -  *end = (uptr)VmEntry->kve_end; -  *offset = (uptr)VmEntry->kve_offset; +  segment->start = (uptr)VmEntry->kve_start; +  segment->end = (uptr)VmEntry->kve_end; +  segment->offset = (uptr)VmEntry->kve_offset; -  *protection = 0; +  segment->protection = 0;    if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) -    *protection |= kProtectionRead; +    segment->protection |= kProtectionRead;    if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) -    *protection |= kProtectionWrite; +    segment->protection |= kProtectionWrite;    if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) -    *protection |= kProtectionExecute; +    segment->protection |= kProtectionExecute; -  if (filename != NULL && filename_size > 0) { -    internal_snprintf(filename, -                      Min(filename_size, (uptr)PATH_MAX), -                      "%s", VmEntry->kve_path); +  if (segment->filename != NULL && segment->filename_size > 0) { +    internal_snprintf(segment->filename, +                      Min(segment->filename_size, (uptr)PATH_MAX), "%s", +                      VmEntry->kve_path);    }    current_ += VmEntry->kve_structsize; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc index 7e4a44be95b..713bc21307f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc @@ -26,41 +26,28 @@ static bool IsOneOf(char c, char c1, char c2) {    return c == c1 || c == c2;  } -bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, -                               char filename[], uptr filename_size, -                               uptr *protection, ModuleArch *arch, u8 *uuid) { -  CHECK(!arch && "not implemented"); -  CHECK(!uuid && "not implemented"); +bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {    char *last = proc_self_maps_.data + proc_self_maps_.len;    if (current_ >= last) return false; -  uptr dummy; -  if (!start) start = &dummy; -  if (!end) end = &dummy; -  if (!offset) offset = &dummy; -  if (!protection) protection = &dummy;    char *next_line = (char*)internal_memchr(current_, '\n', last - current_);    if (next_line == 0)      next_line = last;    // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar -  *start = ParseHex(¤t_); +  segment->start = ParseHex(¤t_);    CHECK_EQ(*current_++, '-'); -  *end = ParseHex(¤t_); +  segment->end = ParseHex(¤t_);    CHECK_EQ(*current_++, ' ');    CHECK(IsOneOf(*current_, '-', 'r')); -  *protection = 0; -  if (*current_++ == 'r') -    *protection |= kProtectionRead; +  segment->protection = 0; +  if (*current_++ == 'r') segment->protection |= kProtectionRead;    CHECK(IsOneOf(*current_, '-', 'w')); -  if (*current_++ == 'w') -    *protection |= kProtectionWrite; +  if (*current_++ == 'w') segment->protection |= kProtectionWrite;    CHECK(IsOneOf(*current_, '-', 'x')); -  if (*current_++ == 'x') -    *protection |= kProtectionExecute; +  if (*current_++ == 'x') segment->protection |= kProtectionExecute;    CHECK(IsOneOf(*current_, 's', 'p')); -  if (*current_++ == 's') -    *protection |= kProtectionShared; +  if (*current_++ == 's') segment->protection |= kProtectionShared;    CHECK_EQ(*current_++, ' '); -  *offset = ParseHex(¤t_); +  segment->offset = ParseHex(¤t_);    CHECK_EQ(*current_++, ' ');    ParseHex(¤t_);    CHECK_EQ(*current_++, ':'); @@ -77,12 +64,11 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,    // Fill in the filename.    uptr i = 0;    while (current_ < next_line) { -    if (filename && i < filename_size - 1) -      filename[i++] = *current_; +    if (segment->filename && i < segment->filename_size - 1) +      segment->filename[i++] = *current_;      current_++;    } -  if (filename && i < filename_size) -    filename[i] = 0; +  if (segment->filename && i < segment->filename_size) segment->filename[i] = 0;    current_ = next_line + 1;    return true;  } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc index 131017458d4..037022ee314 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -96,40 +96,24 @@ void MemoryMappingLayout::LoadFromCache() {  // 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, -                                          ModuleArch *arch, u8 *uuid, -                                          uptr *protection) { +bool MemoryMappingLayout::NextSegmentLoad(MemoryMappedSegment *segment) {    const char *lc = current_load_cmd_addr_;    current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;    if (((const load_command *)lc)->cmd == kLCSegment) {      const SegmentCommand* sc = (const SegmentCommand *)lc; -    GetSegmentAddrRange(start, end, sc->vmaddr, sc->vmsize); -    if (protection) { -      // Return the initial protection. -      *protection = sc->initprot; -    } -    if (offset) { -      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) { -        *offset = sc->vmaddr; -      } else { -        *offset = sc->fileoff; -      } -    } -    if (filename) { -      if (current_image_ == kDyldImageIdx) { -        internal_strncpy(filename, kDyldPath, filename_size); -      } else { -        internal_strncpy(filename, _dyld_get_image_name(current_image_), -                         filename_size); -      } -    } -    if (arch) { -      *arch = current_arch_; -    } -    if (uuid) { -      internal_memcpy(uuid, current_uuid_, kModuleUUIDSize); +    GetSegmentAddrRange(segment, sc->vmaddr, sc->vmsize); +    // Return the initial protection. +    segment->protection = sc->initprot; +    segment->offset = +        (current_filetype_ == /*MH_EXECUTE*/ 0x2) ? sc->vmaddr : sc->fileoff; +    if (segment->filename) { +      const char *src = (current_image_ == kDyldImageIdx) +                            ? kDyldPath +                            : _dyld_get_image_name(current_image_); +      internal_strncpy(segment->filename, src, segment->filename_size);      } +    segment->arch = current_arch_; +    internal_memcpy(segment->uuid, current_uuid_, kModuleUUIDSize);      return true;    }    return false; @@ -215,8 +199,7 @@ static mach_header *get_dyld_image_header() {                                 (vm_region_info_t)&info, &count);      if (err != KERN_SUCCESS) return nullptr; -    if (size >= sizeof(mach_header) && -        info.protection & MemoryMappingLayout::kProtectionRead) { +    if (size >= sizeof(mach_header) && info.protection & kProtectionRead) {        mach_header *hdr = (mach_header *)address;        if ((hdr->magic == MH_MAGIC || hdr->magic == MH_MAGIC_64) &&            hdr->filetype == MH_DYLINKER) { @@ -233,7 +216,7 @@ const mach_header *get_dyld_hdr() {    return dyld_hdr;  } -void MemoryMappingLayout::GetSegmentAddrRange(uptr *start, uptr *end, +void MemoryMappingLayout::GetSegmentAddrRange(MemoryMappedSegment *segment,                                                uptr vmaddr, uptr vmsize) {    if (current_image_ == kDyldImageIdx) {      // vmaddr is masked with 0xfffff because on macOS versions < 10.12, @@ -242,18 +225,16 @@ void MemoryMappingLayout::GetSegmentAddrRange(uptr *start, uptr *end,      // 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. -    if (start) *start = (vmaddr & 0xfffff) + (uptr)get_dyld_hdr(); -    if (end) *end = (vmaddr & 0xfffff) + vmsize + (uptr)get_dyld_hdr(); +    segment->start = (vmaddr & 0xfffff) + (uptr)get_dyld_hdr(); +    segment->end = (vmaddr & 0xfffff) + vmsize + (uptr)get_dyld_hdr();    } else {      const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_); -    if (start) *start = vmaddr + dlloff; -    if (end) *end = vmaddr + vmsize + dlloff; +    segment->start = vmaddr + dlloff; +    segment->end = vmaddr + vmsize + dlloff;    }  } -bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, -                               char filename[], uptr filename_size, -                               uptr *protection, ModuleArch *arch, u8 *uuid) { +bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {    for (; current_image_ >= kDyldImageIdx; current_image_--) {      const mach_header *hdr = (current_image_ == kDyldImageIdx)                                   ? get_dyld_hdr() @@ -291,16 +272,13 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,  #ifdef MH_MAGIC_64          case MH_MAGIC_64: {            if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>( -                  start, end, offset, filename, filename_size, arch, uuid, -                  protection)) +                  segment))              return true;            break;          }  #endif          case MH_MAGIC: { -          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>( -                  start, end, offset, filename, filename_size, arch, uuid, -                  protection)) +          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(segment))              return true;            break;          } @@ -315,28 +293,22 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,  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, &cur_arch, &cur_uuid[0]); -       i++) { -    const char *cur_name = module_name.data(); -    if (cur_name[0] == '\0') -      continue; +  MemoryMappedSegment segment(module_name.data(), kMaxPathLength); +  for (uptr i = 0; Next(&segment); i++) { +    if (segment.filename[0] == '\0') continue;      LoadedModule *cur_module = nullptr;      if (!modules->empty() && -        0 == internal_strcmp(cur_name, modules->back().full_name())) { +        0 == internal_strcmp(segment.filename, modules->back().full_name())) {        cur_module = &modules->back();      } else {        modules->push_back(LoadedModule());        cur_module = &modules->back(); -      cur_module->set(cur_name, cur_beg, cur_arch, cur_uuid, -                      current_instrumented_); +      cur_module->set(segment.filename, segment.start, segment.arch, +                      segment.uuid, current_instrumented_);      } -    cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute, -                                prot & kProtectionWrite); +    cur_module->addAddressRange(segment.start, segment.end, +                                segment.IsExecutable(), segment.IsWritable());    }  } diff --git a/compiler-rt/lib/tsan/dd/dd_interceptors.cc b/compiler-rt/lib/tsan/dd/dd_interceptors.cc index 97c72dd2b7f..a39218f0454 100644 --- a/compiler-rt/lib/tsan/dd/dd_interceptors.cc +++ b/compiler-rt/lib/tsan/dd/dd_interceptors.cc @@ -270,20 +270,19 @@ namespace __dsan {  static void InitDataSeg() {    MemoryMappingLayout proc_maps(true); -  uptr start, end, offset;    char name[128]; +  MemoryMappedSegment segment(name, ARRAY_SIZE(name));    bool prev_is_data = false; -  while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), -                        /*protection*/ 0)) { -    bool is_data = offset != 0 && name[0] != 0; +  while (proc_maps.Next(&segment)) { +    bool is_data = segment.offset != 0 && segment.filename[0] != 0;      // BSS may get merged with [heap] in /proc/self/maps. This is not very      // reliable. -    bool is_bss = offset == 0 && -      (name[0] == 0 || internal_strcmp(name, "[heap]") == 0) && prev_is_data; -    if (g_data_start == 0 && is_data) -      g_data_start = start; -    if (is_bss) -      g_data_end = end; +    bool is_bss = segment.offset == 0 && +                  (segment.filename[0] == 0 || +                   internal_strcmp(segment.filename, "[heap]") == 0) && +                  prev_is_data; +    if (g_data_start == 0 && is_data) g_data_start = segment.start; +    if (is_bss) g_data_end = segment.end;      prev_is_data = is_data;    }    VPrintf(1, "guessed data_start=%p data_end=%p\n",  g_data_start, g_data_end); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index 7d9638c09a1..0ba01babe69 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -181,17 +181,15 @@ static void MapRodata() {    }    // Map the file into shadow of .rodata sections.    MemoryMappingLayout proc_maps(/*cache_enabled*/true); -  uptr start, end, offset, prot;    // Reusing the buffer 'name'. -  while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), &prot)) { -    if (name[0] != 0 && name[0] != '[' -        && (prot & MemoryMappingLayout::kProtectionRead) -        && (prot & MemoryMappingLayout::kProtectionExecute) -        && !(prot & MemoryMappingLayout::kProtectionWrite) -        && IsAppMem(start)) { +  MemoryMappedSegment segment(name, ARRAY_SIZE(name)); +  while (proc_maps.Next(&segment)) { +    if (segment.filename[0] != 0 && segment.filename[0] != '[' && +        segment.IsReadable() && segment.IsExecutable() && +        !segment.IsWritable() && IsAppMem(segment.start)) {        // Assume it's .rodata -      char *shadow_start = (char*)MemToShadow(start); -      char *shadow_end = (char*)MemToShadow(end); +      char *shadow_start = (char *)MemToShadow(segment.start); +      char *shadow_end = (char *)MemToShadow(segment.end);        for (char *p = shadow_start; p < shadow_end; p += marker.size()) {          internal_mmap(p, Min<uptr>(marker.size(), shadow_end - p),                        PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc index e89d955feac..e4f90a811c3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc @@ -118,18 +118,16 @@ static void ProtectRange(uptr beg, uptr end) {  void CheckAndProtect() {    // Ensure that the binary is indeed compiled with -pie.    MemoryMappingLayout proc_maps(true); -  uptr p, end, prot; -  while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { -    if (IsAppMem(p)) +  MemoryMappedSegment segment; +  while (proc_maps.Next(&segment)) { +    if (IsAppMem(segment.start)) continue; +    if (segment.start >= HeapMemEnd() && segment.start < HeapEnd()) continue; +    if (segment.protection == 0)  // Zero page or mprotected.        continue; -    if (p >= HeapMemEnd() && -        p < HeapEnd()) -      continue; -    if (prot == 0)  // Zero page or mprotected. -      continue; -    if (p >= VdsoBeg())  // vdso +    if (segment.start >= VdsoBeg())  // vdso        break; -    Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); +    Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", +           segment.start, segment.end);      Die();    } | 

