omjavaid created this revision.
omjavaid added reviewers: labath, DavidSpickett.
Herald added subscribers: danielkiss, kristof.beyls.
omjavaid requested review of this revision.

This patch adds support to detect and set address bits in use by the current
AArch64 process. We are going to utilize AArch64SVEReconfigure function
for this purpose which was added to GDBRemoteRegisterContext for
supporting vector length update of SVE registers. This function gets called
on every stop to check for vector length changes and will serve as the
configuration area for address bits in use on first stop.

Default value of used address bits will be set to 52 which is maximum
possible AArch64 virtual address width. Addition logic has been added to
AArch64SVEReconfigure to detect pointer authentication feature for the
current process. If PAC is enabled, address bits in use are configured based on
PAC code/data mask.

This patch also includes a test case to demonstrate successful backtrace
calculation in presence of pointer authentication feature.


https://reviews.llvm.org/D99947

Files:
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
  lldb/test/API/functionalities/unwind/aarch64_unwind_pac/Makefile
  
lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
  lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c

Index: lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+
+static void func_a (void) __attribute__((noinline));
+static void func_b (void) __attribute__((noinline));
+static void func_c (void) __attribute__((noinline));
+
+static void
+func_c (void)
+{
+  exit (0); // Frame func_c
+}
+
+static void
+func_b (void)
+{
+  func_c (); // Frame func_b
+}
+
+static void
+func_a (void)
+{
+  func_b (); // Frame func_a
+}
+
+int
+main (int argc, char *argv[])
+{
+  func_a (); // Frame main
+  return 0;
+}
Index: lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
@@ -0,0 +1,42 @@
+"""
+Test that we can backtrace correctly when AArch64 PAC is enabled
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class AArch64UnwindPAC(TestBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIf(archs=no_match(["aarch64"]))
+    @skipIf(oslist=no_match(['linux']))
+    def test(self):
+        """Test that we can backtrace correctly when AArch64 PAC is enabled"""
+        self.build()
+
+        self.line = line_number('main.c', '// Frame func_c')
+
+        exe = self.getBuildArtifact("a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        lldbutil.run_break_set_by_file_and_line(
+            self, "main.c", self.line, num_expected_locations=1)
+        self.runCmd("run", RUN_SUCCEEDED)
+        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
+                    substrs=["stop reason = breakpoint 1."])
+
+        target = self.dbg.GetSelectedTarget()
+        process = target.GetProcess()
+        thread = process.GetThreadAtIndex(0)
+
+        backtrace = ["func_c", "func_b", "func_a", "main"]
+        self.assertEqual(thread.GetNumFrames(), len(backtrace))
+        for i in range(len(backtrace)):
+            frame = thread.GetFrameAtIndex(i)
+            self.assertTrue(frame)
+            self.assertEqual(frame.GetFunctionName(), backtrace[i])
+            self.assertEqual(frame.GetLineEntry().GetLine(),
+                                 line_number("main.c", "Frame " + backtrace[i]))
Index: lldb/test/API/functionalities/unwind/aarch64_unwind_pac/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/unwind/aarch64_unwind_pac/Makefile
@@ -0,0 +1,5 @@
+C_SOURCES := main.c
+
+CFLAGS ?= -g -Os -march=armv8.5-a -mbranch-protection=pac-ret+leaf
+
+include Makefile.rules
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -739,6 +739,40 @@
   if (!m_reg_info_sp)
     return false;
 
+  // In addition to SVE vector length configuration we will use this function
+  // to configure no of address bits being used by the process for addressing.
+  // Default value will be set to 52 which is maximum possible AArch64 virtual
+  // address width.
+  // Code below tries to detect pointer authentication feature for the current
+  // process. If PAC is enabled, address bits in use are configured based on
+  // PAC code/data mask.
+  if (!GetThread().GetProcess()->GetAddressBitsInUse()) {
+    uint32_t address_bits_in_use = 52;
+    const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("code_mask");
+    if (reg_info) {
+      uint64_t fail_value = LLDB_INVALID_ADDRESS;
+      uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
+      uint64_t cmask_reg_value = ReadRegisterAsUnsigned(reg_num, fail_value);
+      if ((cmask_reg_value != fail_value) &&
+          (cmask_reg_value & ((uint64_t)1 << 48)))
+        address_bits_in_use = 48;
+      else {
+        const RegisterInfo *reg_info =
+            m_reg_info_sp->GetRegisterInfo("data_mask");
+        if (reg_info) {
+          fail_value = LLDB_INVALID_ADDRESS;
+          reg_num = reg_info->kinds[eRegisterKindLLDB];
+          uint64_t dmask_reg_value =
+              ReadRegisterAsUnsigned(reg_num, fail_value);
+          if ((dmask_reg_value != fail_value) &&
+              (dmask_reg_value & ((uint64_t)1 << 48)))
+            address_bits_in_use = 48;
+        }
+      }
+    }
+    GetThread().GetProcess()->SetAddressBitsInUse(address_bits_in_use);
+  }
+
   const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg");
   if (!reg_info)
     return false;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PAT... Muhammad Omair Javaid via Phabricator via lldb-commits

Reply via email to