16895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//===-- sanitizer_procmaps.h ------------------------------------*- C++ -*-===//
26895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//
36895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//                     The LLVM Compiler Infrastructure
46895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//
56895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// This file is distributed under the University of Illinois Open Source
66895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// License. See LICENSE.TXT for details.
76895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//
86895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//===----------------------------------------------------------------------===//
96895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//
106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer.
116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//
126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Information about the process mappings.
136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov//===----------------------------------------------------------------------===//
146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifndef SANITIZER_PROCMAPS_H
156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#define SANITIZER_PROCMAPS_H
166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_internal_defs.h"
1893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovnamespace __sanitizer {
216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
2230e110edf92303237d471f1cb8e3ad07954fb145Evgeniy Stepanov#if SANITIZER_WINDOWS
23e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovclass MemoryMappingLayout {
24985aaaaf208f43e4b47625e21e9ebc434c5462e3Alexey Samsonov public:
25b443a65bd65d5c2c6090ed0537382b1ade1dbbb9Dmitry Vyukov  explicit MemoryMappingLayout(bool cache_enabled) {
2609a19b221bc60863bc10f1aad1d210ce9999990cAlexander Potapenko    (void)cache_enabled;
2709a19b221bc60863bc10f1aad1d210ce9999990cAlexander Potapenko  }
28f7fa68f5efbd32acd36987ab55305a3abc037636Alexey Samsonov  bool GetObjectNameAndOffset(uptr addr, uptr *offset,
294a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                              char filename[], uptr filename_size,
304a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                              uptr *protection) {
31f7fa68f5efbd32acd36987ab55305a3abc037636Alexey Samsonov    UNIMPLEMENTED();
32f7fa68f5efbd32acd36987ab55305a3abc037636Alexey Samsonov  }
33e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov};
34e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov
35e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov#else  // _WIN32
3624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX
37ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenkostruct ProcSelfMapsBuff {
38ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  char *data;
39ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  uptr mmaped_size;
40ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  uptr len;
41ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko};
4224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#endif  // SANITIZER_LINUX
43ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko
44e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovclass MemoryMappingLayout {
456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov public:
469ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko  explicit MemoryMappingLayout(bool cache_enabled);
476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  bool Next(uptr *start, uptr *end, uptr *offset,
4845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov            char filename[], uptr filename_size, uptr *protection);
496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  void Reset();
506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Gets the object file name and the offset in that object for a given
516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // address 'addr'. Returns true on success.
526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  bool GetObjectNameAndOffset(uptr addr, uptr *offset,
5345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                              char filename[], uptr filename_size,
5445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                              uptr *protection);
5593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
5693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // to obtain the memory mappings. It should fall back to pre-cached data
5793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // instead of aborting.
5893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  static void CacheMemoryMappings();
59e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  ~MemoryMappingLayout();
606985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany
6145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  // Memory protection masks.
6245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  static const uptr kProtectionRead = 1;
6345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  static const uptr kProtectionWrite = 2;
6445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  static const uptr kProtectionExecute = 4;
6545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  static const uptr kProtectionShared = 8;
6645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov
676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov private:
6893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  void LoadFromCache();
696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Default implementation of GetObjectNameAndOffset.
706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Quite slow, because it iterates through the whole process map for each
716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // lookup.
726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  bool IterateForObjectNameAndOffset(uptr addr, uptr *offset,
7345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                     char filename[], uptr filename_size,
7445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                     uptr *protection) {
756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    Reset();
766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    uptr start, end, file_offset;
7745717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
7845717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                         protection);
796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov         i++) {
806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      if (addr >= start && addr < end) {
81a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        // Don't subtract 'start' for the first entry:
82a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        // * If a binary is compiled w/o -pie, then the first entry in
83a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   process maps is likely the binary itself (all dynamic libs
84a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   are mapped higher in address space). For such a binary,
85a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   instruction offset in binary coincides with the actual
86a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   instruction address in virtual memory (as code section
87a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   is mapped to a fixed memory range).
88a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        // * If a binary is compiled with -pie, all the modules are
89a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   mapped high at address space (in particular, higher than
90a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   shadow memory of the tool), so the module can't be the
91a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov        //   first entry.
926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        *offset = (addr - (i ? start : 0)) + file_offset;
936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        return true;
946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      }
956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename_size)
976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      filename[0] = '\0';
986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    return false;
996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
1006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
10146f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov# if SANITIZER_LINUX
102ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  ProcSelfMapsBuff proc_self_maps_;
1036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *current_;
10493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
10593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // Static mappings cache.
106ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  static ProcSelfMapsBuff cached_proc_self_maps_;
107ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  static StaticSpinMutex cache_lock_;  // protects cached_proc_self_maps_.
10846f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov# elif SANITIZER_MAC
1096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  template<u32 kLCSegment, typename SegmentCommand>
1106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  bool NextSegmentLoad(uptr *start, uptr *end, uptr *offset,
1114a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                       char filename[], uptr filename_size,
1124a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                       uptr *protection);
1136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  int current_image_;
1146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  u32 current_magic_;
1158bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko  u32 current_filetype_;
1166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  int current_load_cmd_count_;
1176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *current_load_cmd_addr_;
118f7fa68f5efbd32acd36987ab55305a3abc037636Alexey Samsonov# endif
1196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov};
1206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
121e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov#endif  // _WIN32
122e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov
1236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}  // namespace __sanitizer
1246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif  // SANITIZER_PROCMAPS_H
126