1""" 2Test how many times newly loaded binaries are notified; 3they should be delivered in batches instead of one-by-one. 4""" 5 6from __future__ import print_function 7 8 9import lldb 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12from lldbsuite.test import lldbutil 13 14class ModuleLoadedNotifysTestCase(TestBase): 15 16 mydir = TestBase.compute_mydir(__file__) 17 NO_DEBUG_INFO_TESTCASE = True 18 19 # DynamicLoaderDarwin should batch up notifications about 20 # newly added/removed libraries. Other DynamicLoaders may 21 # not be written this way. 22 @skipUnlessDarwin 23 24 def setUp(self): 25 # Call super's setUp(). 26 TestBase.setUp(self) 27 # Find the line number to break inside main(). 28 self.line = line_number('main.cpp', '// breakpoint') 29 30 def test_launch_notifications(self): 31 """Test that lldb broadcasts newly loaded libraries in batches.""" 32 self.build() 33 exe = self.getBuildArtifact("a.out") 34 self.dbg.SetAsync(False) 35 36 listener = self.dbg.GetListener() 37 listener.StartListeningForEventClass( 38 self.dbg, 39 lldb.SBTarget.GetBroadcasterClassName(), 40 lldb.SBTarget.eBroadcastBitModulesLoaded | lldb.SBTarget.eBroadcastBitModulesUnloaded) 41 42 # Create a target by the debugger. 43 target = self.dbg.CreateTarget(exe) 44 self.assertTrue(target, VALID_TARGET) 45 46 # break on main 47 breakpoint = target.BreakpointCreateByName('main', 'a.out') 48 49 event = lldb.SBEvent() 50 # CreateTarget() generated modules-loaded events; consume them & toss 51 while listener.GetNextEvent(event): 52 True 53 54 error = lldb.SBError() 55 process = target.Launch(listener, 56 None, # argv 57 None, # envp 58 None, # stdin_path 59 None, # stdout_path 60 None, # stderr_path 61 None, # working directory 62 0, # launch flags 63 False, # Stop at entry 64 error) # error 65 66 self.assertTrue( 67 process.GetState() == lldb.eStateStopped, 68 PROCESS_STOPPED) 69 70 total_solibs_added = 0 71 total_solibs_removed = 0 72 total_modules_added_events = 0 73 total_modules_removed_events = 0 74 while listener.GetNextEvent(event): 75 if lldb.SBTarget.EventIsTargetEvent(event): 76 if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded: 77 solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) 78 total_modules_added_events += 1 79 total_solibs_added += solib_count 80 if self.TraceOn(): 81 # print all of the binaries that have been added 82 added_files = [] 83 i = 0 84 while i < solib_count: 85 module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) 86 added_files.append(module.GetFileSpec().GetFilename()) 87 i = i + 1 88 print("Loaded files: %s" % (', '.join(added_files))) 89 90 if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded: 91 solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) 92 total_modules_removed_events += 1 93 total_solibs_removed += solib_count 94 if self.TraceOn(): 95 # print all of the binaries that have been removed 96 removed_files = [] 97 i = 0 98 while i < solib_count: 99 module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) 100 removed_files.append(module.GetFileSpec().GetFilename()) 101 i = i + 1 102 print("Unloaded files: %s" % (', '.join(removed_files))) 103 104 105 # This is testing that we get back a small number of events with the loaded 106 # binaries in batches. Check that we got back more than 1 solib per event. 107 # In practice on Darwin today, we get back two events for a do-nothing c 108 # program: a.out and dyld, and then all the rest of the system libraries. 109 110 avg_solibs_added_per_event = int(float(total_solibs_added) / float(total_modules_added_events)) 111 self.assertGreater(avg_solibs_added_per_event, 1) 112