llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: David Spickett (DavidSpickett)
<details>
<summary>Changes</summary>
In this change I'm extending the "memory region" command to show users the
overlay permissions that a protection key refers to, and the result of
applying that overlay to the page table permissions.
For example, protection key 0 refers to Perm0 in the por register.
```
(lldb) register read por
Perm0 = Read, Write, Execute
```
This is the default key, so many regions use it.
```
(lldb) memory region --all
<...>
[0x000ffffff7db0000-0x000ffffff7f40000) r-x
/usr/lib/aarch64-linux-gnu/libc.so.6 PT_LOAD[0]
protection key: 0 (rwx, effective: r-x)
```
Protection keys can only change what was already enabled in the
page table. So we start with read and execute. Then a read/write/execute overlay
is applied. We cannot add write, so the result is read and execute.
Here's an example of its use with a real crash (output edited):
```
(lldb) c
* thread #<!-- -->1, name = 'test.o', stop reason = signal SIGSEGV: failed
protection key checks (fault address=0xffffff7d60000)
-> 106 read_only_page[0] = '?';
(lldb) memory region 0xffffff7d60000
[0x000ffffff7d60000-0x000ffffff7d70000) rw-
protection key: 6 (r--, effective: r--)
(lldb) register read por
Perm6 = Read
```
The calculation of permissions is implemented by a new ABI method.
It's in ABI for 2 reasons:
* These overlays are usually in a register (X86 and AArch64 are)
and that register name is architecture specific.
* The way the overlay values apply may differ between architecture.
AArch64 treats a set bit as adding a permission, but some may
treat it as removing.
Technically this is dependent on operating system and architecture.
However, so are the methods for removing non-address bits, and those
are in ABI too.
To test this I have changed the allocations in the test program
to use read+execute permissions by default. With read+write+execute
I could not observe that the overlay only changes enabled permissions.
---
Patch is 43.51 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/184115.diff
18 Files Affected:
- (modified) lldb/docs/resources/lldbgdbremote.md (+2)
- (modified) lldb/include/lldb/API/SBMemoryRegionInfo.h (+13)
- (modified) lldb/include/lldb/Target/ABI.h (+25)
- (modified) lldb/include/lldb/Target/MemoryRegionInfo.h (+11-3)
- (modified) lldb/source/API/SBMemoryRegionInfo.cpp (+12)
- (modified) lldb/source/Commands/CommandObjectMemory.cpp (+23)
- (modified) lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp (+46)
- (modified) lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h (+5)
- (modified) lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp (+4)
- (modified)
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (+4)
- (modified)
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
(+3)
- (modified) lldb/source/Target/MemoryRegionInfo.cpp (+8-8)
- (modified)
lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py (+67)
- (modified) lldb/test/API/linux/aarch64/permission_overlay/main.c (+9-3)
- (modified) lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp (+92-34)
- (modified) lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
(+1-1)
- (modified)
lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp (+20)
- (modified) lldb/unittests/Process/minidump/MinidumpParserTest.cpp (+59-55)
``````````diff
diff --git a/lldb/docs/resources/lldbgdbremote.md
b/lldb/docs/resources/lldbgdbremote.md
index 9aa7ad2259a6a..148b3a03aff86 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -1443,6 +1443,8 @@ tuples to return are:
listed (`dirty-pages:;`) indicates no dirty pages in
this memory region. The *absence* of this key means
that this stub cannot determine dirty pages.
+* `protection-key:<key>`- where `<key>` is an unsigned integer memory
protection
+ key.
If the address requested is not in a mapped region (e.g. we've jumped through
a NULL pointer and are at 0x0) currently lldb expects to get back the size
diff --git a/lldb/include/lldb/API/SBMemoryRegionInfo.h
b/lldb/include/lldb/API/SBMemoryRegionInfo.h
index dc5aa0858e1e3..9174675d2a11c 100644
--- a/lldb/include/lldb/API/SBMemoryRegionInfo.h
+++ b/lldb/include/lldb/API/SBMemoryRegionInfo.h
@@ -111,6 +111,19 @@ class LLDB_API SBMemoryRegionInfo {
/// or 0 if this information is unavailable.
int GetPageSize();
+ /// Returns whether this memory region has a memory protection key.
+ ///
+ /// \return
+ /// True if the region memory region has a memory protection key.
+ bool HasProtectionKey();
+
+ /// Returns the memory protection key of the memory region.
+ ///
+ /// \return
+ /// The memory protection key of the region. This value is only valid if
+ /// HasProtectionKey() is true.
+ uint32_t GetProtectionKey();
+
bool operator==(const lldb::SBMemoryRegionInfo &rhs) const;
bool operator!=(const lldb::SBMemoryRegionInfo &rhs) const;
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index 1a1f1724222e3..4eb38d33c9eed 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -152,6 +152,31 @@ class ABI : public PluginInterface {
static lldb::ABISP FindPlugin(lldb::ProcessSP process_sp, const ArchSpec
&arch);
+ struct MemoryPermissions {
+ // Both of these are sets of lldb::Permissions values.
+ // Overlay are the permissions being applied to the original permissions.
+ uint32_t overlay;
+ // Effective is the result of applying the overlay to the original
+ // permissions. Calculating this is done by the plugin because some
+ // permission overlays are done as positive (add permissions) and some as
+ // negative (remove permissions).
+ uint32_t effective;
+ };
+
+ /// Get the permissions being overlayed for a given memory key, and the
+ /// resulting permissions after applying the overlay. Typically the
protection
+ /// key is used to look up in some architecture specific set of permissions.
+ /// On AArch64, this is the POR register, used by the Permission Overlay
+ /// Extension.
+ ///
+ /// Returns std::nullopt if the current target does not have such an overlay
+ /// system, or if the protection key is not valid.
+ virtual std::optional<MemoryPermissions>
+ GetMemoryPermissions(lldb_private::RegisterContext ®_ctx,
+ unsigned protection_key, uint32_t original_permissions)
{
+ return std::nullopt;
+ }
+
protected:
ABI(lldb::ProcessSP process_sp, std::unique_ptr<llvm::MCRegisterInfo>
info_up)
: m_process_wp(process_sp), m_mc_register_info_up(std::move(info_up)) {
diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h
b/lldb/include/lldb/Target/MemoryRegionInfo.h
index dc37a7dbeda52..1513d93f1ab22 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -29,11 +29,13 @@ class MemoryRegionInfo {
OptionalBool execute, OptionalBool shared,
OptionalBool mapped, ConstString name, OptionalBool flash,
lldb::offset_t blocksize, OptionalBool memory_tagged,
- OptionalBool stack_memory, OptionalBool shadow_stack)
+ OptionalBool stack_memory, OptionalBool shadow_stack,
+ std::optional<unsigned> protection_key)
: m_range(range), m_read(read), m_write(write), m_execute(execute),
m_shared(shared), m_mapped(mapped), m_name(name), m_flash(flash),
m_blocksize(blocksize), m_memory_tagged(memory_tagged),
- m_is_stack_memory(stack_memory), m_is_shadow_stack(shadow_stack) {}
+ m_is_stack_memory(stack_memory), m_is_shadow_stack(shadow_stack),
+ m_protection_key(protection_key) {}
RangeType &GetRange() { return m_range; }
@@ -57,6 +59,8 @@ class MemoryRegionInfo {
OptionalBool IsShadowStack() const { return m_is_shadow_stack; }
+ std::optional<unsigned> GetProtectionKey() const { return m_protection_key; }
+
void SetReadable(OptionalBool val) { m_read = val; }
void SetWritable(OptionalBool val) { m_write = val; }
@@ -81,6 +85,8 @@ class MemoryRegionInfo {
void SetIsShadowStack(OptionalBool val) { m_is_shadow_stack = val; }
+ void SetProtectionKey(std::optional<unsigned> key) { m_protection_key = key;
}
+
// Get permissions as a uint32_t that is a mask of one or more bits from the
// lldb::Permissions
uint32_t GetLLDBPermissions() const {
@@ -111,7 +117,8 @@ class MemoryRegionInfo {
m_memory_tagged == rhs.m_memory_tagged &&
m_pagesize == rhs.m_pagesize &&
m_is_stack_memory == rhs.m_is_stack_memory &&
- m_is_shadow_stack == rhs.m_is_shadow_stack;
+ m_is_shadow_stack == rhs.m_is_shadow_stack &&
+ m_protection_key == rhs.m_protection_key;
}
bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs);
}
@@ -154,6 +161,7 @@ class MemoryRegionInfo {
OptionalBool m_memory_tagged = eDontKnow;
OptionalBool m_is_stack_memory = eDontKnow;
OptionalBool m_is_shadow_stack = eDontKnow;
+ std::optional<unsigned> m_protection_key = std::nullopt;
int m_pagesize = 0;
std::optional<std::vector<lldb::addr_t>> m_dirty_pages;
};
diff --git a/lldb/source/API/SBMemoryRegionInfo.cpp
b/lldb/source/API/SBMemoryRegionInfo.cpp
index cd25be5d52769..99bb6f0de4915 100644
--- a/lldb/source/API/SBMemoryRegionInfo.cpp
+++ b/lldb/source/API/SBMemoryRegionInfo.cpp
@@ -160,6 +160,18 @@ int SBMemoryRegionInfo::GetPageSize() {
return m_opaque_up->GetPageSize();
}
+bool SBMemoryRegionInfo::HasProtectionKey() {
+ LLDB_INSTRUMENT_VA(this);
+
+ return m_opaque_up->GetProtectionKey() != std::nullopt;
+}
+
+uint32_t SBMemoryRegionInfo::GetProtectionKey() {
+ LLDB_INSTRUMENT_VA(this);
+
+ return m_opaque_up->GetProtectionKey().value_or(0);
+}
+
bool SBMemoryRegionInfo::GetDescription(SBStream &description) {
LLDB_INSTRUMENT_VA(this, description);
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp
b/lldb/source/Commands/CommandObjectMemory.cpp
index 93b6c1751b121..f1e3479fc8f69 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -1694,6 +1694,29 @@ class CommandObjectMemoryRegion : public
CommandObjectParsed {
MemoryRegionInfo::OptionalBool is_shadow_stack =
range_info.IsShadowStack();
if (is_shadow_stack == MemoryRegionInfo::OptionalBool::eYes)
result.AppendMessage("shadow stack: yes");
+ if (std::optional<unsigned> protection_key =
+ range_info.GetProtectionKey()) {
+ result.AppendMessageWithFormat("protection key: %" PRIu32,
+ *protection_key);
+
+ if (const lldb::ABISP &abi = target.GetProcessSP()->GetABI()) {
+ uint32_t base_permissions = range_info.GetLLDBPermissions();
+ if (auto permissions =
+ abi->GetMemoryPermissions(*m_exe_ctx.GetRegisterContext(),
+ *protection_key, base_permissions)) {
+ result.AppendMessageWithFormatv(
+ " ({0}{1}{2}, effective: {3}{4}{5})",
+ permissions->overlay & lldb::ePermissionsReadable ? 'r' : '-',
+ permissions->overlay & lldb::ePermissionsWritable ? 'w' : '-',
+ permissions->overlay & lldb::ePermissionsExecutable ? 'x' : '-',
+ permissions->effective & lldb::ePermissionsReadable ? 'r' : '-',
+ permissions->effective & lldb::ePermissionsWritable ? 'w' : '-',
+ permissions->effective & lldb::ePermissionsExecutable ? 'x'
+ : '-');
+ }
+ } else
+ result.AppendMessage("");
+ }
const std::optional<std::vector<addr_t>> &dirty_page_list =
range_info.GetDirtyPageList();
diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
index aa9c20b6bb2cf..83a777da3237e 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
@@ -884,3 +884,49 @@ void ABISysV_arm64::Initialize() {
void ABISysV_arm64::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
+
+std::optional<ABISysV_arm64::MemoryPermissions>
+ABISysV_arm64::GetMemoryPermissions(lldb_private::RegisterContext ®_ctx,
+ unsigned protection_key,
+ uint32_t original_permissions) {
+ // The presence of the POR register means we have the Permission Overlay
+ // Extension.
+ // See Arm Architecture Reference manual "POR_EL0, Permission Overlay
Register
+ // 0 (EL0)".
+ const RegisterInfo *por_info = reg_ctx.GetRegisterInfoByName("por");
+ if (!por_info)
+ return std::nullopt;
+
+ uint64_t por_value =
+ reg_ctx.ReadRegisterAsUnsigned(por_info, LLDB_INVALID_ADDRESS);
+ if (por_value == LLDB_INVALID_ADDRESS)
+ return std::nullopt;
+
+ // POR contains 16, 4-bit permission sets (though Linux limits this to 8
+ // useable sets).
+ if (protection_key >= 16)
+ return std::nullopt;
+
+ // Bit 3 - reserved, bit 2 - write, bit 1 - execute, bit 0 - read.
+ const uint64_t por_permissions = (por_value >> (protection_key * 4)) & 0xf;
+ uint32_t overlay = 0;
+ if (por_permissions & 4)
+ overlay |= lldb::ePermissionsWritable;
+ if (por_permissions & 2)
+ overlay |= lldb::ePermissionsExecutable;
+ if (por_permissions & 1)
+ overlay |= lldb::ePermissionsReadable;
+
+ uint32_t effective = original_permissions;
+
+ // Permission overlays cannot add permissions, they can only keep, or
disable,
+ // what was originally set.
+ if (!(overlay & lldb::ePermissionsWritable))
+ effective &= ~lldb::ePermissionsWritable;
+ if (!(overlay & lldb::ePermissionsExecutable))
+ effective &= ~lldb::ePermissionsExecutable;
+ if (!(overlay & lldb::ePermissionsReadable))
+ effective &= ~lldb::ePermissionsReadable;
+
+ return MemoryPermissions{overlay, effective};
+}
diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
index 213fbf7417b2c..53c79ee2d6eb1 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
@@ -81,6 +81,11 @@ class ABISysV_arm64 : public ABIAArch64 {
lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+ virtual std::optional<MemoryPermissions>
+ GetMemoryPermissions(lldb_private::RegisterContext ®_ctx,
+ unsigned protection_key,
+ uint32_t original_permissions) override;
+
protected:
lldb::ValueObjectSP
GetReturnValueObjectImpl(lldb_private::Thread &thread,
diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
index 2ed896327a2f8..eea0bf245877d 100644
--- a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
+++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
@@ -174,6 +174,10 @@ void lldb_private::ParseLinuxSMapRegions(llvm::StringRef
linux_smap,
region->SetMemoryTagged(MemoryRegionInfo::eYes);
else if (flag == "ss")
region->SetIsShadowStack(MemoryRegionInfo::eYes);
+ } else if (name == "ProtectionKey") {
+ unsigned key = 0;
+ if (!value.ltrim().getAsInteger(10, key))
+ region->SetProtectionKey(key);
}
} else {
// Orphaned settings line
diff --git
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 738e4013b6154..c639090ebe9af 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1677,6 +1677,10 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
dirty_page_list.push_back(page);
}
region_info.SetDirtyPageList(dirty_page_list);
+ } else if (name == "protection-key") {
+ unsigned protection_key = 0;
+ if (!value.getAsInteger(10, protection_key))
+ region_info.SetProtectionKey(protection_key);
}
}
diff --git
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 2f62415446b7a..72b6d7adbbf96 100644
---
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2907,6 +2907,9 @@
GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
response.PutStringAsRawHex8(name.GetStringRef());
response.PutChar(';');
}
+
+ if (std::optional<unsigned> protection_key =
region_info.GetProtectionKey())
+ response.Printf("protection-key:%" PRIu32 ";", *protection_key);
}
return SendPacketNoLock(response.GetString());
diff --git a/lldb/source/Target/MemoryRegionInfo.cpp
b/lldb/source/Target/MemoryRegionInfo.cpp
index 979e45ad023af..7bdb3dc4f3168 100644
--- a/lldb/source/Target/MemoryRegionInfo.cpp
+++ b/lldb/source/Target/MemoryRegionInfo.cpp
@@ -12,14 +12,14 @@ using namespace lldb_private;
llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS,
const MemoryRegionInfo &Info) {
- return OS << llvm::formatv("MemoryRegionInfo([{0}, {1}), {2:r}{3:w}{4:x}, "
- "{5}, `{6}`, {7}, {8}, {9}, {10}, {11})",
- Info.GetRange().GetRangeBase(),
- Info.GetRange().GetRangeEnd(), Info.GetReadable(),
- Info.GetWritable(), Info.GetExecutable(),
- Info.GetMapped(), Info.GetName(), Info.GetFlash(),
- Info.GetBlocksize(), Info.GetMemoryTagged(),
- Info.IsStackMemory(), Info.IsShadowStack());
+ return OS << llvm::formatv(
+ "MemoryRegionInfo([{0}, {1}), {2:r}{3:w}{4:x}, "
+ "{5}, `{6}`, {7}, {8}, {9}, {10}, {11}, {12})",
+ Info.GetRange().GetRangeBase(), Info.GetRange().GetRangeEnd(),
+ Info.GetReadable(), Info.GetWritable(), Info.GetExecutable(),
+ Info.GetMapped(), Info.GetName(), Info.GetFlash(),
+ Info.GetBlocksize(), Info.GetMemoryTagged(), Info.IsStackMemory(),
+ Info.IsShadowStack(), Info.GetProtectionKey());
}
void llvm::format_provider<MemoryRegionInfo::OptionalBool>::format(
diff --git
a/lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py
b/lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py
index 056267a2dc900..9b20b39095789 100644
--- a/lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py
+++ b/lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py
@@ -79,6 +79,63 @@ def test_poe_live(self):
self.expect("expression expr_function()", substrs=["$0 = 1"])
self.expect("register read por", substrs=[self.EXPECTED_POR])
+ # Unmapped region has no key (not even default).
+ self.expect("memory region 0", substrs=["protection key:"],
matching=False)
+
+ # The region has base permissions r-x, and overlay is r--. The result
+ # is that execution is disabled.
+ self.expect(
+ "memory region read_only_page",
+ substrs=["rw-", "protection key: 6 (r--, effective: r--)"],
+ )
+ # A region not assigned to a protection key has the default key 0. This
+ # key is rwx, but overlays cannot add permissions not already in the
+ # page table. So the execute permission is not enabled.
+ self.expect(
+ "memory region key_zero_page",
+ substrs=["rw-", "protection key: 0 (rwx, effective: rw-)"],
+ )
+
+ # Overlay permissions are on their own line.
+ self.expect(
+ "memory region --all",
+ patterns=["\nprotection key: [0-9]+ \([rwx-]{3}, effective:
[rwx-]{3}\)\n"],
+ )
+
+ # Protection keys are also in SBMemoryRegionInfo.
+ process = self.dbg.GetSelectedTarget().GetProcess()
+ info = lldb.SBMemoryRegionInfo()
+
+ frame = (
+ self.dbg.GetSelectedTarget()
+ .GetProcess()
+ .GetSelectedThread()
+ .GetSelectedFrame()
+ )
+
+ err = lldb.SBError()
+ read_only_addr = frame.GetValueForVariablePath(
+ "read_only_page"
+ ).GetValueAsUnsigned(err)
+ self.assertTrue(err.Success())
+ key_zero_addr = frame.GetValueForVariablePath(
+ "key_zero_page"
+ ).GetValueAsUnsigned(err)
+ self.assertTrue(err.Success())
+
+ region_api_info = [
+ # An unmapped region will have no key at all.
+ # The getter returns 0 as a default, but should not be trusted.
+ (0, False, 0),
+ (read_only_addr, True, 6),
+ (key_zero_addr, True, 0),
+ ]
+ for addr, valid, key in region_api_info:
+ err = process.GetMemoryRegionInfo(addr, info)
+ self.assertTrue(err.Success())
+ self.assertEqual(info.HasProtectionKey(), valid)
+ self.assertEqual(info.GetProtectionKey(), key)
+
# Not passing this to the application allows us to fix the permissions
# using lldb, then continue to a normal exit.
self.runCmd("process handle SIGSEGV --pass false")
@@ -127,3 +184,13 @@ def test_poe_core(self):
"register read por",
substrs=[f" {self.EXPECTED_POR}\n" +
self.EXPECTED_POR_FIELDS],
)
+
+ # Protection keys are listed in /proc/<pid>/smaps, which is not
included
+ # in core files.
+ self.expect("memory region --all", substrs=["protection key:"],
matching=False)
+
+ # No region should have a key at all, not even a default.
+ process = self.dbg.GetSelectedTarget().GetProcess()
+ for region in
self.dbg.GetSelectedTarget().GetProcess().GetMemoryRegions():
+ self.assertEqual(region.HasProtectionKey(), False)
+ self.assertEqual(region.GetProtectionKey(), 0)
diff --git a/lldb/test/API/linux/aarch64/permission_overlay/main.c
b/lldb/test/API/linux/aarch64/permission_overlay/main.c
index 6f47ba9d774da..5eb4782b9a6ca 100644
--- a/lldb/test/API/linux/aarch64/permission_overlay/main.c
+++ b/lldb/test/API/linux/aarch64/permission_overlay/main.c
@@ -76,11 +76,17 @@ int main(void) {
// Which leaves 7 keys available for programs to allocate.
const size_t page_size = (size_t)sysconf(_SC_PAGESIZE);
- // pkeys can only subtract from the set of permissions in the page table,
- // so we set the page table to allow everything.
- const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+ // pkeys can only subtract from the set of permissions in the page table.
+ // So we leave out execute here to check later that an overlay does not
+ // enable execution.
+ const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ // This page will have the default key 0.
+ char *key_zero_page = mmap(NULL, page_size, prot, flags, -1, 0);
+ if (key_zero_page == MAP_FAILED)
+ exit(2);
+
// Later we will use this to cause a protection key fault.
char *read_only_page = NULL;
diff --git a/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
b/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
index d94bb4f4db982..f3f40cbc2f19d 100644
--- a/l...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/184115
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits