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

via lldb-commits lldb-commits at lists.llvm.org
Tue Jan 14 07:19:26 PST 2025


Author: David Spickett
Date: 2025-01-14T15:19:22Z
New Revision: b1751faada35e3456b2a3f6b6c9559b5d74d559b

URL: https://github.com/llvm/llvm-project/commit/b1751faada35e3456b2a3f6b6c9559b5d74d559b
DIFF: https://github.com/llvm/llvm-project/commit/b1751faada35e3456b2a3f6b6c9559b5d74d559b.diff

LOG: [lldb][Linux] Mark memory regions used for shadow stacks (#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.

Added: 
    lldb/test/API/linux/aarch64/gcs/Makefile
    lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py
    lldb/test/API/linux/aarch64/gcs/main.c

Modified: 
    lldb/include/lldb/Target/MemoryRegionInfo.h
    lldb/packages/Python/lldbsuite/test/lldbtest.py
    lldb/source/Commands/CommandObjectMemory.cpp
    lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/source/Target/MemoryRegionInfo.cpp
    lldb/unittests/Process/Utility/LinuxProcMapsTest.cpp
    lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
    lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
    lldb/unittests/Process/minidump/MinidumpParserTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h
index 7e1385b210b8c6..dc37a7dbeda52a 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -29,11 +29,11 @@ class MemoryRegionInfo {
                    OptionalBool execute, OptionalBool shared,
                    OptionalBool mapped, ConstString name, OptionalBool flash,
                    lldb::offset_t blocksize, OptionalBool memory_tagged,
-                   OptionalBool stack_memory)
+                   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 {
@@ -106,7 +110,8 @@ class MemoryRegionInfo {
            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 6ff8e17030b10b..81b286340560dc 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1364,6 +1364,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 164c61d1720171..f2fa5391f8f338 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..8cdeaac5c7cb28 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2796,11 +2796,18 @@ 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) {
-        response.PutCString("mt");
-      }
+      // Space is the separator.
+      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..d94bb4f4db982c 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,20 +278,35 @@ 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),
             },
+            ""),
+        // We must look for exact flag strings, ignoring substrings of longer
+        // flag names.
+        std::make_tuple(
+            "0-0 rw-p 00000000 00:00 0\n"
+            "VmFlags: amt mtb amtb",
+            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::eNo),
+            },
             "")));
 
 TEST_P(LinuxProcSMapsTestFixture, ParseSMapRegions) {

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