diff options
author | Alexander Potapenko <glider@google.com> | 2013-09-03 11:09:16 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2013-09-03 11:09:16 +0000 |
commit | 7e1c51988dda76be4aae68f751e472315a403fb3 (patch) | |
tree | 4f1b754e84c75fcb6d57af0fe2be883b0b9313ee /compiler-rt | |
parent | e2391f66f9b049e9cb88278dec8b640c68f164c1 (diff) | |
download | bcm5719-llvm-7e1c51988dda76be4aae68f751e472315a403fb3.tar.gz bcm5719-llvm-7e1c51988dda76be4aae68f751e472315a403fb3.zip |
[TSan] Move the /proc/self/maps parsing logic to sanitizer_common
Provide a generic way for the tools to generate memory profiles from contents of /proc/self/maps
llvm-svn: 189789
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_linux.cc | 48 | ||||
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h | 12 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc | 77 |
3 files changed, 78 insertions, 59 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 7e786c27b45..22553363b5f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -403,6 +403,30 @@ static bool IsDecimal(char c) { return c >= '0' && c <= '9'; } +static bool IsHex(char c) { + return (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f'); +} + +static uptr ReadHex(const char *p) { + uptr v = 0; + for (; IsHex(p[0]); p++) { + if (p[0] >= '0' && p[0] <= '9') + v = v * 16 + p[0] - '0'; + else + v = v * 16 + p[0] - 'a' + 10; + } + return v; +} + +static uptr ReadDecimal(const char *p) { + uptr v = 0; + for (; IsDecimal(p[0]); p++) + v = v * 10 + p[0] - '0'; + return v; +} + + bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, char filename[], uptr filename_size, uptr *protection) { @@ -473,6 +497,30 @@ bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, protection); } +void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { + char *smaps = 0; + uptr smaps_cap = 0; + uptr smaps_len = ReadFileToBuffer("/proc/self/smaps", + &smaps, &smaps_cap, 64<<20); + uptr total = 0; + uptr start = 0; + bool file = false; + const char *pos = smaps; + while (pos < smaps + smaps_len) { + if (IsHex(pos[0])) { + start = ReadHex(pos); + for (; *pos != '/' && *pos > '\n'; pos++) {} + file = *pos == '/'; + } else if (internal_strncmp(pos, "Rss:", 4) == 0) { + for (; *pos < '0' || *pos > '9'; pos++) {} + uptr rss = ReadDecimal(pos) * 1024; + cb(start, rss, file, stats, stats_size); + } + while (*pos++ != '\n') {} + } + UnmapOrDie(smaps, smaps_cap); +} + enum MutexState { MtxUnlocked = 0, MtxLocked = 1, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h index b96f09ec456..ed281997f1a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h @@ -32,7 +32,7 @@ class MemoryMappingLayout { } }; -#else // _WIN32 +#else // SANITIZER_WINDOWS #if SANITIZER_LINUX struct ProcSelfMapsBuff { char *data; @@ -118,7 +118,15 @@ class MemoryMappingLayout { # endif }; -#endif // _WIN32 +typedef void (*fill_profile_f)(uptr start, uptr rss, bool file, + /*out*/uptr *stats, uptr stats_size); + +// Parse the contents of /proc/self/smaps and generate a memory profile. +// |cb| is a tool-specific callback that fills the |stats| array containing +// |stats_size| elements. +void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size); + +#endif // SANITIZER_WINDOWS } // namespace __sanitizer diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index a0d71e8589d..8e2a081228b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -72,70 +72,33 @@ ScopedInRtl::~ScopedInRtl() { } #endif -static bool ishex(char c) { - return (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f'); -} - -static uptr readhex(const char *p) { - uptr v = 0; - for (; ishex(p[0]); p++) { - if (p[0] >= '0' && p[0] <= '9') - v = v * 16 + p[0] - '0'; - else - v = v * 16 + p[0] - 'a' + 10; - } - return v; -} - -static uptr readdec(const char *p) { - uptr v = 0; - for (; p[0] >= '0' && p[0] <= '9' ; p++) - v = v * 10 + p[0] - '0'; - return v; +void FillProfileCallback(uptr start, uptr rss, bool file, + uptr *mem, uptr stats_size) { + CHECK_EQ(7, stats_size); + mem[6] += rss; // total + start >>= 40; + if (start < 0x10) // shadow + mem[0] += rss; + else if (start >= 0x20 && start < 0x30) // compat modules + mem[file ? 1 : 2] += rss; + else if (start >= 0x7e) // modules + mem[file ? 1 : 2] += rss; + else if (start >= 0x60 && start < 0x62) // traces + mem[3] += rss; + else if (start >= 0x7d && start < 0x7e) // heap + mem[4] += rss; + else // other + mem[5] += rss; } void WriteMemoryProfile(char *buf, uptr buf_size) { - char *smaps = 0; - uptr smaps_cap = 0; - uptr smaps_len = ReadFileToBuffer("/proc/self/smaps", - &smaps, &smaps_cap, 64<<20); - uptr mem[6] = {}; - uptr total = 0; - uptr start = 0; - bool file = false; - const char *pos = smaps; - while (pos < smaps + smaps_len) { - if (ishex(pos[0])) { - start = readhex(pos); - for (; *pos != '/' && *pos > '\n'; pos++) {} - file = *pos == '/'; - } else if (internal_strncmp(pos, "Rss:", 4) == 0) { - for (; *pos < '0' || *pos > '9'; pos++) {} - uptr rss = readdec(pos) * 1024; - total += rss; - start >>= 40; - if (start < 0x10) // shadow - mem[0] += rss; - else if (start >= 0x20 && start < 0x30) // compat modules - mem[file ? 1 : 2] += rss; - else if (start >= 0x7e) // modules - mem[file ? 1 : 2] += rss; - else if (start >= 0x60 && start < 0x62) // traces - mem[3] += rss; - else if (start >= 0x7d && start < 0x7e) // heap - mem[4] += rss; - else // other - mem[5] += rss; - } - while (*pos++ != '\n') {} - } - UnmapOrDie(smaps, smaps_cap); + uptr mem[7] = {}; + __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7); char *buf_pos = buf; char *buf_end = buf + buf_size; buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos, "RSS %zd MB: shadow:%zd file:%zd mmap:%zd trace:%zd heap:%zd other:%zd\n", - total >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20, + mem[6] >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20, mem[3] >> 20, mem[4] >> 20, mem[5] >> 20); struct mallinfo mi = __libc_mallinfo(); buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos, |