1353944Sdim//===-- sanitizer_procmaps_linux.cpp --------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// Information about the process mappings (Linux-specific parts). 10353944Sdim//===----------------------------------------------------------------------===// 11353944Sdim 12353944Sdim#include "sanitizer_platform.h" 13353944Sdim#if SANITIZER_LINUX 14353944Sdim#include "sanitizer_common.h" 15353944Sdim#include "sanitizer_procmaps.h" 16353944Sdim 17353944Sdimnamespace __sanitizer { 18353944Sdim 19353944Sdimvoid ReadProcMaps(ProcSelfMapsBuff *proc_maps) { 20353944Sdim if (!ReadFileToBuffer("/proc/self/maps", &proc_maps->data, 21353944Sdim &proc_maps->mmaped_size, &proc_maps->len)) { 22353944Sdim proc_maps->data = nullptr; 23353944Sdim proc_maps->mmaped_size = 0; 24353944Sdim proc_maps->len = 0; 25353944Sdim } 26353944Sdim} 27353944Sdim 28353944Sdimstatic bool IsOneOf(char c, char c1, char c2) { 29353944Sdim return c == c1 || c == c2; 30353944Sdim} 31353944Sdim 32353944Sdimbool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { 33353944Sdim if (Error()) return false; // simulate empty maps 34353944Sdim char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; 35353944Sdim if (data_.current >= last) return false; 36353944Sdim char *next_line = 37353944Sdim (char *)internal_memchr(data_.current, '\n', last - data_.current); 38353944Sdim if (next_line == 0) 39353944Sdim next_line = last; 40353944Sdim // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar 41353944Sdim segment->start = ParseHex(&data_.current); 42353944Sdim CHECK_EQ(*data_.current++, '-'); 43353944Sdim segment->end = ParseHex(&data_.current); 44353944Sdim CHECK_EQ(*data_.current++, ' '); 45353944Sdim CHECK(IsOneOf(*data_.current, '-', 'r')); 46353944Sdim segment->protection = 0; 47353944Sdim if (*data_.current++ == 'r') segment->protection |= kProtectionRead; 48353944Sdim CHECK(IsOneOf(*data_.current, '-', 'w')); 49353944Sdim if (*data_.current++ == 'w') segment->protection |= kProtectionWrite; 50353944Sdim CHECK(IsOneOf(*data_.current, '-', 'x')); 51353944Sdim if (*data_.current++ == 'x') segment->protection |= kProtectionExecute; 52353944Sdim CHECK(IsOneOf(*data_.current, 's', 'p')); 53353944Sdim if (*data_.current++ == 's') segment->protection |= kProtectionShared; 54353944Sdim CHECK_EQ(*data_.current++, ' '); 55353944Sdim segment->offset = ParseHex(&data_.current); 56353944Sdim CHECK_EQ(*data_.current++, ' '); 57353944Sdim ParseHex(&data_.current); 58353944Sdim CHECK_EQ(*data_.current++, ':'); 59353944Sdim ParseHex(&data_.current); 60353944Sdim CHECK_EQ(*data_.current++, ' '); 61353944Sdim while (IsDecimal(*data_.current)) data_.current++; 62353944Sdim // Qemu may lack the trailing space. 63353944Sdim // https://github.com/google/sanitizers/issues/160 64353944Sdim // CHECK_EQ(*data_.current++, ' '); 65353944Sdim // Skip spaces. 66353944Sdim while (data_.current < next_line && *data_.current == ' ') data_.current++; 67353944Sdim // Fill in the filename. 68353944Sdim if (segment->filename) { 69353944Sdim uptr len = 70353944Sdim Min((uptr)(next_line - data_.current), segment->filename_size - 1); 71353944Sdim internal_strncpy(segment->filename, data_.current, len); 72353944Sdim segment->filename[len] = 0; 73353944Sdim } 74353944Sdim 75353944Sdim data_.current = next_line + 1; 76353944Sdim return true; 77353944Sdim} 78353944Sdim 79353944Sdim} // namespace __sanitizer 80353944Sdim 81353944Sdim#endif // SANITIZER_LINUX 82