1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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)
|