summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_procmaps.h
blob: 50753c4e607b1772a8ce5fba4f433039834a6099 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//===-- sanitizer_procmaps.h ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer.
//
// Information about the process mappings.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_PROCMAPS_H
#define SANITIZER_PROCMAPS_H

#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_mutex.h"

namespace __sanitizer {

#if SANITIZER_FREEBSD || SANITIZER_LINUX
struct ProcSelfMapsBuff {
  char *data;
  uptr mmaped_size;
  uptr len;
};

// Reads process memory map in an OS-specific way.
void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX

// Memory protection masks.
static const uptr kProtectionRead = 1;
static const uptr kProtectionWrite = 2;
static const uptr kProtectionExecute = 4;
static const uptr kProtectionShared = 8;

class MemoryMappedSegment {
 public:
  MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
      : filename(buff), filename_size(size) {}
  ~MemoryMappedSegment() {}

  bool IsReadable() { return protection & kProtectionRead; }
  bool IsWritable() { return protection & kProtectionWrite; }
  bool IsExecutable() { return protection & kProtectionExecute; }
  bool IsShared() { return protection & kProtectionShared; }

  uptr start;
  uptr end;
  uptr offset;
  char *filename;  // owned by caller
  uptr filename_size;
  uptr protection;
  ModuleArch arch;
  u8 uuid[kModuleUUIDSize];

#if SANITIZER_MAC
  char name[kMaxSegName];

 private:
  friend class MemoryMappingLayout;

  template <typename Section>
  void NextSectionLoad(LoadedModule *module);
  void AddAddressRanges(LoadedModule *module);

  uptr nsects_;
  char *current_load_cmd_addr_;
  u32 lc_type_;
  uptr base_virt_addr_;
#endif
};

class MemoryMappingLayout {
 public:
  explicit MemoryMappingLayout(bool cache_enabled);
  ~MemoryMappingLayout();
  bool Next(MemoryMappedSegment *segment);
  void Reset();
  // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
  // to obtain the memory mappings. It should fall back to pre-cached data
  // instead of aborting.
  static void CacheMemoryMappings();

  // Adds all mapped objects into a vector.
  void DumpListOfModules(InternalMmapVector<LoadedModule> *modules);

 private:
  void LoadFromCache();

  // FIXME: Hide implementation details for different platforms in
  // platform-specific files.
# if SANITIZER_FREEBSD || SANITIZER_LINUX
  ProcSelfMapsBuff proc_self_maps_;
  const char *current_;

  // Static mappings cache.
  static ProcSelfMapsBuff cached_proc_self_maps_;
  static StaticSpinMutex cache_lock_;  // protects cached_proc_self_maps_.
# elif SANITIZER_MAC
  template <u32 kLCSegment, typename SegmentCommand>
  bool NextSegmentLoad(MemoryMappedSegment *segment);
  int current_image_;
  u32 current_magic_;
  u32 current_filetype_;
  ModuleArch current_arch_;
  u8 current_uuid_[kModuleUUIDSize];
  int current_load_cmd_count_;
  char *current_load_cmd_addr_;
  bool current_instrumented_;
# endif
};

typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
                               /*out*/uptr *stats, uptr stats_size);

// Parse the contents of /proc/self/smaps and generate a memory profile.
// |cb| is a tool-specific callback that fills the |stats| array containing
// |stats_size| elements.
void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);

// Returns code range for the specified module.
bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end);

bool IsDecimal(char c);
uptr ParseDecimal(const char **p);
bool IsHex(char c);
uptr ParseHex(const char **p);

}  // namespace __sanitizer

#endif  // SANITIZER_PROCMAPS_H