[Lldb-commits] [lldb] [lldb][Linux] Mark memory regions used for shadow stacks (PR #117861)

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 27 01:50:09 PST 2024


https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/117861

This is intended for use with Arm's Guarded Control Stack extension (GCS). Which reuses some existing shadow stack support in Linux. It should also work with the x86 equivalent.

A "ss" flag is added to the "VmFlags" line of shadow stack memory regions in /proc/<pid>/smaps. To keep the naming generic I've called it shadow stack instead of guarded control stack.

Also the wording is "shadow stack: yes" because the shadow stack region is just where it's stored. It's enabled for the whole process or it isn't. As opposed to memory tagging which can be enabled per region, so "memory tagging: enabled" fits better for that.

I've added a test case that is also intended to be the start of a set of tests for GCS. This should help me avoid duplicating the inline assembly needed.

Note that no special compiler support is needed for the test. However, for the intial enabling of GCS (assuming the libc isn't doing it) we do need to use an inline assembly version of prctl.

This is because as soon as you enable GCS, all returns are checked against the GCS. If the GCS is empty, the program will fault. In other words, you can never return from the function that enabled GCS, unless you push values onto it (which is possible but not needed here).

So you cannot use the libc's prctl wrapper for this reason. You can use that wrapper for anything else, as we do to check if GCS is enabled.

>From ecac70b8d7b00e729b3203c6d5e6aff827775467 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 19 Aug 2024 15:55:45 +0100
Subject: [PATCH] [lldb][Linux] Mark memory regions used for shadow stacks

This is intended for use with Arm's Guarded Control Stack extension
(GCS). Which reuses some existing shadow stack support in Linux.
It should also work with the x86 equivalent.

A "ss" flag is added to the "VmFlags" line of shadow stack memory
regions in /proc/<pid>/smaps. To keep the naming generic I've called
it shadow stack instead of guarded control stack.

Also the wording is "shadow stack: yes" because the shadow stack
region is just where it's stored. It's enabled for the whole process
or it isn't. As opposed to memory tagging which can be enabled per
region, so "memory tagging: enabled" fits better for that.

I've added a test case that is also intended to be the start of
a set of tests for GCS. This should help me avoid duplicating the
inline assembly needed.

Note that no special compiler support is needed for the test.
However, for the intial enabling of GCS (assuming the libc isn't
doing it) we do need to use an inline assembly version of prctl.

This is because as soon as you enable GCS, all returns are checked
against the GCS. If the GCS is empty, the program will fault.
In other words, you can never return from the function that enabled
GCS, unless you push values onto it (which is possible but not needed
here).

So you cannot use the libc's prctl wrapper for this reason. You can
use that wrapper for anything else, as we do to check if GCS is
enabled.
---
 lldb/include/lldb/Target/MemoryRegionInfo.h   |  22 ++-
 .../Python/lldbsuite/test/lldbtest.py         |   3 +
 lldb/source/Commands/CommandObjectMemory.cpp  |   3 +
 .../Plugins/Process/Utility/LinuxProcMaps.cpp |  15 +-
 .../GDBRemoteCommunicationClient.cpp          |   7 +-
 .../GDBRemoteCommunicationServerLLGS.cpp      |  12 +-
 lldb/source/Target/MemoryRegionInfo.cpp       |   5 +-
 lldb/test/API/linux/aarch64/gcs/Makefile      |   3 +
 .../linux/aarch64/gcs/TestAArch64LinuxGCS.py  |  63 +++++++
 lldb/test/API/linux/aarch64/gcs/main.c        |  54 ++++++
 .../Process/Utility/LinuxProcMapsTest.cpp     | 156 +++++++++---------
 .../MemoryTagManagerAArch64MTETest.cpp        |  10 +-
 .../GDBRemoteCommunicationClientTest.cpp      |   5 +-
 .../Process/minidump/MinidumpParserTest.cpp   |  92 ++++++-----
 14 files changed, 304 insertions(+), 146 deletions(-)
 create mode 100644 lldb/test/API/linux/aarch64/gcs/Makefile
 create mode 100644 lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py
 create mode 100644 lldb/test/API/linux/aarch64/gcs/main.c

diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h
index 66a4b3ed1b42d5..3e1272c2bba214 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -27,13 +27,13 @@ class MemoryRegionInfo {
   MemoryRegionInfo() = default;
   MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write,
                    OptionalBool execute, OptionalBool shared,
-                   OptionalBool mapped, ConstString name,
-                   OptionalBool flash, lldb::offset_t blocksize,
-                   OptionalBool memory_tagged, OptionalBool stack_memory)
+                   OptionalBool mapped, ConstString name, OptionalBool flash,
+                   lldb::offset_t blocksize, OptionalBool memory_tagged,
+                   OptionalBool stack_memory, OptionalBool shadow_stack)
       : 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_stack_memory(stack_memory), m_is_shadow_stack(shadow_stack) {}
 
   RangeType &GetRange() { return m_range; }
 
@@ -55,6 +55,8 @@ class MemoryRegionInfo {
 
   OptionalBool GetMemoryTagged() const { return m_memory_tagged; }
 
+  OptionalBool IsShadowStack() const { return m_is_shadow_stack; }
+
   void SetReadable(OptionalBool val) { m_read = val; }
 
   void SetWritable(OptionalBool val) { m_write = val; }
@@ -77,6 +79,8 @@ class MemoryRegionInfo {
 
   void SetMemoryTagged(OptionalBool val) { m_memory_tagged = val; }
 
+  void SetIsShadowStack(OptionalBool val) { m_is_shadow_stack = val; }
+
   // Get permissions as a uint32_t that is a mask of one or more bits from the
   // lldb::Permissions
   uint32_t GetLLDBPermissions() const {
@@ -101,12 +105,13 @@ class MemoryRegionInfo {
   bool operator==(const MemoryRegionInfo &rhs) const {
     return m_range == rhs.m_range && m_read == rhs.m_read &&
            m_write == rhs.m_write && m_execute == rhs.m_execute &&
-           m_shared == rhs.m_shared &&
-           m_mapped == rhs.m_mapped && m_name == rhs.m_name &&
-           m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize &&
+           m_shared == rhs.m_shared && m_mapped == rhs.m_mapped &&
+           m_name == rhs.m_name && m_flash == rhs.m_flash &&
+           m_blocksize == rhs.m_blocksize &&
            m_memory_tagged == rhs.m_memory_tagged &&
            m_pagesize == rhs.m_pagesize &&
-           m_is_stack_memory == rhs.m_is_stack_memory;
+           m_is_stack_memory == rhs.m_is_stack_memory &&
+           m_is_shadow_stack == rhs.m_is_shadow_stack;
   }
 
   bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); }
@@ -148,6 +153,7 @@ class MemoryRegionInfo {
   lldb::offset_t m_blocksize = 0;
   OptionalBool m_memory_tagged = eDontKnow;
   OptionalBool m_is_stack_memory = eDontKnow;
+  OptionalBool m_is_shadow_stack = eDontKnow;
   int m_pagesize = 0;
   std::optional<std::vector<lldb::addr_t>> m_dirty_pages;
 };
diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index 8884ef5933ada8..cee2abafdac83f 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1363,6 +1363,9 @@ def isAArch64SMEFA64(self):
     def isAArch64MTE(self):
         return self.isAArch64() and "mte" in self.getCPUInfo()
 
+    def isAArch64GCS(self):
+        return self.isAArch64() and "gcs" in self.getCPUInfo()
+
     def isAArch64PAuth(self):
         if self.getArchitecture() == "arm64e":
             return True
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index b5612f21f11563..6ca4056c960ee5 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -1664,6 +1664,9 @@ class CommandObjectMemoryRegion : public CommandObjectParsed {
     MemoryRegionInfo::OptionalBool memory_tagged = range_info.GetMemoryTagged();
     if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes)
       result.AppendMessage("memory tagging: enabled");
+    MemoryRegionInfo::OptionalBool is_shadow_stack = range_info.IsShadowStack();
+    if (is_shadow_stack == MemoryRegionInfo::OptionalBool::eYes)
+      result.AppendMessage("shadow stack: yes");
 
     const std::optional<std::vector<addr_t>> &dirty_page_list =
         range_info.GetDirtyPageList();
diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
index fd803c8cabafe3..2ed896327a2f82 100644
--- a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
+++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
@@ -164,12 +164,17 @@ void lldb_private::ParseLinuxSMapRegions(llvm::StringRef linux_smap,
     if (!name.contains(' ')) {
       if (region) {
         if (name == "VmFlags") {
-          if (value.contains("mt"))
-            region->SetMemoryTagged(MemoryRegionInfo::eYes);
-          else
-            region->SetMemoryTagged(MemoryRegionInfo::eNo);
+          region->SetMemoryTagged(MemoryRegionInfo::eNo);
+          region->SetIsShadowStack(MemoryRegionInfo::eNo);
+
+          llvm::SmallVector<llvm::StringRef> flags;
+          value.split(flags, ' ', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+          for (llvm::StringRef flag : flags)
+            if (flag == "mt")
+              region->SetMemoryTagged(MemoryRegionInfo::eYes);
+            else if (flag == "ss")
+              region->SetIsShadowStack(MemoryRegionInfo::eYes);
         }
-        // Ignore anything else
       } else {
         // Orphaned settings line
         callback(ProcMapError(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index e42526c8fd7266..b3f1c6f052955b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1621,6 +1621,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
           region_info.SetName(name.c_str());
         } else if (name == "flags") {
           region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
+          region_info.SetIsShadowStack(MemoryRegionInfo::eNo);
 
           llvm::StringRef flags = value;
           llvm::StringRef flag;
@@ -1629,10 +1630,10 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
             std::tie(flag, flags) = flags.split(' ');
             // To account for trailing whitespace
             if (flag.size()) {
-              if (flag == "mt") {
+              if (flag == "mt")
                 region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
-                break;
-              }
+              else if (flag == "ss")
+                region_info.SetIsShadowStack(MemoryRegionInfo::eYes);
             }
           }
         } else if (name == "type") {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 35fa93e53bc66f..becc79eb8a07c6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2796,11 +2796,17 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
     // Flags
     MemoryRegionInfo::OptionalBool memory_tagged =
         region_info.GetMemoryTagged();
-    if (memory_tagged != MemoryRegionInfo::eDontKnow) {
+    MemoryRegionInfo::OptionalBool is_shadow_stack =
+        region_info.IsShadowStack();
+
+    if (memory_tagged != MemoryRegionInfo::eDontKnow ||
+        is_shadow_stack != MemoryRegionInfo::eDontKnow) {
       response.PutCString("flags:");
-      if (memory_tagged == MemoryRegionInfo::eYes) {
+      if (memory_tagged == MemoryRegionInfo::eYes)
         response.PutCString("mt");
-      }
+      if (is_shadow_stack == MemoryRegionInfo::eYes)
+        response.PutCString("ss");
+
       response.PutChar(';');
     }
 
diff --git a/lldb/source/Target/MemoryRegionInfo.cpp b/lldb/source/Target/MemoryRegionInfo.cpp
index 0d5ebbdbe23800..979e45ad023af9 100644
--- a/lldb/source/Target/MemoryRegionInfo.cpp
+++ b/lldb/source/Target/MemoryRegionInfo.cpp
@@ -13,12 +13,13 @@ 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})",
+                             "{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.GetBlocksize(), Info.GetMemoryTagged(),
+                             Info.IsStackMemory(), Info.IsShadowStack());
 }
 
 void llvm::format_provider<MemoryRegionInfo::OptionalBool>::format(
diff --git a/lldb/test/API/linux/aarch64/gcs/Makefile b/lldb/test/API/linux/aarch64/gcs/Makefile
new file mode 100644
index 00000000000000..10495940055b63
--- /dev/null
+++ b/lldb/test/API/linux/aarch64/gcs/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py
new file mode 100644
index 00000000000000..b425c9e548ee51
--- /dev/null
+++ b/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py
@@ -0,0 +1,63 @@
+"""
+Check that lldb features work when the AArch64 Guarded Control Stack (GCS)
+extension is enabled.
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class AArch64LinuxGCSTestCase(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessArch("aarch64")
+    @skipUnlessPlatform(["linux"])
+    def test_gcs_region(self):
+        if not self.isAArch64GCS():
+            self.skipTest("Target must support GCS.")
+
+        # This test assumes that we have /proc/<PID>/smaps files
+        # that include "VmFlags:" lines.
+        # AArch64 kernel config defaults to enabling smaps with
+        # PROC_PAGE_MONITOR and "VmFlags" was added in kernel 3.8,
+        # before GCS was supported at all.
+
+        self.build()
+        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
+
+        lldbutil.run_break_set_by_file_and_line(
+            self,
+            "main.c",
+            line_number("main.c", "// Set break point at this line."),
+            num_expected_locations=1,
+        )
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        if self.process().GetState() == lldb.eStateExited:
+            self.fail("Test program failed to run.")
+
+        self.expect(
+            "thread list",
+            STOPPED_DUE_TO_BREAKPOINT,
+            substrs=["stopped", "stop reason = breakpoint"],
+        )
+
+        # By now either the program or the system C library enabled GCS and there
+        # should be one region marked for use by it (we cannot predict exactly
+        # where it will be).
+        self.runCmd("memory region --all")
+        found_ss = False
+        for line in self.res.GetOutput().splitlines():
+            if line.strip() == "shadow stack: yes":
+                if found_ss:
+                    self.fail("Found more than one shadow stack region.")
+                found_ss = True
+
+        self.assertTrue(found_ss, "Failed to find a shadow stack region.")
+
+        # Note that we must let the debugee get killed here as it cannot exit
+        # cleanly if GCS was manually enabled.
diff --git a/lldb/test/API/linux/aarch64/gcs/main.c b/lldb/test/API/linux/aarch64/gcs/main.c
new file mode 100644
index 00000000000000..9633ed2838f9e8
--- /dev/null
+++ b/lldb/test/API/linux/aarch64/gcs/main.c
@@ -0,0 +1,54 @@
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+
+#ifndef HWCAP2_GCS
+#define HWCAP2_GCS (1UL << 63)
+#endif
+
+#define PR_GET_SHADOW_STACK_STATUS 74
+#define PR_SET_SHADOW_STACK_STATUS 75
+#define PR_SHADOW_STACK_ENABLE (1UL)
+#define PRCTL_SYSCALL_NO 167
+
+// Once we enable GCS, we cannot return from the function that made the syscall
+// to enable it. This is because the control stack is empty, there is no valid
+// address for us to return to. So for the initial enable we must use inline asm
+// instead of the libc's prctl wrapper function.
+#define my_prctl(option, arg2, arg3, arg4, arg5)                               \
+  ({                                                                           \
+    register unsigned long x0 __asm__("x0") = option;                          \
+    register unsigned long x1 __asm__("x1") = arg2;                            \
+    register unsigned long x2 __asm__("x2") = arg3;                            \
+    register unsigned long x3 __asm__("x3") = arg4;                            \
+    register unsigned long x4 __asm__("x4") = arg5;                            \
+    register unsigned long x8 __asm__("x8") = PRCTL_SYSCALL_NO;                \
+    __asm__ __volatile__("svc #0\n"                                            \
+                         : "=r"(x0)                                            \
+                         : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4),        \
+                           "r"(x8)                                             \
+                         : "cc", "memory");                                    \
+  })
+
+unsigned long get_gcs_status() {
+  unsigned long mode = 0;
+  prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0);
+  return mode;
+}
+
+int main() {
+  if (!(getauxval(AT_HWCAP2) & HWCAP2_GCS))
+    return 1;
+
+  unsigned long mode = get_gcs_status();
+  if ((mode & 1) == 0) {
+    // If GCS wasn't already enabled by the C library, enable it.
+    my_prctl(PR_SET_SHADOW_STACK_STATUS, PR_SHADOW_STACK_ENABLE, 0, 0, 0);
+    // From this point on, we cannot return from main without faulting because
+    // the return address from main, and every function before that, is not on
+    // the guarded control stack.
+  }
+
+  // By now we should have one memory region where the GCS is stored.
+  return 0; // Set break point at this line.
+}
diff --git a/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp b/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
index ac1c6132630b0b..0f90520411c932 100644
--- a/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
+++ b/lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
@@ -87,12 +87,13 @@ INSTANTIATE_TEST_SUITE_P(
             "0-0 rwzp 00000000 00:00 0\n"
             "2-3 r-xp 00000000 00:00 0 [def]\n",
             MemoryRegionInfos{
-                MemoryRegionInfo(make_range(0, 1), MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eYes, ConstString("[abc]"),
-                                 MemoryRegionInfo::eDontKnow, 0,
-                                 MemoryRegionInfo::eDontKnow,
-                                 MemoryRegionInfo::eDontKnow),
+                MemoryRegionInfo(
+                    make_range(0, 1), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[abc]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
+                    MemoryRegionInfo::eDontKnow),
             },
             "unexpected /proc/{pid}/maps exec permission char"),
         // Single entry
@@ -101,10 +102,10 @@ INSTANTIATE_TEST_SUITE_P(
             MemoryRegionInfos{
                 MemoryRegionInfo(
                     make_range(0x55a4512f7000, 0x55a451b68000),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes,
-                    ConstString("[heap]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eYes, ConstString("[heap]"),
+                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow),
             },
             ""),
@@ -117,24 +118,24 @@ INSTANTIATE_TEST_SUITE_P(
             MemoryRegionInfos{
                 MemoryRegionInfo(
                     make_range(0x7fc090021000, 0x7fc094000000),
-                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes,
-                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eYes, ConstString(nullptr),
+                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow),
                 MemoryRegionInfo(
                     make_range(0x7fc094000000, 0x7fc094a00000),
-                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eYes,
-                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, ConstString(nullptr),
+                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow),
                 MemoryRegionInfo(
                     make_range(0xffffffffff600000, 0xffffffffff601000),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes,
-                    ConstString("[vsyscall]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eYes, ConstString("[vsyscall]"),
+                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow),
             },
             "")));
@@ -157,11 +158,11 @@ INSTANTIATE_TEST_SUITE_P(
             "0/0 rw-p 00000000 00:00 0",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString("[foo]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[foo]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
             },
             "malformed /proc/{pid}/smaps entry, missing dash between address "
@@ -178,11 +179,11 @@ INSTANTIATE_TEST_SUITE_P(
             "1111-2222 rw-p 00000000 00:00 0    [foo]",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString("[foo]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[foo]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
             },
             ""),
@@ -191,11 +192,11 @@ INSTANTIATE_TEST_SUITE_P(
             "1111-2222 rw-s 00000000 00:00 0    [foo]",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eYes, ConstString("[foo]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
+                    ConstString("[foo]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
             },
             ""),
@@ -207,12 +208,12 @@ INSTANTIATE_TEST_SUITE_P(
             "VmFlags: mt",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString("[foo]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eDontKnow),
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[foo]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eDontKnow,
+                    MemoryRegionInfo::eNo),
             },
             ""),
         // Whitespace ignored
@@ -220,13 +221,13 @@ INSTANTIATE_TEST_SUITE_P(
             "0-0 rw-p 00000000 00:00 0\n"
             "VmFlags:      mt      ",
             MemoryRegionInfos{
-                MemoryRegionInfo(make_range(0, 0),
-                                 MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eYes, ConstString(nullptr),
-                                 MemoryRegionInfo::eDontKnow, 0,
-                                 MemoryRegionInfo::eYes,
-                                 MemoryRegionInfo::eDontKnow),
+                MemoryRegionInfo(
+                    make_range(0, 0), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eDontKnow,
+                    MemoryRegionInfo::eNo),
             },
             ""),
         // VmFlags line means it has flag info, but nothing is set
@@ -234,13 +235,13 @@ INSTANTIATE_TEST_SUITE_P(
             "0-0 rw-p 00000000 00:00 0\n"
             "VmFlags:         ",
             MemoryRegionInfos{
-                MemoryRegionInfo(make_range(0, 0),
-                                 MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eYes, ConstString(nullptr),
-                                 MemoryRegionInfo::eDontKnow, 0,
-                                 MemoryRegionInfo::eNo,
-                                 MemoryRegionInfo::eDontKnow),
+                MemoryRegionInfo(
+                    make_range(0, 0), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eDontKnow,
+                    MemoryRegionInfo::eNo),
             },
             ""),
         // Handle some pages not having a flags line
@@ -252,18 +253,19 @@ INSTANTIATE_TEST_SUITE_P(
             "VmFlags: mt",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString("[foo]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[foo]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
                 MemoryRegionInfo(
-                    make_range(0x3333, 0x4444), MemoryRegionInfo::eYes, MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString("[bar]"),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eDontKnow),
+                    make_range(0x3333, 0x4444), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString("[bar]"), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eDontKnow,
+                    MemoryRegionInfo::eNo),
             },
             ""),
         // Handle no pages having a flags line (older kernels)
@@ -276,18 +278,18 @@ INSTANTIATE_TEST_SUITE_P(
             "MMUPageSize:           4 kB\n",
             MemoryRegionInfos{
                 MemoryRegionInfo(
-                    make_range(0x1111, 0x2222),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString(nullptr),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
                 MemoryRegionInfo(
-                    make_range(0x3333, 0x4444),
-                    MemoryRegionInfo::eYes, MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
-                    MemoryRegionInfo::eNo,
-                    MemoryRegionInfo::eYes, ConstString(nullptr),
-                    MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eDontKnow,
+                    make_range(0x3333, 0x4444), MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
+                    ConstString(nullptr), MemoryRegionInfo::eDontKnow, 0,
+                    MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow,
                     MemoryRegionInfo::eDontKnow),
             },
             "")));
diff --git a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
index 6d8b699bbadae8..40d7c3601ccfda 100644
--- a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
+++ b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
@@ -200,14 +200,12 @@ TEST(MemoryTagManagerAArch64MTETest, ExpandToGranule) {
 static MemoryRegionInfo MakeRegionInfo(lldb::addr_t base, lldb::addr_t size,
                                        bool tagged) {
   return MemoryRegionInfo(
-      MemoryRegionInfo::RangeType(base, size),
-      MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
-      MemoryRegionInfo::eNo,
-      MemoryRegionInfo::eYes,
-      ConstString(), MemoryRegionInfo::eNo, 0,
+      MemoryRegionInfo::RangeType(base, size), MemoryRegionInfo::eYes,
+      MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
+      MemoryRegionInfo::eYes, ConstString(), MemoryRegionInfo::eNo, 0,
       /*memory_tagged=*/
       tagged ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo,
-      MemoryRegionInfo::eDontKnow);
+      MemoryRegionInfo::eDontKnow, MemoryRegionInfo::eDontKnow);
 }
 
 TEST(MemoryTagManagerAArch64MTETest, MakeTaggedRange) {
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index ce5ab2cf508293..96f377ec7dfac8 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -344,6 +344,7 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
   EXPECT_EQ("/foo/bar.so", region_info.GetName().GetStringRef());
   EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.GetMemoryTagged());
   EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsStackMemory());
+  EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
@@ -354,16 +355,18 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
   EXPECT_TRUE(result.get().Success());
   EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetMemoryTagged());
   EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
+  EXPECT_EQ(MemoryRegionInfo::eNo, region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
   });
 
   HandlePacket(server, "qMemoryRegionInfo:a000",
-               "start:a000;size:2000;flags: mt  zz mt  ;type:ha,ha,stack;");
+               "start:a000;size:2000;flags: mt  zz mt ss  ;type:ha,ha,stack;");
   EXPECT_TRUE(result.get().Success());
   EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetMemoryTagged());
   EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
+  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
diff --git a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
index a6d015e79a7ef2..ee31c8e63644b9 100644
--- a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
+++ b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
@@ -379,19 +379,23 @@ TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
 
   EXPECT_THAT(
       parser->BuildMemoryRegions(),
-      testing::Pair(
-          testing::ElementsAre(
-              MemoryRegionInfo({0x0, 0x10000}, no, no, no, unknown, no, ConstString(),
-                               unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x10000, 0x21000}, yes, yes, no, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x40000, 0x1000}, yes, no, no, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x7ffe0000, 0x1000}, yes, no, no, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x7ffe1000, 0xf000}, no, no, no, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown)),
-          true));
+      testing::Pair(testing::ElementsAre(
+                        MemoryRegionInfo({0x0, 0x10000}, no, no, no, unknown,
+                                         no, ConstString(), unknown, 0, unknown,
+                                         unknown, unknown),
+                        MemoryRegionInfo({0x10000, 0x21000}, yes, yes, no,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown),
+                        MemoryRegionInfo({0x40000, 0x1000}, yes, no, no,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown),
+                        MemoryRegionInfo({0x7ffe0000, 0x1000}, yes, no, no,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown),
+                        MemoryRegionInfo({0x7ffe1000, 0xf000}, no, no, no,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown)),
+                    true));
 }
 
 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
@@ -413,13 +417,14 @@ TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
 
   EXPECT_THAT(
       parser->BuildMemoryRegions(),
-      testing::Pair(
-          testing::ElementsAre(
-              MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown)),
-          false));
+      testing::Pair(testing::ElementsAre(
+                        MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown),
+                        MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown)),
+                    false));
 }
 
 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
@@ -429,13 +434,14 @@ TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
   // we don't have a MemoryInfoListStream.
   EXPECT_THAT(
       parser->BuildMemoryRegions(),
-      testing::Pair(
-          testing::ElementsAre(
-              MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown, unknown, yes,
-                               ConstString(), unknown, 0, unknown, unknown)),
-          false));
+      testing::Pair(testing::ElementsAre(
+                        MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown),
+                        MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,
+                                         unknown, yes, ConstString(), unknown,
+                                         0, unknown, unknown, unknown)),
+                    false));
 }
 
 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
@@ -464,17 +470,21 @@ TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
       testing::Pair(
           testing::ElementsAre(
               MemoryRegionInfo({0x400d9000, 0x2000}, yes, no, yes, no, yes,
-                               app_process, unknown, 0, unknown, unknown),
+                               app_process, unknown, 0, unknown, unknown,
+                               unknown),
               MemoryRegionInfo({0x400db000, 0x1000}, yes, no, no, no, yes,
-                               app_process, unknown, 0, unknown, unknown),
+                               app_process, unknown, 0, unknown, unknown,
+                               unknown),
               MemoryRegionInfo({0x400dc000, 0x1000}, yes, yes, no, no, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
+                               ConstString(), unknown, 0, unknown, unknown,
+                               unknown),
               MemoryRegionInfo({0x400ec000, 0x1000}, yes, no, no, no, yes,
-                               ConstString(), unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x400ee000, 0x1000}, yes, yes, no, no, yes, linker,
-                               unknown, 0, unknown, unknown),
-              MemoryRegionInfo({0x400fc000, 0x1000}, yes, yes, yes, no, yes, liblog,
-                               unknown, 0, unknown, unknown)),
+                               ConstString(), unknown, 0, unknown, unknown,
+                               unknown),
+              MemoryRegionInfo({0x400ee000, 0x1000}, yes, yes, no, no, yes,
+                               linker, unknown, 0, unknown, unknown, unknown),
+              MemoryRegionInfo({0x400fc000, 0x1000}, yes, yes, yes, no, yes,
+                               liblog, unknown, 0, unknown, unknown, unknown)),
           true));
 }
 
@@ -491,12 +501,12 @@ TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMapsError) {
                     llvm::Succeeded());
   // Test that when a /proc/maps region fails to parse
   // we handle the error and continue with the rest.
-  EXPECT_THAT(
-      parser->BuildMemoryRegions(),
-      testing::Pair(testing::ElementsAre(MemoryRegionInfo(
-                        {0x400fc000, 0x1000}, yes, yes, yes, no, yes,
-                        ConstString(nullptr), unknown, 0, unknown, unknown)),
-                    true));
+  EXPECT_THAT(parser->BuildMemoryRegions(),
+              testing::Pair(testing::ElementsAre(MemoryRegionInfo(
+                                {0x400fc000, 0x1000}, yes, yes, yes, no, yes,
+                                ConstString(nullptr), unknown, 0, unknown,
+                                unknown, unknown)),
+                            true));
 }
 
 // Windows Minidump tests



More information about the lldb-commits mailing list