brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · 88acafd Raw
255 lines · python
1"""Test breaking inside functions defined within a BSD archive file libfoo.a."""2 3 4import lldb5from lldbsuite.test.decorators import *6from lldbsuite.test.lldbtest import *7from lldbsuite.test import lldbutil8import os9import time10 11 12class BSDArchivesTestCase(TestBase):13    # If your test case doesn't stress debug info, then14    # set this to true.  That way it won't be run once for15    # each debug info format.16    NO_DEBUG_INFO_TESTCASE = True17 18    def setUp(self):19        # Call super's setUp().20        TestBase.setUp(self)21        # Find the line number in a(int) to break at.22        self.line = line_number("a.c", "// Set file and line breakpoint inside a().")23 24    def test(self):25        """Break inside a() and b() defined within libfoo.a."""26        self.build()27 28        exe = self.getBuildArtifact("a.out")29        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)30 31        # Break inside a() by file and line first.32        lldbutil.run_break_set_by_file_and_line(33            self, "a.c", self.line, num_expected_locations=1, loc_exact=True34        )35 36        self.runCmd("run", RUN_SUCCEEDED)37 38        # The stop reason of the thread should be breakpoint.39        self.expect(40            "thread list",41            STOPPED_DUE_TO_BREAKPOINT,42            substrs=["stopped", "stop reason = breakpoint"],43        )44 45        # Break at a(int) first.46        self.expect(47            "frame variable", VARIABLES_DISPLAYED_CORRECTLY, substrs=["(int) arg = 1"]48        )49        self.expect_var_path("__a_global", type="int", value="1")50 51        # Set breakpoint for b() next.52        lldbutil.run_break_set_by_symbol(53            self, "b", num_expected_locations=1, sym_exact=True54        )55 56        # Continue the program, we should break at b(int) next.57        self.runCmd("continue")58        self.expect(59            "thread list",60            STOPPED_DUE_TO_BREAKPOINT,61            substrs=["stopped", "stop reason = breakpoint"],62        )63        self.expect(64            "frame variable", VARIABLES_DISPLAYED_CORRECTLY, substrs=["(int) arg = 2"]65        )66        self.expect_var_path("__b_global", type="int", value="2")67 68    def check_frame_variable_errors(self, thread, error_strings):69        command_result = lldb.SBCommandReturnObject()70        interp = self.dbg.GetCommandInterpreter()71        result = interp.HandleCommand("frame variable", command_result)72        self.assertEqual(73            result, lldb.eReturnStatusFailed, "frame var succeeded unexpectedly"74        )75        command_error = command_result.GetError()76 77        frame = thread.GetFrameAtIndex(0)78        var_list = frame.GetVariables(True, True, False, True)79        self.assertEqual(var_list.GetSize(), 0)80        api_error = var_list.GetError().GetCString()81 82        for s in error_strings:83            self.assertIn(84                s,85                command_error,86                'Make sure "%s" exists in the command error "%s"' % (s, command_error),87            )88        for s in error_strings:89            self.assertIn(90                s,91                api_error,92                'Make sure "%s" exists in the API error "%s"' % (s, api_error),93            )94 95    @skipIfRemote96    @skipUnlessDarwin97    def test_frame_var_errors_when_archive_missing(self):98        """99        Break inside a() and remove libfoo.a to make sure we can't load100        the debug information and report an appropriate error when doing101        'frame variable'.102        """103        self.build()104        exe = self.getBuildArtifact("a.out")105        libfoo_path = self.getBuildArtifact("libfoo.a")106        # Delete the main.o file that contains the debug info so we force an107        # error when we run to main and try to get variables for the a()108        # function. Since the libfoo.a is missing, the debug info won't be109        # loaded and we should see an error when trying to read varibles.110        os.unlink(libfoo_path)111 112        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(113            self, "a", bkpt_module=exe114        )115 116        error_strings = [117            'debug map object file "',118            'libfoo.a(a.o)" containing debug info does not exist, debug info will not be loaded',119        ]120        self.check_frame_variable_errors(thread, error_strings)121 122    @skipIfRemote123    @skipIf(compiler="clang", compiler_version=["<", "12.0"])124    def test_archive_specifications(self):125        """126        Create archives and make sure the information we get when retrieving127        the modules specifications is correct.128        """129        self.build()130        libbar_path = self.getBuildArtifact("libbar.a")131        libfoo_path = self.getBuildArtifact("libfoo.a")132        libfoothin_path = self.getBuildArtifact("libfoo-thin.a")133        objfile_a = self.getBuildArtifact("a.o")134        objfile_b = self.getBuildArtifact("b.o")135        objfile_c = self.getBuildArtifact("c.o")136        size_a = os.path.getsize(objfile_a)137        size_b = os.path.getsize(objfile_b)138        size_c = os.path.getsize(objfile_c)139 140        # Test loading normal archives141        module_specs = lldb.SBModuleSpecList.GetModuleSpecifications(libfoo_path)142        num_specs = module_specs.GetSize()143        self.assertEqual(num_specs, 2)144        spec = module_specs.GetSpecAtIndex(0)145        self.assertEqual(spec.GetObjectName(), "a.o")146        self.assertEqual(spec.GetObjectSize(), size_a)147        spec = module_specs.GetSpecAtIndex(1)148        self.assertEqual(spec.GetObjectName(), "b.o")149        self.assertEqual(spec.GetObjectSize(), size_b)150 151        # Test loading thin archives152        module_specs = lldb.SBModuleSpecList.GetModuleSpecifications(libbar_path)153        num_specs = module_specs.GetSize()154        self.assertEqual(num_specs, 1)155        spec = module_specs.GetSpecAtIndex(0)156        self.assertEqual(spec.GetObjectName(), "c.o")157        self.assertEqual(spec.GetObjectSize(), size_c)158 159        module_specs = lldb.SBModuleSpecList.GetModuleSpecifications(libfoothin_path)160        num_specs = module_specs.GetSize()161        self.assertEqual(num_specs, 2)162        spec = module_specs.GetSpecAtIndex(0)163        self.assertEqual(spec.GetObjectName(), "a.o")164        self.assertEqual(spec.GetObjectSize(), size_a)165        spec = module_specs.GetSpecAtIndex(1)166        self.assertEqual(spec.GetObjectName(), "b.o")167        self.assertEqual(spec.GetObjectSize(), size_b, libfoothin_path)168 169    @skipIfRemote170    @skipUnlessDarwin171    def test_frame_var_errors_when_thin_archive_malformed(self):172        """173        Create thin archive libfoo.a and make it malformed to make sure174        we don't crash and report an appropriate error when resolving175        breakpoint using debug map.176        """177        self.build()178        exe = self.getBuildArtifact("a.out")179        libfoo_path = self.getBuildArtifact("libfoo.a")180        libthin_path = self.getBuildArtifact("libfoo-thin.a")181        objfile_a = self.getBuildArtifact("a.o")182        objfile_b = self.getBuildArtifact("b.o")183        objfile_c = self.getBuildArtifact("c.o")184        # Replace the libfoo.a file with a thin archive containing the same185        # debug information (a.o, b.o). Then remove a.o from the file system186        # so we force an error when we set a breakpoint on a() function.187        # Since the a.o is missing, the debug info won't be loaded and we188        # should see an error when trying to break into a().189        os.remove(libfoo_path)190        shutil.copyfile(libthin_path, libfoo_path)191        os.remove(objfile_a)192 193        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)194        # We won't be able to see source file195        self.expect(196            "b a",197            substrs=["Breakpoint 1: where = a.out`a, address ="],198        )199        # Break at a() should fail200        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(201            self, "a", bkpt_module=exe202        )203        error_strings = [204            '"a.o" object from the "',205            "libfoo.a\" archive: either the .o file doesn't exist in the archive or the modification time (0x",206            ") of the .o file doesn't match",207        ]208        self.check_frame_variable_errors(thread, error_strings)209 210        # Break at b() should succeed211        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(212            self, "b", bkpt_module=exe213        )214        self.expect(215            "thread list",216            STOPPED_DUE_TO_BREAKPOINT,217            substrs=["stopped", "stop reason = breakpoint"],218        )219        self.expect(220            "frame variable", VARIABLES_DISPLAYED_CORRECTLY, substrs=["(int) arg = 2"]221        )222 223    @skipIfRemote224    @skipUnlessDarwin225    def test_frame_var_errors_when_mtime_mistmatch_for_object_in_archive(self):226        """227        Break inside a() and modify the modification time for "a.o" within228        libfoo.a to make sure we can't load the debug information and229        report an appropriate error when doing 'frame variable'.230        """231        self.build()232        exe = self.getBuildArtifact("a.out")233        a_path = self.getBuildArtifact("a.o")234 235        # Change the modification time of the a.o object file after sleeping for236        # 2 seconds to ensure the modification time is different. The rebuild237        # only the "libfoo.a" target. This means the modification time of the238        # a.o within libfoo.a will not match the debug map's modification time239        # in a.out and will cause the debug information to not be loaded and we240        # should get an appropriate error when reading variables.241        time.sleep(2)242        os.utime(a_path, None)243        self.build(make_targets=["libfoo.a"])244 245        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(246            self, "a", bkpt_module=exe247        )248 249        error_strings = [250            '"a.o" object from the "',251            "libfoo.a\" archive: either the .o file doesn't exist in the archive or the modification time (0x",252            ") of the .o file doesn't match",253        ]254        self.check_frame_variable_errors(thread, error_strings)255