summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/sanitizer_common
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/sanitizer_common')
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cc48
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h12
2 files changed, 58 insertions, 2 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
OpenPOWER on IntegriCloud