import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil @skipUnlessDarwin @skipIf(archs=no_match(["arm64"])) class TestArmPointerMetadataStripping(TestBase): def test(self): self.build() target, process, thread, bkpt = lldbutil.run_to_name_breakpoint(self, "foo") # Step over the first two instructions of foo in order to # toggle the bit of fp and save it on the stack: # orr x29, x29, #0x1000000000000000 # stp x29, x30, [sp, #-16]! # This is effectively adding metadata to the CFA of the caller frame (main). thread.StepInstruction(False) thread.StepInstruction(False) # The location of `argv` has been artificially made equal to the CFA of the frame. # As such, it should have the metadata artificially set previously. argv_addr = thread.frames[1].GetValueForVariablePath("&argv") self.assertTrue(argv_addr.IsValid()) argv_addr_uint = argv_addr.GetValueAsUnsigned() self.assertNotEqual((argv_addr_uint & (1 << 60)), 0) # GetCFA strips metadata. cfa = thread.frames[1].GetCFA() self.assertEqual((cfa & (1 << 60)), 0) # If the test worked correctly, the cfa and the location should be identical, # modulo the metadata. self.assertEqual(cfa | (1 << 60), argv_addr_uint)