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