1 | //===-- MemoryRegionInfo.h ---------------------------------------*- C++ |
2 | //-*-===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef LLDB_TARGET_MEMORYREGIONINFO_H |
11 | #define LLDB_TARGET_MEMORYREGIONINFO_H |
12 | |
13 | #include <optional> |
14 | #include <vector> |
15 | |
16 | #include "lldb/Utility/ConstString.h" |
17 | #include "lldb/Utility/RangeMap.h" |
18 | #include "llvm/Support/FormatProviders.h" |
19 | |
20 | namespace lldb_private { |
21 | class MemoryRegionInfo { |
22 | public: |
23 | typedef Range<lldb::addr_t, lldb::addr_t> RangeType; |
24 | |
25 | enum OptionalBool { eDontKnow = -1, eNo = 0, eYes = 1 }; |
26 | |
27 | MemoryRegionInfo() = default; |
28 | MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write, |
29 | OptionalBool execute, OptionalBool shared, |
30 | OptionalBool mapped, ConstString name, |
31 | OptionalBool flash, lldb::offset_t blocksize, |
32 | OptionalBool memory_tagged, OptionalBool stack_memory) |
33 | : m_range(range), m_read(read), m_write(write), m_execute(execute), |
34 | m_shared(shared), m_mapped(mapped), m_name(name), m_flash(flash), |
35 | m_blocksize(blocksize), m_memory_tagged(memory_tagged), |
36 | m_is_stack_memory(stack_memory) {} |
37 | |
38 | RangeType &GetRange() { return m_range; } |
39 | |
40 | void Clear() { *this = MemoryRegionInfo(); } |
41 | |
42 | const RangeType &GetRange() const { return m_range; } |
43 | |
44 | OptionalBool GetReadable() const { return m_read; } |
45 | |
46 | OptionalBool GetWritable() const { return m_write; } |
47 | |
48 | OptionalBool GetExecutable() const { return m_execute; } |
49 | |
50 | OptionalBool GetShared() const { return m_shared; } |
51 | |
52 | OptionalBool GetMapped() const { return m_mapped; } |
53 | |
54 | ConstString GetName() const { return m_name; } |
55 | |
56 | OptionalBool GetMemoryTagged() const { return m_memory_tagged; } |
57 | |
58 | void SetReadable(OptionalBool val) { m_read = val; } |
59 | |
60 | void SetWritable(OptionalBool val) { m_write = val; } |
61 | |
62 | void SetExecutable(OptionalBool val) { m_execute = val; } |
63 | |
64 | void SetShared(OptionalBool val) { m_shared = val; } |
65 | |
66 | void SetMapped(OptionalBool val) { m_mapped = val; } |
67 | |
68 | void SetName(const char *name) { m_name = ConstString(name); } |
69 | |
70 | OptionalBool GetFlash() const { return m_flash; } |
71 | |
72 | void SetFlash(OptionalBool val) { m_flash = val; } |
73 | |
74 | lldb::offset_t GetBlocksize() const { return m_blocksize; } |
75 | |
76 | void SetBlocksize(lldb::offset_t blocksize) { m_blocksize = blocksize; } |
77 | |
78 | void SetMemoryTagged(OptionalBool val) { m_memory_tagged = val; } |
79 | |
80 | // Get permissions as a uint32_t that is a mask of one or more bits from the |
81 | // lldb::Permissions |
82 | uint32_t GetLLDBPermissions() const { |
83 | uint32_t permissions = 0; |
84 | if (m_read == eYes) |
85 | permissions |= lldb::ePermissionsReadable; |
86 | if (m_write == eYes) |
87 | permissions |= lldb::ePermissionsWritable; |
88 | if (m_execute == eYes) |
89 | permissions |= lldb::ePermissionsExecutable; |
90 | return permissions; |
91 | } |
92 | |
93 | // Set permissions from a uint32_t that contains one or more bits from the |
94 | // lldb::Permissions |
95 | void SetLLDBPermissions(uint32_t permissions) { |
96 | m_read = (permissions & lldb::ePermissionsReadable) ? eYes : eNo; |
97 | m_write = (permissions & lldb::ePermissionsWritable) ? eYes : eNo; |
98 | m_execute = (permissions & lldb::ePermissionsExecutable) ? eYes : eNo; |
99 | } |
100 | |
101 | bool operator==(const MemoryRegionInfo &rhs) const { |
102 | return m_range == rhs.m_range && m_read == rhs.m_read && |
103 | m_write == rhs.m_write && m_execute == rhs.m_execute && |
104 | m_shared == rhs.m_shared && |
105 | m_mapped == rhs.m_mapped && m_name == rhs.m_name && |
106 | m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize && |
107 | m_memory_tagged == rhs.m_memory_tagged && |
108 | m_pagesize == rhs.m_pagesize && |
109 | m_is_stack_memory == rhs.m_is_stack_memory; |
110 | } |
111 | |
112 | bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); } |
113 | |
114 | /// Get the target system's VM page size in bytes. |
115 | /// \return |
116 | /// 0 is returned if this information is unavailable. |
117 | int GetPageSize() const { return m_pagesize; } |
118 | |
119 | /// Get a vector of target VM pages that are dirty -- that have been |
120 | /// modified -- within this memory region. This is an Optional return |
121 | /// value; it will only be available if the remote stub was able to |
122 | /// detail this. |
123 | const std::optional<std::vector<lldb::addr_t>> &GetDirtyPageList() const { |
124 | return m_dirty_pages; |
125 | } |
126 | |
127 | OptionalBool IsStackMemory() const { return m_is_stack_memory; } |
128 | |
129 | void SetIsStackMemory(OptionalBool val) { m_is_stack_memory = val; } |
130 | |
131 | void SetPageSize(int pagesize) { m_pagesize = pagesize; } |
132 | |
133 | void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) { |
134 | if (m_dirty_pages) |
135 | m_dirty_pages->clear(); |
136 | m_dirty_pages = std::move(pagelist); |
137 | } |
138 | |
139 | protected: |
140 | RangeType m_range; |
141 | OptionalBool m_read = eDontKnow; |
142 | OptionalBool m_write = eDontKnow; |
143 | OptionalBool m_execute = eDontKnow; |
144 | OptionalBool m_shared = eDontKnow; |
145 | OptionalBool m_mapped = eDontKnow; |
146 | ConstString m_name; |
147 | OptionalBool m_flash = eDontKnow; |
148 | lldb::offset_t m_blocksize = 0; |
149 | OptionalBool m_memory_tagged = eDontKnow; |
150 | OptionalBool m_is_stack_memory = eDontKnow; |
151 | int m_pagesize = 0; |
152 | std::optional<std::vector<lldb::addr_t>> m_dirty_pages; |
153 | }; |
154 | |
155 | inline bool operator<(const MemoryRegionInfo &lhs, |
156 | const MemoryRegionInfo &rhs) { |
157 | return lhs.GetRange() < rhs.GetRange(); |
158 | } |
159 | |
160 | inline bool operator<(const MemoryRegionInfo &lhs, lldb::addr_t rhs) { |
161 | return lhs.GetRange().GetRangeBase() < rhs; |
162 | } |
163 | |
164 | inline bool operator<(lldb::addr_t lhs, const MemoryRegionInfo &rhs) { |
165 | return lhs < rhs.GetRange().GetRangeBase(); |
166 | } |
167 | |
168 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, |
169 | const MemoryRegionInfo &Info); |
170 | |
171 | // Forward-declarable wrapper. |
172 | class MemoryRegionInfos : public std::vector<lldb_private::MemoryRegionInfo> { |
173 | public: |
174 | using std::vector<lldb_private::MemoryRegionInfo>::vector; |
175 | }; |
176 | |
177 | } |
178 | |
179 | namespace llvm { |
180 | template <> |
181 | /// If Options is empty, prints a textual representation of the value. If |
182 | /// Options is a single character, it uses that character for the "yes" value, |
183 | /// while "no" is printed as "-", and "don't know" as "?". This can be used to |
184 | /// print the permissions in the traditional "rwx" form. |
185 | struct format_provider<lldb_private::MemoryRegionInfo::OptionalBool> { |
186 | static void format(const lldb_private::MemoryRegionInfo::OptionalBool &B, |
187 | raw_ostream &OS, StringRef Options); |
188 | }; |
189 | } |
190 | |
191 | #endif // LLDB_TARGET_MEMORYREGIONINFO_H |
192 | |