Index: base/debug/proc_maps_linux.cc |
diff --git a/base/debug/proc_maps_linux.cc b/base/debug/proc_maps_linux.cc |
index c9afd45037b7cce2787b5ccc5bdf4d9ed35e3679..2dea57b603d2ba686f92f545bf639dbeab6800a5 100644 |
--- a/base/debug/proc_maps_linux.cc |
+++ b/base/debug/proc_maps_linux.cc |
@@ -4,6 +4,8 @@ |
#include "base/debug/proc_maps_linux.h" |
+#include <fcntl.h> |
+ |
#if defined(OS_LINUX) |
#include <inttypes.h> |
#endif |
@@ -22,9 +24,63 @@ |
namespace base { |
namespace debug { |
+// Scans |proc_maps| starting from |pos| returning true if the gate VMA was |
+// found, otherwise returns false. |
+static bool ContainsGateVMA(std::string* proc_maps, size_t pos) { |
+#if defined(ARCH_CPU_ARM_FAMILY) |
+ // The gate VMA on ARM kernels is the interrupt vectors page. |
+ return proc_maps->find("[vectors]", pos) != std::string::npos; |
Mark Mentovai
2013/09/05 16:31:17
Wanna look for the trailing \n too? And one leadin
scherkus (not reviewing)
2013/09/05 17:24:34
Done.
|
+#elif defined(ARCH_CPU_X86_64) |
+ // The gate VMA on x86 64-bit kernels is the virtual system call page. |
+ return proc_maps->find("[vsyscall]", pos) != std::string::npos; |
+#else |
+ // Otherwise assume there is no gate VMA in which case we shouldn't |
+ // get duplicate entires. |
+ return false; |
+#endif |
+} |
+ |
bool ReadProcMaps(std::string* proc_maps) { |
- FilePath proc_maps_path("/proc/self/maps"); |
- return ReadFileToString(proc_maps_path, proc_maps); |
+ // seq_file only writes out a page-sized amount on each call. Refer to header |
+ // file for details. |
+ const long kBufferSize = sysconf(_SC_PAGESIZE); |
+ scoped_ptr<char[]> buffer(new char[kBufferSize]); |
+ |
+ int fd = HANDLE_EINTR(open("/proc/self/maps", O_RDONLY)); |
+ if (fd == -1) { |
+ DPLOG(ERROR) << "Couldn't open /proc/self/maps"; |
+ return false; |
+ } |
+ file_util::ScopedFD fd_closer(&fd); |
+ |
+ while (true) { |
+ ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer.get(), kBufferSize)); |
+ if (bytes_read < 0) { |
+ DPLOG(ERROR) << "Couldn't read /proc/self/maps"; |
+ return false; |
+ } |
+ |
+ if (bytes_read == 0) |
+ break; |
+ |
+ // Use 2-arg version of append() as |buffer| *is not* NUL-terminated. This |
+ // also avoids an unnecessary length computation. |
+ size_t pos = proc_maps->size(); |
Mark Mentovai
2013/09/05 16:31:17
You haven’t documented that proc_maps should start
scherkus (not reviewing)
2013/09/05 17:24:34
Done and test added.
|
+ proc_maps->append(buffer.get(), bytes_read); |
+ |
+ // The gate VMA is handled as a special case after seq_file has finished |
+ // iterating through all entries in the virtual memory table. |
+ // |
+ // Unfortunately, if additional entries are added at this point in time |
+ // seq_file gets confused and the next call to read() will return duplicate |
+ // entries including the gate VMA again. |
+ // |
+ // Avoid this by searching for the gate VMA and breaking early. |
+ if (ContainsGateVMA(proc_maps, pos)) |
+ break; |
+ } |
+ |
+ return true; |
} |
bool ParseProcMaps(const std::string& input, |