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