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 target = self.createTestTarget() 35 36 self.registerSanitizerLibrariesWithTarget(target) 37 38 self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) 39 40 # "memory history" command should not work without a process 41 self.expect("memory history 0", 42 error=True, 43 substrs=["invalid process"]) 44 45 self.runCmd("run") 46 47 stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() 48 if stop_reason == lldb.eStopReasonExec: 49 # On OS X 10.10 and older, we need to re-exec to enable 50 # interceptors. 51 self.runCmd("continue") 52 53 # the stop reason of the thread should be breakpoint. 54 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 55 substrs=['stopped', 'stop reason = breakpoint']) 56 57 # test that the ASan dylib is present 58 self.expect( 59 "image lookup -n __asan_describe_address", 60 "__asan_describe_address should be present", 61 substrs=['1 match found']) 62 63 # test the 'memory history' command 64 self.expect( 65 "memory history 'pointer'", 66 substrs=[ 67 'Memory deallocated by Thread', 68 'a.out`f2', 69 'main.c:%d' % self.line_free, 70 'Memory allocated by Thread', 71 'a.out`f1', 72 'main.c:%d' % self.line_malloc, 73 ]) 74 75 # do the same using SB API 76 process = self.dbg.GetSelectedTarget().process 77 val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") 78 addr = val.GetValueAsUnsigned() 79 threads = process.GetHistoryThreads(addr) 80 self.assertEqual(threads.GetSize(), 2) 81 82 history_thread = threads.GetThreadAtIndex(0) 83 self.assertTrue(history_thread.num_frames >= 2) 84 self.assertEqual(history_thread.frames[1].GetLineEntry( 85 ).GetFileSpec().GetFilename(), "main.c") 86 self.assertEqual( 87 history_thread.frames[1].GetLineEntry().GetLine(), 88 self.line_free) 89 90 history_thread = threads.GetThreadAtIndex(1) 91 self.assertTrue(history_thread.num_frames >= 2) 92 self.assertEqual(history_thread.frames[1].GetLineEntry( 93 ).GetFileSpec().GetFilename(), "main.c") 94 self.assertEqual( 95 history_thread.frames[1].GetLineEntry().GetLine(), 96 self.line_malloc) 97 98 # let's free the container (SBThreadCollection) and see if the 99 # SBThreads still live 100 threads = None 101 self.assertTrue(history_thread.num_frames >= 2) 102 self.assertEqual(history_thread.frames[1].GetLineEntry( 103 ).GetFileSpec().GetFilename(), "main.c") 104 self.assertEqual( 105 history_thread.frames[1].GetLineEntry().GetLine(), 106 self.line_malloc) 107 108 # ASan will break when a report occurs and we'll try the API then 109 self.runCmd("continue") 110 111 self.expect( 112 "thread list", 113 "Process should be stopped due to ASan report", 114 substrs=[ 115 'stopped', 116 'stop reason = Use of deallocated memory']) 117 118 # make sure the 'memory history' command still works even when we're 119 # generating a report now 120 self.expect( 121 "memory history 'another_pointer'", 122 substrs=[ 123 'Memory allocated by Thread', 124 'a.out`f1', 125 'main.c:%d' % 126 self.line_malloc2]) 127