199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest that ASan memory history provider returns correct stack traces 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprecht 699451b44SJordan Rupprechtimport lldb 799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 999451b44SJordan Rupprechtfrom lldbsuite.test import lldbplatform 1099451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 11*988ffd06SUsama Hameedfrom lldbsuite.test_event.build_exception import BuildError 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprechtclass AsanTestCase(TestBase): 1499451b44SJordan Rupprecht @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default 1599451b44SJordan Rupprecht @expectedFailureNetBSD 1699451b44SJordan Rupprecht @skipUnlessAddressSanitizer 1799451b44SJordan Rupprecht def test(self): 18*988ffd06SUsama Hameed self.build(make_targets=["asan"]) 1999451b44SJordan Rupprecht self.asan_tests() 2099451b44SJordan Rupprecht 21*988ffd06SUsama Hameed @skipIf(oslist=no_match(["macosx"])) 22*988ffd06SUsama Hameed def test_libsanitizers_asan(self): 23*988ffd06SUsama Hameed try: 24*988ffd06SUsama Hameed self.build(make_targets=["libsanitizers"]) 25*988ffd06SUsama Hameed except BuildError as e: 26*988ffd06SUsama Hameed self.skipTest("failed to build with libsanitizers") 27*988ffd06SUsama Hameed self.libsanitizer_tests() 28*988ffd06SUsama Hameed 2999451b44SJordan Rupprecht def setUp(self): 3099451b44SJordan Rupprecht # Call super's setUp(). 3199451b44SJordan Rupprecht TestBase.setUp(self) 322238dcc3SJonas Devlieghere self.line_malloc = line_number("main.c", "// malloc line") 332238dcc3SJonas Devlieghere self.line_malloc2 = line_number("main.c", "// malloc2 line") 342238dcc3SJonas Devlieghere self.line_free = line_number("main.c", "// free line") 352238dcc3SJonas Devlieghere self.line_breakpoint = line_number("main.c", "// break line") 3699451b44SJordan Rupprecht 37*988ffd06SUsama Hameed # Test line numbers: rdar://126237493 38*988ffd06SUsama Hameed def libsanitizer_tests(self): 39*988ffd06SUsama Hameed target = self.createTestTarget() 40*988ffd06SUsama Hameed 41*988ffd06SUsama Hameed self.runCmd( 42*988ffd06SUsama Hameed "env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0" 43*988ffd06SUsama Hameed ) 44*988ffd06SUsama Hameed 45*988ffd06SUsama Hameed self.runCmd("run") 46*988ffd06SUsama Hameed 47*988ffd06SUsama Hameed # In libsanitizers, memory history is not supported until a report has been generated 48*988ffd06SUsama Hameed self.expect( 49*988ffd06SUsama Hameed "thread list", 50*988ffd06SUsama Hameed "Process should be stopped due to ASan report", 51*988ffd06SUsama Hameed substrs=["stopped", "stop reason = Use of deallocated memory"], 52*988ffd06SUsama Hameed ) 53*988ffd06SUsama Hameed 54*988ffd06SUsama Hameed # test the 'memory history' command 55*988ffd06SUsama Hameed self.expect( 56*988ffd06SUsama Hameed "memory history 'pointer'", 57*988ffd06SUsama Hameed substrs=[ 58*988ffd06SUsama Hameed "Memory deallocated by Thread", 59*988ffd06SUsama Hameed "a.out`f2", 60*988ffd06SUsama Hameed "main.c", 61*988ffd06SUsama Hameed "Memory allocated by Thread", 62*988ffd06SUsama Hameed "a.out`f1", 63*988ffd06SUsama Hameed "main.c", 64*988ffd06SUsama Hameed ], 65*988ffd06SUsama Hameed ) 66*988ffd06SUsama Hameed 67*988ffd06SUsama Hameed # do the same using SB API 68*988ffd06SUsama Hameed process = self.dbg.GetSelectedTarget().process 69*988ffd06SUsama Hameed val = ( 70*988ffd06SUsama Hameed process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") 71*988ffd06SUsama Hameed ) 72*988ffd06SUsama Hameed addr = val.GetValueAsUnsigned() 73*988ffd06SUsama Hameed threads = process.GetHistoryThreads(addr) 74*988ffd06SUsama Hameed self.assertEqual(threads.GetSize(), 2) 75*988ffd06SUsama Hameed 76*988ffd06SUsama Hameed history_thread = threads.GetThreadAtIndex(0) 77*988ffd06SUsama Hameed self.assertTrue(history_thread.num_frames >= 2) 78*988ffd06SUsama Hameed self.assertEqual( 79*988ffd06SUsama Hameed history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 80*988ffd06SUsama Hameed "main.c", 81*988ffd06SUsama Hameed ) 82*988ffd06SUsama Hameed 83*988ffd06SUsama Hameed history_thread = threads.GetThreadAtIndex(1) 84*988ffd06SUsama Hameed self.assertTrue(history_thread.num_frames >= 2) 85*988ffd06SUsama Hameed self.assertEqual( 86*988ffd06SUsama Hameed history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 87*988ffd06SUsama Hameed "main.c", 88*988ffd06SUsama Hameed ) 89*988ffd06SUsama Hameed 90*988ffd06SUsama Hameed # let's free the container (SBThreadCollection) and see if the 91*988ffd06SUsama Hameed # SBThreads still live 92*988ffd06SUsama Hameed threads = None 93*988ffd06SUsama Hameed self.assertTrue(history_thread.num_frames >= 2) 94*988ffd06SUsama Hameed self.assertEqual( 95*988ffd06SUsama Hameed history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 96*988ffd06SUsama Hameed "main.c", 97*988ffd06SUsama Hameed ) 98*988ffd06SUsama Hameed 9999451b44SJordan Rupprecht def asan_tests(self): 10054c26872SRaphael Isemann target = self.createTestTarget() 10199451b44SJordan Rupprecht 10299451b44SJordan Rupprecht self.registerSanitizerLibrariesWithTarget(target) 10399451b44SJordan Rupprecht 10499451b44SJordan Rupprecht self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) 10599451b44SJordan Rupprecht 10699451b44SJordan Rupprecht # "memory history" command should not work without a process 1072238dcc3SJonas Devlieghere self.expect( 1082238dcc3SJonas Devlieghere "memory history 0", 10999451b44SJordan Rupprecht error=True, 1102238dcc3SJonas Devlieghere substrs=["Command requires a current process"], 1112238dcc3SJonas Devlieghere ) 11299451b44SJordan Rupprecht 11399451b44SJordan Rupprecht self.runCmd("run") 11499451b44SJordan Rupprecht 1152238dcc3SJonas Devlieghere stop_reason = ( 1162238dcc3SJonas Devlieghere self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() 1172238dcc3SJonas Devlieghere ) 11899451b44SJordan Rupprecht if stop_reason == lldb.eStopReasonExec: 11999451b44SJordan Rupprecht # On OS X 10.10 and older, we need to re-exec to enable 12099451b44SJordan Rupprecht # interceptors. 12199451b44SJordan Rupprecht self.runCmd("continue") 12299451b44SJordan Rupprecht 12399451b44SJordan Rupprecht # the stop reason of the thread should be breakpoint. 1242238dcc3SJonas Devlieghere self.expect( 1252238dcc3SJonas Devlieghere "thread list", 1262238dcc3SJonas Devlieghere STOPPED_DUE_TO_BREAKPOINT, 1272238dcc3SJonas Devlieghere substrs=["stopped", "stop reason = breakpoint"], 1282238dcc3SJonas Devlieghere ) 12999451b44SJordan Rupprecht 13099451b44SJordan Rupprecht # test that the ASan dylib is present 13199451b44SJordan Rupprecht self.expect( 13299451b44SJordan Rupprecht "image lookup -n __asan_describe_address", 13399451b44SJordan Rupprecht "__asan_describe_address should be present", 1342238dcc3SJonas Devlieghere substrs=["1 match found"], 1352238dcc3SJonas Devlieghere ) 13699451b44SJordan Rupprecht 13799451b44SJordan Rupprecht # test the 'memory history' command 13899451b44SJordan Rupprecht self.expect( 13999451b44SJordan Rupprecht "memory history 'pointer'", 14099451b44SJordan Rupprecht substrs=[ 1412238dcc3SJonas Devlieghere "Memory deallocated by Thread", 1422238dcc3SJonas Devlieghere "a.out`f2", 1432238dcc3SJonas Devlieghere "main.c:%d" % self.line_free, 1442238dcc3SJonas Devlieghere "Memory allocated by Thread", 1452238dcc3SJonas Devlieghere "a.out`f1", 1462238dcc3SJonas Devlieghere "main.c:%d" % self.line_malloc, 1472238dcc3SJonas Devlieghere ], 1482238dcc3SJonas Devlieghere ) 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht # do the same using SB API 15199451b44SJordan Rupprecht process = self.dbg.GetSelectedTarget().process 1522238dcc3SJonas Devlieghere val = ( 1532238dcc3SJonas Devlieghere process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer") 1542238dcc3SJonas Devlieghere ) 15599451b44SJordan Rupprecht addr = val.GetValueAsUnsigned() 15699451b44SJordan Rupprecht threads = process.GetHistoryThreads(addr) 15799451b44SJordan Rupprecht self.assertEqual(threads.GetSize(), 2) 15899451b44SJordan Rupprecht 15999451b44SJordan Rupprecht history_thread = threads.GetThreadAtIndex(0) 1609c246882SJordan Rupprecht self.assertGreaterEqual(history_thread.num_frames, 2) 16199451b44SJordan Rupprecht self.assertEqual( 1622238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 1632238dcc3SJonas Devlieghere "main.c", 1642238dcc3SJonas Devlieghere ) 1652238dcc3SJonas Devlieghere self.assertEqual( 1662238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetLine(), self.line_free 1672238dcc3SJonas Devlieghere ) 16899451b44SJordan Rupprecht 16999451b44SJordan Rupprecht history_thread = threads.GetThreadAtIndex(1) 1709c246882SJordan Rupprecht self.assertGreaterEqual(history_thread.num_frames, 2) 17199451b44SJordan Rupprecht self.assertEqual( 1722238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 1732238dcc3SJonas Devlieghere "main.c", 1742238dcc3SJonas Devlieghere ) 1752238dcc3SJonas Devlieghere self.assertEqual( 1762238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc 1772238dcc3SJonas Devlieghere ) 17899451b44SJordan Rupprecht 17999451b44SJordan Rupprecht # let's free the container (SBThreadCollection) and see if the 18099451b44SJordan Rupprecht # SBThreads still live 18199451b44SJordan Rupprecht threads = None 1829c246882SJordan Rupprecht self.assertGreaterEqual(history_thread.num_frames, 2) 18399451b44SJordan Rupprecht self.assertEqual( 1842238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), 1852238dcc3SJonas Devlieghere "main.c", 1862238dcc3SJonas Devlieghere ) 1872238dcc3SJonas Devlieghere self.assertEqual( 1882238dcc3SJonas Devlieghere history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc 1892238dcc3SJonas Devlieghere ) 19099451b44SJordan Rupprecht 19199451b44SJordan Rupprecht # ASan will break when a report occurs and we'll try the API then 19299451b44SJordan Rupprecht self.runCmd("continue") 19399451b44SJordan Rupprecht 19499451b44SJordan Rupprecht self.expect( 19599451b44SJordan Rupprecht "thread list", 19699451b44SJordan Rupprecht "Process should be stopped due to ASan report", 1972238dcc3SJonas Devlieghere substrs=["stopped", "stop reason = Use of deallocated memory"], 1982238dcc3SJonas Devlieghere ) 19999451b44SJordan Rupprecht 20099451b44SJordan Rupprecht # make sure the 'memory history' command still works even when we're 20199451b44SJordan Rupprecht # generating a report now 20299451b44SJordan Rupprecht self.expect( 20399451b44SJordan Rupprecht "memory history 'another_pointer'", 20499451b44SJordan Rupprecht substrs=[ 2052238dcc3SJonas Devlieghere "Memory allocated by Thread", 2062238dcc3SJonas Devlieghere "a.out`f1", 2072238dcc3SJonas Devlieghere "main.c:%d" % self.line_malloc2, 2082238dcc3SJonas Devlieghere ], 2092238dcc3SJonas Devlieghere ) 210