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 # At least DynamicLoaderDarwin and DynamicLoaderPOSIXDYLD should batch up 20 # notifications about newly added/removed libraries. Other DynamicLoaders may 21 # not be written this way. 22 @skipUnlessPlatform(["linux"]+lldbplatformutil.getDarwinOSTriples()) 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 flags = target.GetLaunchInfo().GetLaunchFlags() 56 process = target.Launch(listener, 57 None, # argv 58 None, # envp 59 None, # stdin_path 60 None, # stdout_path 61 None, # stderr_path 62 None, # working directory 63 flags, # launch flags 64 False, # Stop at entry 65 error) # error 66 67 self.assertEqual( 68 process.GetState(), lldb.eStateStopped, 69 PROCESS_STOPPED) 70 71 total_solibs_added = 0 72 total_solibs_removed = 0 73 total_modules_added_events = 0 74 total_modules_removed_events = 0 75 already_loaded_modules = [] 76 while listener.GetNextEvent(event): 77 if lldb.SBTarget.EventIsTargetEvent(event): 78 if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded: 79 solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) 80 total_modules_added_events += 1 81 total_solibs_added += solib_count 82 added_files = [] 83 i = 0 84 while i < solib_count: 85 module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) 86 self.assertTrue(module not in already_loaded_modules) 87 already_loaded_modules.append(module) 88 if self.TraceOn(): 89 added_files.append(module.GetFileSpec().GetFilename()) 90 i = i + 1 91 if self.TraceOn(): 92 # print all of the binaries that have been added 93 print("Loaded files: %s" % (', '.join(added_files))) 94 95 if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded: 96 solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) 97 total_modules_removed_events += 1 98 total_solibs_removed += solib_count 99 if self.TraceOn(): 100 # print all of the binaries that have been removed 101 removed_files = [] 102 i = 0 103 while i < solib_count: 104 module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) 105 removed_files.append(module.GetFileSpec().GetFilename()) 106 i = i + 1 107 print("Unloaded files: %s" % (', '.join(removed_files))) 108 109 110 # This is testing that we get back a small number of events with the loaded 111 # binaries in batches. Check that we got back more than 1 solib per event. 112 # In practice on Darwin today, we get back two events for a do-nothing c 113 # program: a.out and dyld, and then all the rest of the system libraries. 114 # On Linux we get events for ld.so, [vdso], the binary and then all libraries. 115 116 avg_solibs_added_per_event = round(float(total_solibs_added) / float(total_modules_added_events)) 117 self.assertGreater(avg_solibs_added_per_event, 1) 118