Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_procmaps.h ------------------------------------*- C++ -*-===//
      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 // This file is shared between AddressSanitizer and ThreadSanitizer.
     11 //
     12 // Information about the process mappings.
     13 //===----------------------------------------------------------------------===//
     14 #ifndef SANITIZER_PROCMAPS_H
     15 #define SANITIZER_PROCMAPS_H
     16 
     17 #include "sanitizer_internal_defs.h"
     18 #include "sanitizer_mutex.h"
     19 
     20 namespace __sanitizer {
     21 
     22 #if SANITIZER_WINDOWS
     23 class MemoryMappingLayout {
     24  public:
     25   explicit MemoryMappingLayout(bool cache_enabled) {
     26     (void)cache_enabled;
     27   }
     28   bool GetObjectNameAndOffset(uptr addr, uptr *offset,
     29                               char filename[], uptr filename_size,
     30                               uptr *protection) {
     31     UNIMPLEMENTED();
     32   }
     33 };
     34 
     35 #else  // _WIN32
     36 #if SANITIZER_LINUX
     37 struct ProcSelfMapsBuff {
     38   char *data;
     39   uptr mmaped_size;
     40   uptr len;
     41 };
     42 #endif  // SANITIZER_LINUX
     43 
     44 class MemoryMappingLayout {
     45  public:
     46   explicit MemoryMappingLayout(bool cache_enabled);
     47   bool Next(uptr *start, uptr *end, uptr *offset,
     48             char filename[], uptr filename_size, uptr *protection);
     49   void Reset();
     50   // Gets the object file name and the offset in that object for a given
     51   // address 'addr'. Returns true on success.
     52   bool GetObjectNameAndOffset(uptr addr, uptr *offset,
     53                               char filename[], uptr filename_size,
     54                               uptr *protection);
     55   // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
     56   // to obtain the memory mappings. It should fall back to pre-cached data
     57   // instead of aborting.
     58   static void CacheMemoryMappings();
     59   ~MemoryMappingLayout();
     60 
     61   // Memory protection masks.
     62   static const uptr kProtectionRead = 1;
     63   static const uptr kProtectionWrite = 2;
     64   static const uptr kProtectionExecute = 4;
     65   static const uptr kProtectionShared = 8;
     66 
     67  private:
     68   void LoadFromCache();
     69   // Default implementation of GetObjectNameAndOffset.
     70   // Quite slow, because it iterates through the whole process map for each
     71   // lookup.
     72   bool IterateForObjectNameAndOffset(uptr addr, uptr *offset,
     73                                      char filename[], uptr filename_size,
     74                                      uptr *protection) {
     75     Reset();
     76     uptr start, end, file_offset;
     77     for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
     78                          protection);
     79          i++) {
     80       if (addr >= start && addr < end) {
     81         // Don't subtract 'start' for the first entry:
     82         // * If a binary is compiled w/o -pie, then the first entry in
     83         //   process maps is likely the binary itself (all dynamic libs
     84         //   are mapped higher in address space). For such a binary,
     85         //   instruction offset in binary coincides with the actual
     86         //   instruction address in virtual memory (as code section
     87         //   is mapped to a fixed memory range).
     88         // * If a binary is compiled with -pie, all the modules are
     89         //   mapped high at address space (in particular, higher than
     90         //   shadow memory of the tool), so the module can't be the
     91         //   first entry.
     92         *offset = (addr - (i ? start : 0)) + file_offset;
     93         return true;
     94       }
     95     }
     96     if (filename_size)
     97       filename[0] = '\0';
     98     return false;
     99   }
    100 
    101 # if SANITIZER_LINUX
    102   ProcSelfMapsBuff proc_self_maps_;
    103   char *current_;
    104 
    105   // Static mappings cache.
    106   static ProcSelfMapsBuff cached_proc_self_maps_;
    107   static StaticSpinMutex cache_lock_;  // protects cached_proc_self_maps_.
    108 # elif SANITIZER_MAC
    109   template<u32 kLCSegment, typename SegmentCommand>
    110   bool NextSegmentLoad(uptr *start, uptr *end, uptr *offset,
    111                        char filename[], uptr filename_size,
    112                        uptr *protection);
    113   int current_image_;
    114   u32 current_magic_;
    115   u32 current_filetype_;
    116   int current_load_cmd_count_;
    117   char *current_load_cmd_addr_;
    118 # endif
    119 };
    120 
    121 #endif  // _WIN32
    122 
    123 }  // namespace __sanitizer
    124 
    125 #endif  // SANITIZER_PROCMAPS_H
    126