1""" 2Test that ASan memory history provider returns correct stack traces 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbplatform 11from lldbsuite.test import lldbutil 12 13 14class AsanTestCase(TestBase): 15 16 mydir = TestBase.compute_mydir(__file__) 17 18 @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default 19 @expectedFailureNetBSD 20 @skipUnlessAddressSanitizer 21 def test(self): 22 self.build() 23 self.asan_tests() 24 25 def setUp(self): 26 # Call super's setUp(). 27 TestBase.setUp(self) 28 self.line_malloc = line_number('main.c', '// malloc line') 29 self.line_malloc2 = line_number('main.c', '// malloc2 line') 30 self.line_free = line_number('main.c', '// free line') 31 self.line_breakpoint = line_number('main.c', '// break line') 32 33 def asan_tests(self): 34 exe = self.getBuildArtifact("a.out") 35 target = self.dbg.CreateTarget(exe) 36 self.assertTrue(target, VALID_TARGET) 37 38 self.registerSanitizerLibrariesWithTarget(target) 39 40 self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) 41 42 # "memory history" command should not work without a process 43 self.expect("memory history 0", 44 error=True, 45 substrs=["invalid process"]) 46 47 self.runCmd("run") 48 49 stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() 50 if stop_reason == lldb.eStopReasonExec: 51 # On OS X 10.10 and older, we need to re-exec to enable 52 # interceptors. 53 self.runCmd("continue") 54 55 # the stop reason of the thread should be breakpoint. 56 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 57 substrs=['stopped', 'stop reason = breakpoint']) 58 59 # test that the ASan dylib is present 60 self.expect( 61 "image lookup -n __asan_describe_address", 62 "__asan_describe_address should be present", 63 substrs=['1 match found']) 64 65 # test the 'memory history' command 66 self.expect( 67 "memory history 'pointer'", 68 substrs=[ 69 'Memory deallocated by Thread', 70 'a.out`f2', 71 'main.c:%d' % self.line_free, 72 'Memory allocated by Thread', 73 'a.out`f1', 74 'main.c:%d' % self.line_malloc, 75 ]) 76 77 # do the same using SB API 78 process = self.dbg.GetSelectedTarget().process 79 val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") 80 addr = val.GetValueAsUnsigned() 81 threads = process.GetHistoryThreads(addr) 82 self.assertEqual(threads.GetSize(), 2) 83 84 history_thread = threads.GetThreadAtIndex(0) 85 self.assertTrue(history_thread.num_frames >= 2) 86 self.assertEqual(history_thread.frames[1].GetLineEntry( 87 ).GetFileSpec().GetFilename(), "main.c") 88 self.assertEqual( 89 history_thread.frames[1].GetLineEntry().GetLine(), 90 self.line_free) 91 92 history_thread = threads.GetThreadAtIndex(1) 93 self.assertTrue(history_thread.num_frames >= 2) 94 self.assertEqual(history_thread.frames[1].GetLineEntry( 95 ).GetFileSpec().GetFilename(), "main.c") 96 self.assertEqual( 97 history_thread.frames[1].GetLineEntry().GetLine(), 98 self.line_malloc) 99 100 # let's free the container (SBThreadCollection) and see if the 101 # SBThreads still live 102 threads = None 103 self.assertTrue(history_thread.num_frames >= 2) 104 self.assertEqual(history_thread.frames[1].GetLineEntry( 105 ).GetFileSpec().GetFilename(), "main.c") 106 self.assertEqual( 107 history_thread.frames[1].GetLineEntry().GetLine(), 108 self.line_malloc) 109 110 # ASan will break when a report occurs and we'll try the API then 111 self.runCmd("continue") 112 113 self.expect( 114 "thread list", 115 "Process should be stopped due to ASan report", 116 substrs=[ 117 'stopped', 118 'stop reason = Use of deallocated memory']) 119 120 # make sure the 'memory history' command still works even when we're 121 # generating a report now 122 self.expect( 123 "memory history 'another_pointer'", 124 substrs=[ 125 'Memory allocated by Thread', 126 'a.out`f1', 127 'main.c:%d' % 128 self.line_malloc2]) 129