summaryrefslogtreecommitdiffstats
path: root/xpcom/base/MemoryMapping.h
blob: 51bbb0ab66868068b4bd11119b76f39cda0c1ef5 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_MemoryMapping_h
#define mozilla_MemoryMapping_h

#include <cstdint>
#include "mozilla/EnumSet.h"
#include "nsString.h"
#include "nsTArrayForwardDeclare.h"

/**
 * MemoryMapping is a helper class which describes an entry in the Linux
 * /proc/<pid>/smaps file. See procfs(5) for details on the entry format.
 *
 * The GetMemoryMappings() function returns an array of such entries, sorted by
 * start address, one for each entry in the current process's address space.
 */

namespace mozilla {

enum class VMFlag : uint8_t {
  Readable,       // rd  - readable
  Writable,       // wr  - writable
  Executable,     // ex  - executable
  Shared,         // sh  - shared
  MayRead,        // mr  - may read
  MayWrite,       // mw  - may write
  MayExecute,     // me  - may execute
  MayShare,       // ms  - may share
  GrowsDown,      // gd  - stack segment grows down
  PurePFN,        // pf  - pure PFN range
  DisabledWrite,  // dw  - disabled write to the mapped file
  Locked,         // lo  - pages are locked in memory
  IO,             // io  - memory mapped I/O area
  Sequential,     // sr  - sequential read advise provided
  Random,         // rr  - random read advise provided
  NoFork,         // dc  - do not copy area on fork
  NoExpand,       // de  - do not expand area on remapping
  Accountable,    // ac  - area is accountable
  NotReserved,    // nr  - swap space is not reserved for the area
  HugeTLB,        // ht  - area uses huge tlb pages
  NonLinear,      // nl  - non-linear mapping
  ArchSpecific,   // ar  - architecture specific flag
  NoCore,         // dd  - do not include area into core dump
  SoftDirty,      // sd  - soft-dirty flag
  MixedMap,       // mm  - mixed map area
  HugePage,       // hg  - huge page advise flag
  NoHugePage,     // nh  - no-huge page advise flag
  Mergeable,      // mg  - mergeable advise flag
};

using VMFlagSet = EnumSet<VMFlag, uint32_t>;

class MemoryMapping final {
 public:
  enum class Perm : uint8_t {
    Read,
    Write,
    Execute,
    Shared,
    Private,
  };

  using PermSet = EnumSet<Perm>;

  MemoryMapping(uintptr_t aStart, uintptr_t aEnd, PermSet aPerms,
                size_t aOffset, const char* aName)
      : mStart(aStart),
        mEnd(aEnd),
        mOffset(aOffset),
        mName(aName),
        mPerms(aPerms) {}

  const nsCString& Name() const { return mName; }

  uintptr_t Start() const { return mStart; }
  uintptr_t End() const { return mEnd; }

  bool Includes(const void* aPtr) const {
    auto ptr = uintptr_t(aPtr);
    return ptr >= mStart && ptr < mEnd;
  }

  PermSet Perms() const { return mPerms; }
  VMFlagSet VMFlags() const { return mFlags; }

  // For file mappings, the offset in the mapped file which corresponds to the
  // start of the mapped region.
  size_t Offset() const { return mOffset; }

  size_t AnonHugePages() const { return mAnonHugePages; }
  size_t Anonymous() const { return mAnonymous; }
  size_t KernelPageSize() const { return mKernelPageSize; }
  size_t LazyFree() const { return mLazyFree; }
  size_t Locked() const { return mLocked; }
  size_t MMUPageSize() const { return mMMUPageSize; }
  size_t Private_Clean() const { return mPrivate_Clean; }
  size_t Private_Dirty() const { return mPrivate_Dirty; }
  size_t Private_Hugetlb() const { return mPrivate_Hugetlb; }
  size_t Pss() const { return mPss; }
  size_t Referenced() const { return mReferenced; }
  size_t Rss() const { return mRss; }
  size_t Shared_Clean() const { return mShared_Clean; }
  size_t Shared_Dirty() const { return mShared_Dirty; }
  size_t Shared_Hugetlb() const { return mShared_Hugetlb; }
  size_t ShmemPmdMapped() const { return mShmemPmdMapped; }
  size_t Size() const { return mSize; }
  size_t Swap() const { return mSwap; }
  size_t SwapPss() const { return mSwapPss; }

  // Dumps a string representation of the entry, similar to its format in the
  // smaps file, to the given string. Mainly useful for debugging.
  void Dump(nsACString& aOut) const;

  // These comparison operators are used for binary searching sorted arrays of
  // MemoryMapping entries to find the one which contains a given pointer.
  bool operator==(const void* aPtr) const { return Includes(aPtr); }
  bool operator<(const void* aPtr) const { return mStart < uintptr_t(aPtr); }

 private:
  friend nsresult GetMemoryMappings(nsTArray<MemoryMapping>& aMappings,
                                    pid_t aPid);

  uintptr_t mStart = 0;
  uintptr_t mEnd = 0;

  size_t mOffset = 0;

  nsCString mName;

  // Members for size fields in the smaps file. Please keep these in sync with
  // the sFields array.
  size_t mAnonHugePages = 0;
  size_t mAnonymous = 0;
  size_t mKernelPageSize = 0;
  size_t mLazyFree = 0;
  size_t mLocked = 0;
  size_t mMMUPageSize = 0;
  size_t mPrivate_Clean = 0;
  size_t mPrivate_Dirty = 0;
  size_t mPrivate_Hugetlb = 0;
  size_t mPss = 0;
  size_t mReferenced = 0;
  size_t mRss = 0;
  size_t mShared_Clean = 0;
  size_t mShared_Dirty = 0;
  size_t mShared_Hugetlb = 0;
  size_t mShmemPmdMapped = 0;
  size_t mSize = 0;
  size_t mSwap = 0;
  size_t mSwapPss = 0;

  PermSet mPerms{};
  VMFlagSet mFlags{};

  // Contains the name and offset of one of the above size_t fields, for use in
  // parsing in dumping. The below helpers contain a list of the fields, and map
  // Field entries to the appropriate member in a class instance.
  struct Field {
    const char* mName;
    size_t mOffset;
  };

  static const Field sFields[20];

  size_t& ValueForField(const Field& aField) {
    char* fieldPtr = reinterpret_cast<char*>(this) + aField.mOffset;
    return reinterpret_cast<size_t*>(fieldPtr)[0];
  }
  size_t ValueForField(const Field& aField) const {
    return const_cast<MemoryMapping*>(this)->ValueForField(aField);
  }
};

nsresult GetMemoryMappings(nsTArray<MemoryMapping>& aMappings, pid_t aPid = 0);

}  // namespace mozilla

#endif  // mozilla_MemoryMapping_h