Home | History | Annotate | 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   CHECK(ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
     22                          &proc_maps->mmaped_size, &proc_maps->len));
     23 }
     24 
     25 static bool IsOneOf(char c, char c1, char c2) {
     26   return c == c1 || c == c2;
     27 }
     28 
     29 bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
     30                                char filename[], uptr filename_size,
     31                                uptr *protection) {
     32   char *last = proc_self_maps_.data + proc_self_maps_.len;
     33   if (current_ >= last) return false;
     34   uptr dummy;
     35   if (!start) start = &dummy;
     36   if (!end) end = &dummy;
     37   if (!offset) offset = &dummy;
     38   if (!protection) protection = &dummy;
     39   char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
     40   if (next_line == 0)
     41     next_line = last;
     42   // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
     43   *start = ParseHex(&current_);
     44   CHECK_EQ(*current_++, '-');
     45   *end = ParseHex(&current_);
     46   CHECK_EQ(*current_++, ' ');
     47   CHECK(IsOneOf(*current_, '-', 'r'));
     48   *protection = 0;
     49   if (*current_++ == 'r')
     50     *protection |= kProtectionRead;
     51   CHECK(IsOneOf(*current_, '-', 'w'));
     52   if (*current_++ == 'w')
     53     *protection |= kProtectionWrite;
     54   CHECK(IsOneOf(*current_, '-', 'x'));
     55   if (*current_++ == 'x')
     56     *protection |= kProtectionExecute;
     57   CHECK(IsOneOf(*current_, 's', 'p'));
     58   if (*current_++ == 's')
     59     *protection |= kProtectionShared;
     60   CHECK_EQ(*current_++, ' ');
     61   *offset = ParseHex(&current_);
     62   CHECK_EQ(*current_++, ' ');
     63   ParseHex(&current_);
     64   CHECK_EQ(*current_++, ':');
     65   ParseHex(&current_);
     66   CHECK_EQ(*current_++, ' ');
     67   while (IsDecimal(*current_))
     68     current_++;
     69   // Qemu may lack the trailing space.
     70   // https://github.com/google/sanitizers/issues/160
     71   // CHECK_EQ(*current_++, ' ');
     72   // Skip spaces.
     73   while (current_ < next_line && *current_ == ' ')
     74     current_++;
     75   // Fill in the filename.
     76   uptr i = 0;
     77   while (current_ < next_line) {
     78     if (filename && i < filename_size - 1)
     79       filename[i++] = *current_;
     80     current_++;
     81   }
     82   if (filename && i < filename_size)
     83     filename[i] = 0;
     84   current_ = next_line + 1;
     85   return true;
     86 }
     87 
     88 }  // namespace __sanitizer
     89 
     90 #endif  // SANITIZER_LINUX
     91