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("/proc/self/maps", &proc_maps->data, 21 &proc_maps->mmaped_size, &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(data_.current, '\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(&data_.current); 42 CHECK_EQ(*data_.current++, '-'); 43 segment->end = ParseHex(&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(&data_.current); 56 CHECK_EQ(*data_.current++, ' '); 57 ParseHex(&data_.current); 58 CHECK_EQ(*data_.current++, ':'); 59 ParseHex(&data_.current); 60 CHECK_EQ(*data_.current++, ' '); 61 while (IsDecimal(*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((uptr)(next_line - data_.current), segment->filename_size - 1); 71 internal_strncpy(segment->filename, data_.current, 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