From 06d3aa4884a76cd71de7259d9a704349438cabec Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Wed, 13 Mar 2013 06:51:02 +0000 Subject: [PATCH] [Sanitizer] Change MemoryMappingLayout methods to also report memory protection flags (for future use in leak checker). Patch by Sergey Matveev. llvm-svn: 176931 --- compiler-rt/lib/msan/msan.cc | 2 +- .../lib/sanitizer_common/sanitizer_linux.cc | 31 ++++++++++++++++------ compiler-rt/lib/sanitizer_common/sanitizer_mac.cc | 10 ++++--- .../lib/sanitizer_common/sanitizer_posix.cc | 5 ++-- .../lib/sanitizer_common/sanitizer_procmaps.h | 17 +++++++++--- .../lib/sanitizer_common/sanitizer_stacktrace.cc | 3 ++- compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc | 6 +++-- 7 files changed, 53 insertions(+), 21 deletions(-) diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index 96f99d4..0071b95 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -74,7 +74,7 @@ static bool IsRunningUnderDr() { const sptr kBufSize = 4095; char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__); while (proc_maps.Next(/* start */0, /* end */0, /* file_offset */0, - filename, kBufSize)) { + filename, kBufSize, /* protection */0)) { if (internal_strstr(filename, "libdynamorio") != 0) { result = true; break; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 9b51d2c..3f32ecc 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -184,7 +184,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, MemoryMappingLayout proc_maps; uptr start, end, offset; uptr prev_end = 0; - while (proc_maps.Next(&start, &end, &offset, 0, 0)) { + while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) { if ((uptr)&rl < end) break; prev_end = end; @@ -390,7 +390,8 @@ static bool IsDecimal(char c) { } bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, - char filename[], uptr filename_size) { + char filename[], uptr filename_size, + uptr *protection) { char *last = proc_self_maps_.data + proc_self_maps_.len; if (current_ >= last) return false; uptr dummy; @@ -405,10 +406,22 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, CHECK_EQ(*current_++, '-'); *end = ParseHex(¤t_); CHECK_EQ(*current_++, ' '); - CHECK(IsOnOf(*current_++, '-', 'r')); - CHECK(IsOnOf(*current_++, '-', 'w')); - CHECK(IsOnOf(*current_++, '-', 'x')); - CHECK(IsOnOf(*current_++, 's', 'p')); + uptr local_protection = 0; + CHECK(IsOnOf(*current_, '-', 'r')); + if (*current_++ == 'r') + local_protection |= kProtectionRead; + CHECK(IsOnOf(*current_, '-', 'w')); + if (*current_++ == 'w') + local_protection |= kProtectionWrite; + CHECK(IsOnOf(*current_, '-', 'x')); + if (*current_++ == 'x') + local_protection |= kProtectionExecute; + CHECK(IsOnOf(*current_, 's', 'p')); + if (*current_++ == 's') + local_protection |= kProtectionShared; + if (protection) { + *protection = local_protection; + } CHECK_EQ(*current_++, ' '); *offset = ParseHex(¤t_); CHECK_EQ(*current_++, ' '); @@ -438,8 +451,10 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, // Gets the object name and the offset by walking MemoryMappingLayout. bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, char filename[], - uptr filename_size) { - return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); + uptr filename_size, + uptr *protection) { + return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, + protection); } bool SanitizerSetThreadName(const char *name) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 0f11220..eb2a6b6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -216,7 +216,9 @@ void MemoryMappingLayout::LoadFromCache() { template bool MemoryMappingLayout::NextSegmentLoad( uptr *start, uptr *end, uptr *offset, - char filename[], uptr filename_size) { + char filename[], uptr filename_size, uptr *protection) { + if (protection) + UNIMPLEMENTED(); const char* lc = current_load_cmd_addr_; current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize; if (((const load_command *)lc)->cmd == kLCSegment) { @@ -294,8 +296,10 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, char filename[], - uptr filename_size) { - return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); + uptr filename_size + uptr *protection) { + return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, + protection); } BlockingMutex::BlockingMutex(LinkerInitialized) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index 773f376..27f0977 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -152,7 +152,8 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { MemoryMappingLayout procmaps; uptr start, end; while (procmaps.Next(&start, &end, - /*offset*/0, /*filename*/0, /*filename_size*/0)) { + /*offset*/0, /*filename*/0, /*filename_size*/0, + /*protection*/0)) { if (!IntervalsAreSeparate(start, end, range_start, range_end)) return false; } @@ -166,7 +167,7 @@ void DumpProcessMap() { char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__); Report("Process memory map follows:\n"); while (proc_maps.Next(&start, &end, /* file_offset */0, - filename, kBufSize)) { + filename, kBufSize, /* protection */0)) { Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); } Report("End of process memory map.\n"); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h index 1b8ea7a..1b61515 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h @@ -42,28 +42,37 @@ class MemoryMappingLayout { public: MemoryMappingLayout(); bool Next(uptr *start, uptr *end, uptr *offset, - char filename[], uptr filename_size); + char filename[], uptr filename_size, uptr *protection); void Reset(); // Gets the object file name and the offset in that object for a given // address 'addr'. Returns true on success. bool GetObjectNameAndOffset(uptr addr, uptr *offset, - char filename[], uptr filename_size); + char filename[], uptr filename_size, + uptr *protection); // 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 // instead of aborting. static void CacheMemoryMappings(); ~MemoryMappingLayout(); + // 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(); // Default implementation of GetObjectNameAndOffset. // Quite slow, because it iterates through the whole process map for each // lookup. bool IterateForObjectNameAndOffset(uptr addr, uptr *offset, - char filename[], uptr filename_size) { + char filename[], uptr filename_size, + uptr *protection) { Reset(); uptr start, end, file_offset; - for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size); + for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size, + protection); i++) { if (addr >= start && addr < end) { // Don't subtract 'start' for the first entry: diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index 6309b23..1b3a1f5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -113,7 +113,8 @@ void StackTrace::PrintStack(const uptr *addr, uptr size, PrintStackFramePrefix(frame_num, pc); uptr offset; if (proc_maps.GetObjectNameAndOffset(pc, &offset, - buff.data(), buff.size())) { + buff.data(), buff.size(), + /* protection */0)) { PrintModuleAndOffset(buff.data(), offset, strip_file_prefix); } Printf("\n"); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index f756cbc..524f03e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -129,7 +129,8 @@ static void CheckPIE() { MemoryMappingLayout proc_maps; uptr start, end; if (proc_maps.Next(&start, &end, - /*offset*/0, /*filename*/0, /*filename_size*/0)) { + /*offset*/0, /*filename*/0, /*filename_size*/0, + /*protection*/0)) { if ((u64)start < kLinuxAppMemBeg) { Printf("FATAL: ThreadSanitizer can not mmap the shadow memory (" "something is mapped at 0x%zx < 0x%zx)\n", @@ -146,7 +147,8 @@ static void InitDataSeg() { uptr start, end, offset; char name[128]; bool prev_is_data = false; - while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name))) { + while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), + /*protection*/ 0)) { DPrintf("%p-%p %p %s\n", start, end, offset, name); bool is_data = offset != 0 && name[0] != 0; // BSS may get merged with [heap] in /proc/self/maps. This is not very -- 2.7.4