xref: /llvm-project/lldb/include/lldb/Target/MemoryRegionInfo.h (revision b1751faada35e3456b2a3f6b6c9559b5d74d559b)
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, OptionalBool flash,
31                    lldb::offset_t blocksize, OptionalBool memory_tagged,
32                    OptionalBool stack_memory, OptionalBool shadow_stack)
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), m_is_shadow_stack(shadow_stack) {}
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   OptionalBool IsShadowStack() const { return m_is_shadow_stack; }
59 
60   void SetReadable(OptionalBool val) { m_read = val; }
61 
62   void SetWritable(OptionalBool val) { m_write = val; }
63 
64   void SetExecutable(OptionalBool val) { m_execute = val; }
65 
66   void SetShared(OptionalBool val) { m_shared = val; }
67 
68   void SetMapped(OptionalBool val) { m_mapped = val; }
69 
70   void SetName(const char *name) { m_name = ConstString(name); }
71 
72   OptionalBool GetFlash() const { return m_flash; }
73 
74   void SetFlash(OptionalBool val) { m_flash = val; }
75 
76   lldb::offset_t GetBlocksize() const { return m_blocksize; }
77 
78   void SetBlocksize(lldb::offset_t blocksize) { m_blocksize = blocksize; }
79 
80   void SetMemoryTagged(OptionalBool val) { m_memory_tagged = val; }
81 
82   void SetIsShadowStack(OptionalBool val) { m_is_shadow_stack = val; }
83 
84   // Get permissions as a uint32_t that is a mask of one or more bits from the
85   // lldb::Permissions
86   uint32_t GetLLDBPermissions() const {
87     uint32_t permissions = 0;
88     if (m_read == eYes)
89       permissions |= lldb::ePermissionsReadable;
90     if (m_write == eYes)
91       permissions |= lldb::ePermissionsWritable;
92     if (m_execute == eYes)
93       permissions |= lldb::ePermissionsExecutable;
94     return permissions;
95   }
96 
97   // Set permissions from a uint32_t that contains one or more bits from the
98   // lldb::Permissions
99   void SetLLDBPermissions(uint32_t permissions) {
100     m_read = (permissions & lldb::ePermissionsReadable) ? eYes : eNo;
101     m_write = (permissions & lldb::ePermissionsWritable) ? eYes : eNo;
102     m_execute = (permissions & lldb::ePermissionsExecutable) ? eYes : eNo;
103   }
104 
105   bool operator==(const MemoryRegionInfo &rhs) const {
106     return m_range == rhs.m_range && m_read == rhs.m_read &&
107            m_write == rhs.m_write && m_execute == rhs.m_execute &&
108            m_shared == rhs.m_shared && m_mapped == rhs.m_mapped &&
109            m_name == rhs.m_name && m_flash == rhs.m_flash &&
110            m_blocksize == rhs.m_blocksize &&
111            m_memory_tagged == rhs.m_memory_tagged &&
112            m_pagesize == rhs.m_pagesize &&
113            m_is_stack_memory == rhs.m_is_stack_memory &&
114            m_is_shadow_stack == rhs.m_is_shadow_stack;
115   }
116 
117   bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); }
118 
119   /// Get the target system's VM page size in bytes.
120   /// \return
121   ///     0 is returned if this information is unavailable.
122   int GetPageSize() const { return m_pagesize; }
123 
124   /// Get a vector of target VM pages that are dirty -- that have been
125   /// modified -- within this memory region.  This is an Optional return
126   /// value; it will only be available if the remote stub was able to
127   /// detail this.
128   const std::optional<std::vector<lldb::addr_t>> &GetDirtyPageList() const {
129     return m_dirty_pages;
130   }
131 
132   OptionalBool IsStackMemory() const { return m_is_stack_memory; }
133 
134   void SetIsStackMemory(OptionalBool val) { m_is_stack_memory = val; }
135 
136   void SetPageSize(int pagesize) { m_pagesize = pagesize; }
137 
138   void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) {
139     if (m_dirty_pages)
140       m_dirty_pages->clear();
141     m_dirty_pages = std::move(pagelist);
142   }
143 
144 protected:
145   RangeType m_range;
146   OptionalBool m_read = eDontKnow;
147   OptionalBool m_write = eDontKnow;
148   OptionalBool m_execute = eDontKnow;
149   OptionalBool m_shared = eDontKnow;
150   OptionalBool m_mapped = eDontKnow;
151   ConstString m_name;
152   OptionalBool m_flash = eDontKnow;
153   lldb::offset_t m_blocksize = 0;
154   OptionalBool m_memory_tagged = eDontKnow;
155   OptionalBool m_is_stack_memory = eDontKnow;
156   OptionalBool m_is_shadow_stack = eDontKnow;
157   int m_pagesize = 0;
158   std::optional<std::vector<lldb::addr_t>> m_dirty_pages;
159 };
160 
161 inline bool operator<(const MemoryRegionInfo &lhs,
162                       const MemoryRegionInfo &rhs) {
163   return lhs.GetRange() < rhs.GetRange();
164 }
165 
166 inline bool operator<(const MemoryRegionInfo &lhs, lldb::addr_t rhs) {
167   return lhs.GetRange().GetRangeBase() < rhs;
168 }
169 
170 inline bool operator<(lldb::addr_t lhs, const MemoryRegionInfo &rhs) {
171   return lhs < rhs.GetRange().GetRangeBase();
172 }
173 
174 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
175                               const MemoryRegionInfo &Info);
176 
177 // Forward-declarable wrapper.
178 class MemoryRegionInfos : public std::vector<lldb_private::MemoryRegionInfo> {
179 public:
180   using std::vector<lldb_private::MemoryRegionInfo>::vector;
181 };
182 
183 } // namespace lldb_private
184 
185 namespace llvm {
186 template <>
187 /// If Options is empty, prints a textual representation of the value. If
188 /// Options is a single character, it uses that character for the "yes" value,
189 /// while "no" is printed as "-", and "don't know" as "?". This can be used to
190 /// print the permissions in the traditional "rwx" form.
191 struct format_provider<lldb_private::MemoryRegionInfo::OptionalBool> {
192   static void format(const lldb_private::MemoryRegionInfo::OptionalBool &B,
193                      raw_ostream &OS, StringRef Options);
194 };
195 } // namespace llvm
196 
197 #endif // LLDB_TARGET_MEMORYREGIONINFO_H
198