diff options
Diffstat (limited to '')
-rw-r--r-- | xpcom/base/MemoryMapping.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/xpcom/base/MemoryMapping.h b/xpcom/base/MemoryMapping.h new file mode 100644 index 0000000000..2dc61a4215 --- /dev/null +++ b/xpcom/base/MemoryMapping.h @@ -0,0 +1,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 "nsStringFwd.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 |