OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/proc_maps_linux.h" | 5 #include "base/debug/proc_maps_linux.h" |
6 | 6 |
7 #include <fcntl.h> | |
8 | |
7 #if defined(OS_LINUX) | 9 #if defined(OS_LINUX) |
8 #include <inttypes.h> | 10 #include <inttypes.h> |
9 #endif | 11 #endif |
10 | 12 |
11 #include "base/file_util.h" | 13 #include "base/file_util.h" |
12 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
13 | 15 |
14 #if defined(OS_ANDROID) | 16 #if defined(OS_ANDROID) |
15 // Bionic's inttypes.h defines PRI/SCNxPTR as an unsigned long int, which | 17 // Bionic's inttypes.h defines PRI/SCNxPTR as an unsigned long int, which |
16 // is incompatible with Bionic's stdint.h defining uintptr_t as a unsigned int: | 18 // is incompatible with Bionic's stdint.h defining uintptr_t as a unsigned int: |
17 // https://code.google.com/p/android/issues/detail?id=57218 | 19 // https://code.google.com/p/android/issues/detail?id=57218 |
18 #undef SCNxPTR | 20 #undef SCNxPTR |
19 #define SCNxPTR "x" | 21 #define SCNxPTR "x" |
20 #endif | 22 #endif |
21 | 23 |
22 namespace base { | 24 namespace base { |
23 namespace debug { | 25 namespace debug { |
24 | 26 |
27 // Local testing revealed that the size of /proc/<pid>/maps for an official | |
28 // release build of chrome hovered around the ~45 KB mark with some processes | |
29 // hitting 80-90 KB. | |
30 // | |
31 // We'll play it safe and use 1 MB. | |
32 enum { kMaxProcMapsSize = 1024 * 1024 }; | |
33 | |
25 bool ReadProcMaps(std::string* proc_maps) { | 34 bool ReadProcMaps(std::string* proc_maps) { |
26 FilePath proc_maps_path("/proc/self/maps"); | 35 scoped_ptr<char[]> buffer(new char[kMaxProcMapsSize]); |
27 return file_util::ReadFileToString(proc_maps_path, proc_maps); | 36 |
37 int fd = HANDLE_EINTR(open("/proc/self/maps", O_RDONLY)); | |
38 if (fd == -1) { | |
39 DPLOG(ERROR) << "Couldn't open /proc/self/maps"; | |
40 return false; | |
41 } | |
42 file_util::ScopedFD fd_closer(&fd); | |
43 | |
44 // XXX there's file_util::ReadFromFD() but it expects an exact # of bytes | |
45 // to be read whereas here we're reading until EOF. Perhaps we can change | |
46 // the API / add a new one / add an optional param? | |
47 ssize_t offset = 0; | |
48 while (true) { | |
49 ssize_t bytes_read = HANDLE_EINTR( | |
50 read(fd, buffer.get() + offset, kMaxProcMapsSize - offset)); | |
Alexander Potapenko
2013/07/11 10:47:23
There must be only one read() call, otherwise we'r
| |
51 if (bytes_read < 0) { | |
52 DPLOG(ERROR) << "Couldn't read /proc/self/maps"; | |
53 return false; | |
54 } | |
55 | |
56 offset += bytes_read; | |
57 if (offset == kMaxProcMapsSize) { | |
58 DLOG(ERROR) << "/proc/self/maps is too large"; | |
59 return false; | |
60 } | |
61 | |
62 if (bytes_read == 0) | |
63 break; | |
64 } | |
65 | |
66 // Use 2-arg version of assign() to avoid an unnecessary length computation | |
67 // of |buffer|. | |
68 buffer[offset] = '\0'; | |
69 proc_maps->assign(buffer.get(), offset); | |
70 return true; | |
28 } | 71 } |
29 | 72 |
30 bool ParseProcMaps(const std::string& input, | 73 bool ParseProcMaps(const std::string& input, |
31 std::vector<MappedMemoryRegion>* regions_out) { | 74 std::vector<MappedMemoryRegion>* regions_out) { |
32 std::vector<MappedMemoryRegion> regions; | 75 std::vector<MappedMemoryRegion> regions; |
33 | 76 |
34 // This isn't async safe nor terribly efficient, but it doesn't need to be at | 77 // This isn't async safe nor terribly efficient, but it doesn't need to be at |
35 // this point in time. | 78 // this point in time. |
36 std::vector<std::string> lines; | 79 std::vector<std::string> lines; |
37 SplitString(input, '\n', &lines); | 80 SplitString(input, '\n', &lines); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 regions.push_back(region); | 135 regions.push_back(region); |
93 regions.back().path.assign(line + path_index); | 136 regions.back().path.assign(line + path_index); |
94 } | 137 } |
95 | 138 |
96 regions_out->swap(regions); | 139 regions_out->swap(regions); |
97 return true; | 140 return true; |
98 } | 141 } |
99 | 142 |
100 } // namespace debug | 143 } // namespace debug |
101 } // namespace base | 144 } // namespace base |
OLD | NEW |