1 | //===-- sanitizer_procmaps_linux.cpp --------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Information about the process mappings (Linux-specific parts). |
10 | //===----------------------------------------------------------------------===// |
11 | |
12 | #include "sanitizer_platform.h" |
13 | #if SANITIZER_LINUX |
14 | #include "sanitizer_common.h" |
15 | #include "sanitizer_procmaps.h" |
16 | |
17 | namespace __sanitizer { |
18 | |
19 | void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { |
20 | if (!ReadFileToBuffer(file_name: "/proc/self/maps" , buff: &proc_maps->data, |
21 | buff_size: &proc_maps->mmaped_size, read_len: &proc_maps->len)) { |
22 | proc_maps->data = nullptr; |
23 | proc_maps->mmaped_size = 0; |
24 | proc_maps->len = 0; |
25 | } |
26 | } |
27 | |
28 | static bool IsOneOf(char c, char c1, char c2) { |
29 | return c == c1 || c == c2; |
30 | } |
31 | |
32 | bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { |
33 | if (Error()) return false; // simulate empty maps |
34 | char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; |
35 | if (data_.current >= last) return false; |
36 | char *next_line = |
37 | (char *)internal_memchr(s: data_.current, c: '\n', n: last - data_.current); |
38 | if (next_line == 0) |
39 | next_line = last; |
40 | // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar |
41 | segment->start = ParseHex(p: &data_.current); |
42 | CHECK_EQ(*data_.current++, '-'); |
43 | segment->end = ParseHex(p: &data_.current); |
44 | CHECK_EQ(*data_.current++, ' '); |
45 | CHECK(IsOneOf(*data_.current, '-', 'r')); |
46 | segment->protection = 0; |
47 | if (*data_.current++ == 'r') segment->protection |= kProtectionRead; |
48 | CHECK(IsOneOf(*data_.current, '-', 'w')); |
49 | if (*data_.current++ == 'w') segment->protection |= kProtectionWrite; |
50 | CHECK(IsOneOf(*data_.current, '-', 'x')); |
51 | if (*data_.current++ == 'x') segment->protection |= kProtectionExecute; |
52 | CHECK(IsOneOf(*data_.current, 's', 'p')); |
53 | if (*data_.current++ == 's') segment->protection |= kProtectionShared; |
54 | CHECK_EQ(*data_.current++, ' '); |
55 | segment->offset = ParseHex(p: &data_.current); |
56 | CHECK_EQ(*data_.current++, ' '); |
57 | ParseHex(p: &data_.current); |
58 | CHECK_EQ(*data_.current++, ':'); |
59 | ParseHex(p: &data_.current); |
60 | CHECK_EQ(*data_.current++, ' '); |
61 | while (IsDecimal(c: *data_.current)) data_.current++; |
62 | // Qemu may lack the trailing space. |
63 | // https://github.com/google/sanitizers/issues/160 |
64 | // CHECK_EQ(*data_.current++, ' '); |
65 | // Skip spaces. |
66 | while (data_.current < next_line && *data_.current == ' ') data_.current++; |
67 | // Fill in the filename. |
68 | if (segment->filename) { |
69 | uptr len = |
70 | Min(a: (uptr)(next_line - data_.current), b: segment->filename_size - 1); |
71 | internal_strncpy(dst: segment->filename, src: data_.current, n: len); |
72 | segment->filename[len] = 0; |
73 | } |
74 | |
75 | data_.current = next_line + 1; |
76 | return true; |
77 | } |
78 | |
79 | } // namespace __sanitizer |
80 | |
81 | #endif // SANITIZER_LINUX |
82 | |