summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2013-09-03 11:09:16 +0000
committerAlexander Potapenko <glider@google.com>2013-09-03 11:09:16 +0000
commit7e1c51988dda76be4aae68f751e472315a403fb3 (patch)
tree4f1b754e84c75fcb6d57af0fe2be883b0b9313ee /compiler-rt
parente2391f66f9b049e9cb88278dec8b640c68f164c1 (diff)
downloadbcm5719-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.cc48
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h12
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc77
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,
OpenPOWER on IntegriCloud