364 lines · python
1"""2Test completing types using information from other shared libraries.3"""4 5import os6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class LimitDebugInfoTestCase(TestBase):13 def _check_type(self, target, name):14 exe = target.FindModule(lldb.SBFileSpec("a.out"))15 type_ = exe.FindFirstType(name)16 self.trace("type_: %s" % type_)17 self.assertTrue(type_)18 self.assertTrue(type_.IsTypeComplete())19 base = type_.GetDirectBaseClassAtIndex(0).GetType()20 self.trace("base:%s" % base)21 self.assertTrue(base)22 self.assertEqual(base.GetNumberOfFields(), 0)23 self.assertFalse(base.IsTypeComplete())24 25 def _check_debug_info_is_limited(self, target):26 # Without other shared libraries we should only see the member declared27 # in the derived class. This serves as a sanity check that we are truly28 # building with limited debug info.29 self._check_type(target, "InheritsFromOne")30 self._check_type(target, "InheritsFromTwo")31 32 # Check that the statistics show that we had incomplete debug info.33 stats = self.get_stats()34 # Find the a.out module info in the stats and verify it has the35 # "debugInfoHadIncompleteTypes" key value pair set to True36 exe_module_found = False37 for module in stats["modules"]:38 if module["path"].endswith("a.out"):39 self.assertTrue(module["debugInfoHadIncompleteTypes"])40 exe_module_found = True41 break42 self.assertTrue(exe_module_found)43 # Verify that "totalModuleCountWithIncompleteTypes" at the top level44 # is greater than zero which shows we had incomplete debug info in a45 # module46 self.assertGreater(stats["totalModuleCountWithIncompleteTypes"], 0)47 48 def _check_incomplete_frame_variable_output(self):49 # Check that the display of the "frame variable" output identifies the50 # incomplete types. Currently the expression parser will find the real51 # definition for a type when running an expression for any forcefully52 # completed types, but "frame variable" won't. I hope to fix this with53 # a follow up patch, but if we don't find the actual definition we54 # should clearly show this to the user by showing which types were55 # incomplete. So this will test verifies the expected output for such56 # types. We also need to verify the standard "frame variable" output57 # which will inline all of the members on one line, versus the full58 # output from "frame variable --raw" and a few other options.59 # self.expect("frame variable two_as_member", error=True,60 # substrs=["no member named 'one' in 'InheritsFromOne'"])61 62 command_expect_pairs = [63 # Test standard "frame variable" output for types to make sure64 # "<incomplete type>" shows up where we expect it to65 [66 "var two_as_member",67 [68 "(TwoAsMember) ::two_as_member = (two = <incomplete type>, member = 47)"69 ],70 ],71 [72 "var inherits_from_one",73 [74 "(InheritsFromOne) ::inherits_from_one = (One = <incomplete type>, member = 47)"75 ],76 ],77 [78 "var inherits_from_two",79 [80 "(InheritsFromTwo) ::inherits_from_two = (Two = <incomplete type>, member = 47)"81 ],82 ],83 [84 "var one_as_member",85 [86 "(OneAsMember) ::one_as_member = (one = <incomplete type>, member = 47)"87 ],88 ],89 [90 "var two_as_member",91 [92 "(TwoAsMember) ::two_as_member = (two = <incomplete type>, member = 47)"93 ],94 ],95 [96 "var array_of_one",97 [98 "(array::One[3]) ::array_of_one = ([0] = <incomplete type>, [1] = <incomplete type>, [2] = <incomplete type>)"99 ],100 ],101 [102 "var array_of_two",103 [104 "(array::Two[3]) ::array_of_two = ([0] = <incomplete type>, [1] = <incomplete type>, [2] = <incomplete type>)"105 ],106 ],107 [108 "var shadowed_one",109 [110 "(ShadowedOne) ::shadowed_one = (func_shadow::One = <incomplete type>, member = 47)"111 ],112 ],113 # Now test "frame variable --show-types output" which has multi-line114 # output and should not always show classes that were forcefully115 # completed to the user to let them know they have a type that should116 # have been complete but wasn't.117 [118 "var --show-types inherits_from_one",119 [120 "(InheritsFromOne) ::inherits_from_one = {",121 " (One) One = <incomplete type> {}",122 " (int) member = 47",123 "}",124 ],125 ],126 [127 "var --show-types inherits_from_two",128 [129 "(InheritsFromTwo) ::inherits_from_two = {",130 " (Two) Two = <incomplete type> {}",131 " (int) member = 47",132 "}",133 ],134 ],135 [136 "var --show-types one_as_member",137 [138 "(OneAsMember) ::one_as_member = {",139 " (member::One) one = <incomplete type> {}",140 " (int) member = 47",141 "}",142 ],143 ],144 [145 "var --show-types two_as_member",146 [147 "(TwoAsMember) ::two_as_member = {",148 " (member::Two) two = <incomplete type> {}",149 " (int) member = 47",150 "}",151 ],152 ],153 [154 "var --show-types array_of_one",155 [156 "(array::One[3]) ::array_of_one = {",157 " (array::One) [0] = <incomplete type> {}",158 " (array::One) [1] = <incomplete type> {}",159 " (array::One) [2] = <incomplete type> {}",160 "}",161 ],162 ],163 [164 "var --show-types array_of_two",165 [166 "(array::Two[3]) ::array_of_two = {",167 " (array::Two) [0] = <incomplete type> {}",168 " (array::Two) [1] = <incomplete type> {}",169 " (array::Two) [2] = <incomplete type> {}",170 "}",171 ],172 ],173 [174 "var --show-types shadowed_one",175 [176 "(ShadowedOne) ::shadowed_one = {",177 " (func_shadow::One) func_shadow::One = <incomplete type> {}",178 " (int) member = 47",179 "}",180 ],181 ],182 ]183 for command, expect_items in command_expect_pairs:184 self.expect(command, substrs=expect_items)185 186 @skipIf(bugnumber="pr46284", debug_info="gmodules")187 @skipIfWindows # Clang emits type info even with -flimit-debug-info188 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call189 # by-value functions.190 @skipIf(compiler="clang", compiler_version=["<", "7.0"])191 def test_one_and_two_debug(self):192 self.build()193 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))194 195 self._check_debug_info_is_limited(target)196 197 lldbutil.run_to_name_breakpoint(self, "main", extra_images=["one", "two"])198 199 # But when other shared libraries are loaded, we should be able to see200 # all members.201 self.expect_expr("inherits_from_one.member", result_value="47")202 self.expect_expr("inherits_from_one.one", result_value="142")203 self.expect_expr("inherits_from_two.member", result_value="47")204 self.expect_expr("inherits_from_two.one", result_value="142")205 self.expect_expr("inherits_from_two.two", result_value="242")206 207 self.expect_expr("one_as_member.member", result_value="47")208 self.expect_expr("one_as_member.one.member", result_value="147")209 self.expect_expr("two_as_member.member", result_value="47")210 self.expect_expr("two_as_member.two.one.member", result_value="147")211 self.expect_expr("two_as_member.two.member", result_value="247")212 213 self.expect_expr("array_of_one[2].member", result_value="174")214 self.expect_expr("array_of_two[2].one[2].member", result_value="174")215 self.expect_expr("array_of_two[2].member", result_value="274")216 217 self.expect_expr("get_one().member", result_value="124")218 self.expect_expr("get_two().one().member", result_value="124")219 self.expect_expr("get_two().member", result_value="224")220 221 self.expect_expr("shadowed_one.member", result_value="47")222 self.expect_expr("shadowed_one.one", result_value="142")223 224 self._check_incomplete_frame_variable_output()225 226 @skipIf(bugnumber="pr46284", debug_info="gmodules")227 @skipIfWindows # Clang emits type info even with -flimit-debug-info228 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call229 # by-value functions.230 @skipIf(compiler="clang", compiler_version=["<", "7.0"])231 def test_two_debug(self):232 self.build(dictionary=dict(STRIP_ONE="1"))233 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))234 235 self._check_debug_info_is_limited(target)236 237 lldbutil.run_to_name_breakpoint(self, "main", extra_images=["one", "two"])238 239 # This time, we should only see the members from the second library.240 self.expect_expr("inherits_from_one.member", result_value="47")241 self.expect(242 "expr inherits_from_one.one",243 error=True,244 substrs=["no member named 'one' in 'InheritsFromOne'"],245 )246 self.expect_expr("inherits_from_two.member", result_value="47")247 self.expect(248 "expr inherits_from_two.one",249 error=True,250 substrs=["no member named 'one' in 'InheritsFromTwo'"],251 )252 self.expect_expr("inherits_from_two.two", result_value="242")253 254 self.expect_expr("one_as_member.member", result_value="47")255 self.expect(256 "expr one_as_member.one.member",257 error=True,258 substrs=["no member named 'member' in 'member::One'"],259 )260 self.expect_expr("two_as_member.member", result_value="47")261 self.expect(262 "expr two_as_member.two.one.member",263 error=True,264 substrs=["no member named 'member' in 'member::One'"],265 )266 self.expect_expr("two_as_member.two.member", result_value="247")267 268 self.expect(269 "expr array_of_one[2].member",270 error=True,271 substrs=["no member named 'member' in 'array::One'"],272 )273 self.expect(274 "expr array_of_two[2].one[2].member",275 error=True,276 substrs=["no member named 'member' in 'array::One'"],277 )278 self.expect_expr("array_of_two[2].member", result_value="274")279 280 self.expect(281 "expr get_one().member",282 error=True,283 substrs=["calling 'get_one' with incomplete return type 'result::One'"],284 )285 self.expect(286 "expr get_two().one().member",287 error=True,288 substrs=["calling 'one' with incomplete return type 'result::One'"],289 )290 self.expect_expr("get_two().member", result_value="224")291 292 self._check_incomplete_frame_variable_output()293 294 @skipIf(bugnumber="pr46284", debug_info="gmodules")295 @skipIfWindows # Clang emits type info even with -flimit-debug-info296 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call297 # by-value functions.298 @skipIf(compiler="clang", compiler_version=["<", "7.0"])299 def test_one_debug(self):300 self.build(dictionary=dict(STRIP_TWO="1"))301 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))302 303 self._check_debug_info_is_limited(target)304 305 lldbutil.run_to_name_breakpoint(self, "main", extra_images=["one", "two"])306 307 # In this case we should only see the members from the second library.308 # Note that we cannot see inherits_from_two.one because without debug309 # info for "Two", we cannot determine that it in fact inherits from310 # "One".311 self.expect_expr("inherits_from_one.member", result_value="47")312 self.expect_expr("inherits_from_one.one", result_value="142")313 self.expect_expr("inherits_from_two.member", result_value="47")314 self.expect(315 "expr inherits_from_two.one",316 error=True,317 substrs=["no member named 'one' in 'InheritsFromTwo'"],318 )319 self.expect(320 "expr inherits_from_two.two",321 error=True,322 substrs=["no member named 'two' in 'InheritsFromTwo'"],323 )324 325 self.expect_expr("one_as_member.member", result_value="47")326 self.expect_expr("one_as_member.one.member", result_value="147")327 self.expect_expr("two_as_member.member", result_value="47")328 self.expect(329 "expr two_as_member.two.one.member",330 error=True,331 substrs=["no member named 'one' in 'member::Two'"],332 )333 self.expect(334 "expr two_as_member.two.member",335 error=True,336 substrs=["no member named 'member' in 'member::Two'"],337 )338 339 self.expect_expr("array_of_one[2].member", result_value="174")340 self.expect(341 "expr array_of_two[2].one[2].member",342 error=True,343 substrs=["no member named 'one' in 'array::Two'"],344 )345 self.expect(346 "expr array_of_two[2].member",347 error=True,348 substrs=["no member named 'member' in 'array::Two'"],349 )350 351 self.expect_expr("get_one().member", result_value="124")352 self.expect(353 "expr get_two().one().member",354 error=True,355 substrs=["calling 'get_two' with incomplete return type 'result::Two'"],356 )357 self.expect(358 "expr get_two().member",359 error=True,360 substrs=["calling 'get_two' with incomplete return type 'result::Two'"],361 )362 363 self._check_incomplete_frame_variable_output()364