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