brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.3 KiB · d3c64d8 Raw
582 lines · python
1"""2Test SBTarget APIs.3"""4 5import os6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class TargetAPITestCase(TestBase):13    def setUp(self):14        # Call super's setUp().15        TestBase.setUp(self)16        # Find the line number to of function 'c'.17        self.line1 = line_number(18            "main.c", "// Find the line number for breakpoint 1 here."19        )20        self.line2 = line_number(21            "main.c", "// Find the line number for breakpoint 2 here."22        )23        self.line_main = line_number("main.c", "// Set a break at entry to main.")24 25    # rdar://problem/970087326    # Find global variable value fails for dwarf if inferior not started27    # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)28    #29    # It does not segfaults now.  But for dwarf, the variable value is None if30    # the inferior process does not exist yet.  The radar has been updated.31    def test_find_global_variables(self):32        """Exercise SBTarget.FindGlobalVariables() API."""33        d = {"EXE": "b.out"}34        self.build(dictionary=d)35        self.setTearDownCleanup(dictionary=d)36        self.find_global_variables("b.out")37 38    def test_find_compile_units(self):39        """Exercise SBTarget.FindCompileUnits() API."""40        d = {"EXE": "b.out"}41        self.build(dictionary=d)42        self.setTearDownCleanup(dictionary=d)43        self.find_compile_units(self.getBuildArtifact("b.out"))44 45    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")46    def test_find_functions(self):47        """Exercise SBTarget.FindFunctions() API."""48        d = {"EXE": "b.out"}49        self.build(dictionary=d)50        self.setTearDownCleanup(dictionary=d)51        self.find_functions("b.out")52 53    def test_get_description(self):54        """Exercise SBTarget.GetDescription() API."""55        self.build()56        self.get_description()57 58    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")59    def test_resolve_symbol_context_with_address(self):60        """Exercise SBTarget.ResolveSymbolContextForAddress() API."""61        self.build()62        self.resolve_symbol_context_with_address()63 64    def test_get_platform(self):65        d = {"EXE": "b.out"}66        self.build(dictionary=d)67        self.setTearDownCleanup(dictionary=d)68        target = self.create_simple_target("b.out")69        platform = target.platform70        self.assertTrue(platform, VALID_PLATFORM)71 72    def test_get_data_byte_size(self):73        d = {"EXE": "b.out"}74        self.build(dictionary=d)75        self.setTearDownCleanup(dictionary=d)76        target = self.create_simple_target("b.out")77        self.assertEqual(target.data_byte_size, 1)78 79    def test_get_code_byte_size(self):80        d = {"EXE": "b.out"}81        self.build(dictionary=d)82        self.setTearDownCleanup(dictionary=d)83        target = self.create_simple_target("b.out")84        self.assertEqual(target.code_byte_size, 1)85 86    def test_resolve_file_address(self):87        d = {"EXE": "b.out"}88        self.build(dictionary=d)89        self.setTearDownCleanup(dictionary=d)90        target = self.create_simple_target("b.out")91 92        # find the file address in the .data section of the main93        # module94        data_section = self.find_data_section(target)95        data_section_addr = data_section.file_addr96 97        # resolve the above address, and compare the address produced98        # by the resolution against the original address/section99        res_file_addr = target.ResolveFileAddress(data_section_addr)100        self.assertTrue(res_file_addr.IsValid())101 102        self.assertEqual(data_section_addr, res_file_addr.file_addr)103 104        data_section2 = res_file_addr.section105        self.assertIsNotNone(data_section2)106        self.assertEqual(data_section.name, data_section2.name)107 108    def test_get_arch_name(self):109        d = {"EXE": "b.out"}110        self.build(dictionary=d)111        self.setTearDownCleanup(dictionary=d)112        target = self.create_simple_target("b.out")113 114        arch_name = target.arch_name115        self.assertTrue(len(arch_name) > 0, "Got an arch name")116 117        # Test consistency with triple.118        triple = target.triple119        self.assertTrue(len(triple) > 0, "Got a triple")120        self.assertEqual(121            triple.split("-")[0],122            arch_name,123            "Arch name is equal to the first item of the triple",124        )125 126    def test_get_ABIName(self):127        d = {"EXE": "b.out"}128        self.build(dictionary=d)129        self.setTearDownCleanup(dictionary=d)130        target = self.create_simple_target("b.out")131 132        abi_pre_launch = target.GetABIName()133        self.assertNotEqual(len(abi_pre_launch), 0, "Got an ABI string")134 135        breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main)136        self.assertTrue(breakpoint, VALID_BREAKPOINT)137 138        # Put debugger into synchronous mode so when we target.LaunchSimple returns139        # it will guaranteed to be at the breakpoint140        self.dbg.SetAsync(False)141 142        # Launch the process, and do not stop at the entry point.143        process = target.LaunchSimple(None, None, self.get_process_working_directory())144        abi_after_launch = target.GetABIName()145        self.assertEqual(146            abi_pre_launch, abi_after_launch, "ABI's match before and during run"147        )148 149    def test_read_memory(self):150        d = {"EXE": "b.out"}151        self.build(dictionary=d)152        self.setTearDownCleanup(dictionary=d)153        target = self.create_simple_target("b.out")154 155        breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main)156        self.assertTrue(breakpoint, VALID_BREAKPOINT)157 158        # Put debugger into synchronous mode so when we target.LaunchSimple returns159        # it will guaranteed to be at the breakpoint160        self.dbg.SetAsync(False)161 162        # Launch the process, and do not stop at the entry point.163        process = target.LaunchSimple(None, None, self.get_process_working_directory())164 165        # find the file address in the .data section of the main166        # module167        data_section = self.find_data_section(target)168        sb_addr = lldb.SBAddress(data_section, 0)169        error = lldb.SBError()170        content = target.ReadMemory(sb_addr, 1, error)171        self.assertSuccess(error, "Make sure memory read succeeded")172        self.assertEqual(len(content), 1)173 174        # Make sure reading from 0x0 fails175        sb_addr = lldb.SBAddress(0, target)176        self.assertIsNone(target.ReadMemory(sb_addr, 1, error))177        self.assertTrue(error.Fail())178 179    @skipIfWindows  # stdio manipulation unsupported on Windows180    @skipIfRemote  # stdio manipulation unsupported on remote iOS devices<rdar://problem/54581135>181    @skipIf(oslist=["linux"], archs=["arm$", "aarch64"])182    @no_debug_info_test183    def test_launch_simple(self):184        d = {"EXE": "b.out"}185        self.build(dictionary=d)186        self.setTearDownCleanup(dictionary=d)187        target = self.create_simple_target("b.out")188 189        # Set the debugger to synchronous mode so we only continue after the190        # process has exited.191        self.dbg.SetAsync(False)192 193        process = target.LaunchSimple(194            ["foo", "bar"], ["baz"], self.get_process_working_directory()195        )196        process.Continue()197        self.assertState(process.GetState(), lldb.eStateExited)198        output = process.GetSTDOUT(9999)199        self.assertIn("arg: foo", output)200        self.assertIn("arg: bar", output)201        self.assertIn("env: baz", output)202 203        self.runCmd("setting set target.run-args foo")204        self.runCmd("setting set target.env-vars bar=baz")205        process = target.LaunchSimple(None, None, self.get_process_working_directory())206        process.Continue()207        self.assertState(process.GetState(), lldb.eStateExited)208        output = process.GetSTDOUT(9999)209        self.assertIn("arg: foo", output)210        self.assertIn("env: bar=baz", output)211 212        # Clear all the run args set above.213        self.runCmd("setting clear target.run-args")214        process = target.LaunchSimple(None, None, self.get_process_working_directory())215        process.Continue()216        self.assertEqual(process.GetState(), lldb.eStateExited)217        output = process.GetSTDOUT(9999)218        self.assertNotIn("arg: foo", output)219 220        self.runCmd("settings set target.disable-stdio true")221        process = target.LaunchSimple(None, None, self.get_process_working_directory())222        process.Continue()223        self.assertState(process.GetState(), lldb.eStateExited)224        output = process.GetSTDOUT(9999)225        self.assertEqual(output, "")226 227    def create_simple_target(self, fn):228        exe = self.getBuildArtifact(fn)229        target = self.dbg.CreateTarget(exe)230        self.assertTrue(target, VALID_TARGET)231        return target232 233    def find_data_section(self, target):234        mod = target.GetModuleAtIndex(0)235        data_section = None236        for s in mod.sections:237            sect_type = s.GetSectionType()238            if sect_type == lldb.eSectionTypeData:239                data_section = s240                break241            elif sect_type == lldb.eSectionTypeContainer:242                for i in range(s.GetNumSubSections()):243                    ss = s.GetSubSectionAtIndex(i)244                    sect_type = ss.GetSectionType()245                    if sect_type == lldb.eSectionTypeData:246                        data_section = ss247                        break248 249        self.assertIsNotNone(data_section)250        return data_section251 252    def find_global_variables(self, exe_name):253        """Exercise SBTarget.FindGlobalVariables() API."""254        exe = self.getBuildArtifact(exe_name)255 256        # Create a target by the debugger.257        target = self.dbg.CreateTarget(exe)258        self.assertTrue(target, VALID_TARGET)259 260        # rdar://problem/9700873261        # Find global variable value fails for dwarf if inferior not started262        # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)263        #264        # Remove the lines to create a breakpoint and to start the inferior265        # which are workarounds for the dwarf case.266 267        breakpoint = target.BreakpointCreateByLocation("main.c", self.line1)268        self.assertTrue(breakpoint, VALID_BREAKPOINT)269 270        # Now launch the process, and do not stop at entry point.271        process = target.LaunchSimple(None, None, self.get_process_working_directory())272        self.assertTrue(process, PROCESS_IS_VALID)273        # Make sure we hit our breakpoint:274        thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint)275        self.assertEqual(len(thread_list), 1)276 277        value_list = target.FindGlobalVariables("my_global_var_of_char_type", 3)278        self.assertEqual(value_list.GetSize(), 1)279        my_global_var = value_list.GetValueAtIndex(0)280        self.DebugSBValue(my_global_var)281        self.assertTrue(my_global_var)282        self.expect(283            my_global_var.GetName(), exe=False, startstr="my_global_var_of_char_type"284        )285        self.expect(my_global_var.GetTypeName(), exe=False, startstr="char")286        self.expect(my_global_var.GetValue(), exe=False, startstr="'X'")287 288        # While we are at it, let's also exercise the similar289        # SBModule.FindGlobalVariables() API.290        for m in target.module_iter():291            if (292                os.path.normpath(m.GetFileSpec().GetDirectory()) == self.getBuildDir()293                and m.GetFileSpec().GetFilename() == exe_name294            ):295                value_list = m.FindGlobalVariables(296                    target, "my_global_var_of_char_type", 3297                )298                self.assertEqual(value_list.GetSize(), 1)299                self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "'X'")300                break301 302    def find_compile_units(self, exe):303        """Exercise SBTarget.FindCompileUnits() API."""304        source_name = "main.c"305 306        # Create a target by the debugger.307        target = self.dbg.CreateTarget(exe)308        self.assertTrue(target, VALID_TARGET)309 310        list = target.FindCompileUnits(lldb.SBFileSpec(source_name, False))311        # Executable has been built just from one source file 'main.c',312        # so we may check only the first element of list.313        self.assertEqual(314            list[0].GetCompileUnit().GetFileSpec().GetFilename(), source_name315        )316 317    def find_functions(self, exe_name):318        """Exercise SBTarget.FindFunctions() API."""319        exe = self.getBuildArtifact(exe_name)320 321        # Create a target by the debugger.322        target = self.dbg.CreateTarget(exe)323        self.assertTrue(target, VALID_TARGET)324 325        # Try it with a null name:326        list = target.FindFunctions(None, lldb.eFunctionNameTypeAuto)327        self.assertEqual(list.GetSize(), 0)328 329        list = target.FindFunctions("c", lldb.eFunctionNameTypeAuto)330        self.assertEqual(list.GetSize(), 1)331 332        for sc in list:333            self.assertEqual(sc.GetModule().GetFileSpec().GetFilename(), exe_name)334            self.assertEqual(sc.GetSymbol().GetName(), "c")335 336    def get_description(self):337        """Exercise SBTarget.GetDescription() API."""338        exe = self.getBuildArtifact("a.out")339 340        # Create a target by the debugger.341        target = self.dbg.CreateTarget(exe)342        self.assertTrue(target, VALID_TARGET)343 344        from lldbsuite.test.lldbutil import get_description345 346        # get_description() allows no option to mean347        # lldb.eDescriptionLevelBrief.348        desc = get_description(target)349        # desc = get_description(target, option=lldb.eDescriptionLevelBrief)350        if not desc:351            self.fail("SBTarget.GetDescription() failed")352        self.expect(desc, exe=False, substrs=["a.out"])353        self.expect(354            desc, exe=False, matching=False, substrs=["Target", "Module", "Breakpoint"]355        )356 357        desc = get_description(target, option=lldb.eDescriptionLevelFull)358        if not desc:359            self.fail("SBTarget.GetDescription() failed")360        self.expect(361            desc, exe=False, substrs=["Target", "Module", "a.out", "Breakpoint"]362        )363 364    @skipIfRemote365    @no_debug_info_test366    def test_launch_new_process_and_redirect_stdout(self):367        """Exercise SBTarget.Launch() API with redirected stdout."""368        self.build()369        exe = self.getBuildArtifact("a.out")370 371        # Create a target by the debugger.372        target = self.dbg.CreateTarget(exe)373        self.assertTrue(target, VALID_TARGET)374 375        # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done.376        # We should still see the entire stdout redirected once the process is377        # finished.378        line = line_number("main.c", "// a(3) -> c(3)")379        breakpoint = target.BreakpointCreateByLocation("main.c", line)380 381        # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file.382        # The inferior should run to completion after "process.Continue()"383        # call.384        local_path = self.getBuildArtifact("stdout.txt")385        if os.path.exists(local_path):386            os.remove(local_path)387 388        if lldb.remote_platform:389            stdout_path = lldbutil.append_to_process_working_directory(390                self, "lldb-stdout-redirect.txt"391            )392        else:393            stdout_path = local_path394        error = lldb.SBError()395        process = target.Launch(396            self.dbg.GetListener(),397            None,398            None,399            None,400            stdout_path,401            None,402            None,403            0,404            False,405            error,406        )407        process.Continue()408        # self.runCmd("process status")409        if lldb.remote_platform:410            # copy output file to host411            lldb.remote_platform.Get(412                lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path)413            )414 415        # The 'stdout.txt' file should now exist.416        self.assertTrue(417            os.path.isfile(local_path),418            "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.",419        )420 421        # Read the output file produced by running the program.422        with open(local_path, "r") as f:423            output = f.read()424 425        self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"])426 427    def resolve_symbol_context_with_address(self):428        """Exercise SBTarget.ResolveSymbolContextForAddress() API."""429        exe = self.getBuildArtifact("a.out")430 431        # Create a target by the debugger.432        target = self.dbg.CreateTarget(exe)433        self.assertTrue(target, VALID_TARGET)434 435        # Now create the two breakpoints inside function 'a'.436        breakpoint1 = target.BreakpointCreateByLocation("main.c", self.line1)437        breakpoint2 = target.BreakpointCreateByLocation("main.c", self.line2)438        self.trace("breakpoint1:", breakpoint1)439        self.trace("breakpoint2:", breakpoint2)440        self.assertTrue(441            breakpoint1 and breakpoint1.GetNumLocations() == 1, VALID_BREAKPOINT442        )443        self.assertTrue(444            breakpoint2 and breakpoint2.GetNumLocations() == 1, VALID_BREAKPOINT445        )446 447        # Now launch the process, and do not stop at entry point.448        process = target.LaunchSimple(None, None, self.get_process_working_directory())449        self.assertTrue(process, PROCESS_IS_VALID)450 451        # Frame #0 should be on self.line1.452        self.assertState(process.GetState(), lldb.eStateStopped)453        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)454        self.assertTrue(455            thread.IsValid(),456            "There should be a thread stopped due to breakpoint condition",457        )458        # self.runCmd("process status")459        frame0 = thread.GetFrameAtIndex(0)460        lineEntry = frame0.GetLineEntry()461        self.assertEqual(lineEntry.GetLine(), self.line1)462 463        address1 = lineEntry.GetStartAddress()464 465        # Continue the inferior, the breakpoint 2 should be hit.466        process.Continue()467        self.assertState(process.GetState(), lldb.eStateStopped)468        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)469        self.assertTrue(470            thread.IsValid(),471            "There should be a thread stopped due to breakpoint condition",472        )473        # self.runCmd("process status")474        frame0 = thread.GetFrameAtIndex(0)475        lineEntry = frame0.GetLineEntry()476        self.assertEqual(lineEntry.GetLine(), self.line2)477 478        address2 = lineEntry.GetStartAddress()479 480        self.trace("address1:", address1)481        self.trace("address2:", address2)482 483        # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses484        # from our line entry.485        context1 = target.ResolveSymbolContextForAddress(486            address1, lldb.eSymbolContextEverything487        )488        context2 = target.ResolveSymbolContextForAddress(489            address2, lldb.eSymbolContextEverything490        )491 492        self.assertTrue(context1 and context2)493        self.trace("context1:", context1)494        self.trace("context2:", context2)495 496        # Verify that the context point to the same function 'a'.497        symbol1 = context1.GetSymbol()498        symbol2 = context2.GetSymbol()499        self.assertTrue(symbol1 and symbol2)500        self.trace("symbol1:", symbol1)501        self.trace("symbol2:", symbol2)502 503        from lldbsuite.test.lldbutil import get_description504 505        desc1 = get_description(symbol1)506        desc2 = get_description(symbol2)507        self.assertTrue(508            desc1 and desc2 and desc1 == desc2,509            "The two addresses should resolve to the same symbol",510        )511 512    @skipIfRemote513    def test_default_arch(self):514        """Test the other two target create methods using LLDB_ARCH_DEFAULT."""515        self.build()516        exe = self.getBuildArtifact("a.out")517        target = self.dbg.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)518        self.assertTrue(target.IsValid(), "Default arch made a valid target.")519        # This should also work with the target's triple:520        target2 = self.dbg.CreateTargetWithFileAndArch(exe, target.GetTriple())521        self.assertTrue(target2.IsValid(), "Round trip with triple works")522        # And this triple should work for the FileAndTriple API:523        target3 = self.dbg.CreateTargetWithFileAndTargetTriple(exe, target.GetTriple())524        self.assertTrue(target3.IsValid())525 526    @skipIfWindows527    def test_is_loaded(self):528        """Exercise SBTarget.IsLoaded(SBModule&) API."""529        d = {"EXE": "b.out"}530        self.build(dictionary=d)531        self.setTearDownCleanup(dictionary=d)532        target = self.create_simple_target("b.out")533 534        self.assertFalse(target.IsLoaded(lldb.SBModule()))535 536        num_modules = target.GetNumModules()537        for i in range(num_modules):538            module = target.GetModuleAtIndex(i)539            self.assertFalse(540                target.IsLoaded(module),541                "Target that isn't " "running shouldn't have any module loaded.",542            )543 544        process = target.LaunchSimple(None, None, self.get_process_working_directory())545 546        for i in range(num_modules):547            module = target.GetModuleAtIndex(i)548            self.assertTrue(549                target.IsLoaded(module),550                "Running the target should " "have loaded its modules.",551            )552 553    @no_debug_info_test554    def test_setting_selected_target_with_invalid_target(self):555        """Make sure we don't crash when trying to select invalid target."""556        target = lldb.SBTarget()557        self.dbg.SetSelectedTarget(target)558 559    @no_debug_info_test560    def test_get_api_mutex(self):561        """Make sure we can lock and unlock the API mutex from Python."""562        target = self.dbg.GetDummyTarget()563 564        mutex = target.GetAPIMutex()565        self.assertTrue(mutex.IsValid())566        mutex.lock()567        # The API call below doesn't actually matter, it's just there to568        # confirm we don't block on the API lock.569        target.BreakpointCreateByName("foo", "bar")570        mutex.unlock()571 572    @no_debug_info_test573    def test_get_api_mutex_with_statement(self):574        """Make sure we can lock and unlock the API mutex using a with-statement from Python."""575        target = self.dbg.GetDummyTarget()576 577        with target.GetAPIMutex() as mutex:578            self.assertTrue(mutex.IsValid())579            # The API call below doesn't actually matter, it's just there to580            # confirm we don't block on the API lock.581            target.BreakpointCreateByName("foo", "bar")582