diff --git a/compiler-rt/lib/scudo/standalone/common.h b/compiler-rt/lib/scudo/standalone/common.h --- a/compiler-rt/lib/scudo/standalone/common.h +++ b/compiler-rt/lib/scudo/standalone/common.h @@ -132,6 +132,10 @@ const char *getEnv(const char *Name); +u64 GetRSSFromBuffer(char *buf); + +u64 getRSS(); + u64 getMonotonicTime(); u32 getThreadID(); diff --git a/compiler-rt/lib/scudo/standalone/internal_defs.h b/compiler-rt/lib/scudo/standalone/internal_defs.h --- a/compiler-rt/lib/scudo/standalone/internal_defs.h +++ b/compiler-rt/lib/scudo/standalone/internal_defs.h @@ -88,6 +88,11 @@ typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; +typedef int fd_t; + +enum FileAccessMode { RdOnly, WrOnly, RdWr }; + +#define kInvalidFd ((fd_t)-1) // The following two functions have platform specific implementations. void outputRaw(const char *Buffer); diff --git a/compiler-rt/lib/scudo/standalone/linux.cpp b/compiler-rt/lib/scudo/standalone/linux.cpp --- a/compiler-rt/lib/scudo/standalone/linux.cpp +++ b/compiler-rt/lib/scudo/standalone/linux.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ #endif // defined(SYS_getrandom) // Up to 256 bytes, a read off /dev/urandom will not be interrupted. // Blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom. - const int FileDesc = open("/dev/urandom", O_RDONLY); + const int FileDesc = open("/dev/urandom", RdOnly); if (FileDesc == -1) return false; ReadBytes = read(FileDesc, Buffer, Length); @@ -180,6 +181,44 @@ extern "C" WEAK int async_safe_write_log(int pri, const char *tag, const char *msg); +s64 internal_read(fd_t fd, char *buf, size_t size) { + return read(fd, buf, size); +} + +void internal_close(fd_t fd) { close(fd); } + +fd_t OpenFile(const char *FileName, int flags) { return open(FileName, flags); } + +u64 GetRSSFromBuffer(char *buf) { + // The format of the file is: + // 1084 89 69 11 0 79 0 + // We need the second number which is RSS in pages. + char *pos = buf; + // Skip the first number. + while (*pos >= '0' && *pos <= '9') + pos++; + // Skip whitespaces. + while (!(*pos >= '0' && *pos <= '9') && *pos != 0) + pos++; + // Read the number. + u64 rss = 0; + while (*pos >= '0' && *pos <= '9') + rss = rss * 10 + (u64)(*pos)++ - '0'; + return rss * getPageSizeCached(); +} + +u64 GetRSS() { + fd_t fd = OpenFile("/proc/self/statm", RdOnly); + char buf[64]; + s64 len = internal_read(fd, buf, sizeof(buf) - 1); + internal_close(fd); + if (len <= 0) + return 0; + buf[len] = 0; + + return GetRSSFromBuffer(buf); +} + void outputRaw(const char *Buffer) { if (&async_safe_write_log) { constexpr s32 AndroidLogInfo = 4; diff --git a/compiler-rt/lib/scudo/standalone/tests/common_test.cpp b/compiler-rt/lib/scudo/standalone/tests/common_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/common_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/common_test.cpp @@ -69,4 +69,11 @@ unmap(P, Size, 0, &Data); } +TEST(ScudoCommonTest, GetRssFromBuffer) { + std::string buf = "1084 89 69 11 0 79 0"; + auto result = scudo::GetRSSFromBuffer(buf.data()); + + EXPECT_EQ(result, 89 * scudo::getPageSizeCached()); +} + } // namespace scudo