DavidSpickett created this revision. Herald added subscribers: atanasyan, arichardson, sdardis. Herald added a project: All. DavidSpickett requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
This allows you to break on the value of a function pointer with non-address bits in it. For example your ABI might mandate function pointer signing. Previously it would either try to write to an address that was incorrect, or try to set a hardware register incorrectly. I have placed the ABI check before GetBreakableLoadAddress on the logic that that function probably works best with a fixed address. This is somewhat academic because the only user of GetBreakableLoadAddress is MIPS where we don't support any form of address tagging. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D136938 Files: lldb/source/Target/Target.cpp lldb/test/API/linux/aarch64/tagged_code_break/Makefile lldb/test/API/linux/aarch64/tagged_code_break/TestAArch64LinuxTaggedCodeBreak.py lldb/test/API/linux/aarch64/tagged_code_break/main.c
Index: lldb/test/API/linux/aarch64/tagged_code_break/main.c =================================================================== --- /dev/null +++ lldb/test/API/linux/aarch64/tagged_code_break/main.c @@ -0,0 +1,18 @@ +#include <stdint.h> + +void foo(void) {} +typedef void (*FooPtr)(void); + +int main() { + FooPtr fnptr = foo; + // Set top byte. + fnptr = (FooPtr)((uintptr_t)fnptr | (uintptr_t)0xff << 56); + // Then apply a PAuth signature to it. + __asm__ __volatile__("pacdza %0" : "=r"(fnptr) : "r"(fnptr)); + // fnptr is now: + // <8 bit top byte tag><pointer signature><virtual address> + + foo(); // Set break point at this line. + + return 0; +} Index: lldb/test/API/linux/aarch64/tagged_code_break/TestAArch64LinuxTaggedCodeBreak.py =================================================================== --- /dev/null +++ lldb/test/API/linux/aarch64/tagged_code_break/TestAArch64LinuxTaggedCodeBreak.py @@ -0,0 +1,57 @@ +""" +Test that "breakpoint set -a" uses the ABI plugin to remove non-address bits +before attempting to set a breakpoint. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxTaggedCodeBreak(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + def do_tagged_break(self, hardware): + if not self.isAArch64PAuth(): + self.skipTest('Target must support pointer authentication.') + + 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']) + + cmd = "breakpoint set -a fnptr" + # LLDB only has the option to force hardware break, not software. + # It prefers sofware break when it can and this will be one of those cases. + if hardware: + cmd += " --hardware" + self.expect(cmd) + + self.runCmd("continue") + self.assertEqual(self.process().GetState(), lldb.eStateStopped) + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', '`foo at main.c', 'stop reason = breakpoint']) + + # AArch64 Linux always enables the top byte ignore feature + @skipUnlessArch("aarch64") + @skipUnlessPlatform(["linux"]) + def test_software_break(self): + self.do_tagged_break(False) + + @skipUnlessArch("aarch64") + @skipUnlessPlatform(["linux"]) + def test_hardware_break(self): + self.do_tagged_break(True) \ No newline at end of file Index: lldb/test/API/linux/aarch64/tagged_code_break/Makefile =================================================================== --- /dev/null +++ lldb/test/API/linux/aarch64/tagged_code_break/Makefile @@ -0,0 +1,5 @@ +C_SOURCES := main.c + +CFLAGS_EXTRAS := -march=armv8.3-a + +include Makefile.rules Index: lldb/source/Target/Target.cpp =================================================================== --- lldb/source/Target/Target.cpp +++ lldb/source/Target/Target.cpp @@ -2626,8 +2626,14 @@ } lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) { - auto arch_plugin = GetArchitecturePlugin(); - return arch_plugin ? arch_plugin->GetBreakableLoadAddress(addr, *this) : addr; + lldb::ABISP abi_plugin = m_process_sp ? m_process_sp->GetABI() : nullptr; + if (abi_plugin) + addr = abi_plugin->FixCodeAddress(addr); + + if (auto arch_plugin = GetArchitecturePlugin()) + addr = arch_plugin->GetBreakableLoadAddress(addr, *this); + + return addr; } SourceManager &Target::GetSourceManager() {
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits