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