1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#if defined(__arm__)
6#define PAGE_SIZE sysconf(_SC_PAGESIZE)
7#define PAGE_MASK (~(PAGE_SIZE-1))
8#endif
9
10#ifdef BIT64
11#define PRIA "016"
12#else
13#define PRIA "08"
14#endif
15
16enum MEMORY_REGION_FLAGS : uint32_t
17{
18 // PF_X = 0x01, // Execute
19 // PF_W = 0x02, // Write
20 // PF_R = 0x04, // Read
21 MEMORY_REGION_FLAG_PERMISSIONS_MASK = 0x0f,
22 MEMORY_REGION_FLAG_SHARED = 0x10,
23 MEMORY_REGION_FLAG_PRIVATE = 0x20,
24 MEMORY_REGION_FLAG_MEMORY_BACKED = 0x40
25};
26
27struct MemoryRegion
28{
29private:
30 uint32_t m_flags;
31 uint64_t m_startAddress;
32 uint64_t m_endAddress;
33 uint64_t m_offset;
34
35 // The name used for NT_FILE output
36 const char* m_fileName;
37
38public:
39 MemoryRegion(uint32_t flags, uint64_t start, uint64_t end) :
40 m_flags(flags),
41 m_startAddress(start),
42 m_endAddress(end),
43 m_offset(0),
44 m_fileName(nullptr)
45 {
46 assert((start & ~PAGE_MASK) == 0);
47 assert((end & ~PAGE_MASK) == 0);
48 }
49
50 MemoryRegion(uint32_t flags, uint64_t start, uint64_t end, uint64_t offset, const char* filename) :
51 m_flags(flags),
52 m_startAddress(start),
53 m_endAddress(end),
54 m_offset(offset),
55 m_fileName(filename)
56 {
57 assert((start & ~PAGE_MASK) == 0);
58 assert((end & ~PAGE_MASK) == 0);
59 }
60
61 // This is a special constructor for the module base address
62 // set where the start/end are not page aligned and "offset"
63 // is reused as the module base address.
64 MemoryRegion(uint32_t flags, uint64_t start, uint64_t end, uint64_t baseAddress) :
65 m_flags(flags),
66 m_startAddress(start),
67 m_endAddress(end),
68 m_offset(baseAddress),
69 m_fileName(nullptr)
70 {
71 }
72
73 // copy with new file name constructor
74 MemoryRegion(const MemoryRegion& region, const char* fileName) :
75 m_flags(region.m_flags),
76 m_startAddress(region.m_startAddress),
77 m_endAddress(region.m_endAddress),
78 m_offset(region.m_offset),
79 m_fileName(fileName)
80 {
81 }
82
83 // copy with new flags constructor. The file name is not copied.
84 MemoryRegion(const MemoryRegion& region, uint32_t flags) :
85 m_flags(flags),
86 m_startAddress(region.m_startAddress),
87 m_endAddress(region.m_endAddress),
88 m_offset(region.m_offset),
89 m_fileName(nullptr)
90 {
91 }
92
93 // copy constructor
94 MemoryRegion(const MemoryRegion& region) :
95 m_flags(region.m_flags),
96 m_startAddress(region.m_startAddress),
97 m_endAddress(region.m_endAddress),
98 m_offset(region.m_offset),
99 m_fileName(region.m_fileName)
100 {
101 }
102
103 uint32_t Permissions() const { return m_flags & MEMORY_REGION_FLAG_PERMISSIONS_MASK; }
104 uint32_t Flags() const { return m_flags; }
105 bool IsBackedByMemory() const { return (m_flags & MEMORY_REGION_FLAG_MEMORY_BACKED) != 0; }
106 uint64_t StartAddress() const { return m_startAddress; }
107 uint64_t EndAddress() const { return m_endAddress; }
108 uint64_t Size() const { return m_endAddress - m_startAddress; }
109 uint64_t Offset() const { return m_offset; }
110 const char* FileName() const { return m_fileName; }
111
112 bool operator<(const MemoryRegion& rhs) const
113 {
114 return (m_startAddress < rhs.m_startAddress) && (m_endAddress <= rhs.m_startAddress);
115 }
116
117 // Returns true if "rhs" is wholly contained in this one
118 bool Contains(const MemoryRegion& rhs) const
119 {
120 return (m_startAddress <= rhs.m_startAddress) && (m_endAddress >= rhs.m_endAddress);
121 }
122
123 // Free the file name memory
124 void Cleanup()
125 {
126 if (m_fileName != nullptr)
127 {
128 free((void*)m_fileName);
129 m_fileName = nullptr;
130 }
131 }
132
133 void Trace() const
134 {
135 TRACE("%s%" PRIA PRIx64 " - %" PRIA PRIx64 " (%06" PRId64 ") %" PRIA PRIx64 " %02x %s\n", IsBackedByMemory() ? "*" : " ", m_startAddress, m_endAddress,
136 Size() / PAGE_SIZE, m_offset, m_flags, m_fileName != nullptr ? m_fileName : "");
137 }
138};
139