diff options
Diffstat (limited to 'lldb/test/API/functionalities')
21 files changed, 652 insertions, 71 deletions
diff --git a/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py b/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py index d120692e4d6e..3674a8c233c8 100644 --- a/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py +++ b/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py @@ -32,7 +32,7 @@ class BadAddressBreakpointTestCase(TestBase): for region_idx in range(regions.GetSize()): region = lldb.SBMemoryRegionInfo() regions.GetMemoryRegionAtIndex(region_idx, region) - if illegal_address == None or region.GetRegionEnd() > illegal_address: + if illegal_address is None or region.GetRegionEnd() > illegal_address: illegal_address = region.GetRegionEnd() if illegal_address is not None: diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/Makefile index 6914024392cf..3e5da0ecae66 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/Makefile @@ -1,4 +1,12 @@ CXX_SOURCES := main.cpp CFLAGS_EXTRAS := -std=c++20 +ifeq "1" "$(USE_LIBSTDCPP)" + CFLAGS_EXTRAS += -DUSE_LIBSTDCPP +endif + +ifeq "1" "$(USE_LIBCPP)" + CFLAGS_EXTRAS += -DUSE_LIBCPP +endif + include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/main.cpp index 8cb81c3bc9f4..aaf76e0d8d99 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/main.cpp @@ -1,13 +1,27 @@ +#if defined(USE_LIBSTDCPP) +#include <bits/c++config.h> +// glibc++ >= 11 and c++20 +#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 11 #include <coroutine> +#define HAS_CPP_COROUTINES 1 +#endif +#endif + +// libc++ always has 'coroutine' feature. +#if defined(USE_LIBCPP) +#include <coroutine> +#define HAS_CPP_COROUTINES 1 +#endif bool is_implementation_supported() { -#ifdef _GLIBCXX_RELEASE - return _GLIBCXX_RELEASE >= 11; -#else +#ifdef HAS_CPP_COROUTINES return true; +#else + return false; #endif } +#ifdef HAS_CPP_COROUTINES // `int_generator` is a stripped down, minimal coroutine generator // type. struct int_generator { @@ -39,8 +53,11 @@ int_generator my_generator_func() { co_yield 42; } // a place to reliably set a breakpoint on. void empty_function_so_we_can_set_a_breakpoint() {} +#endif // HAS_CPP_COROUTINES + int main() { bool is_supported = is_implementation_supported(); +#ifdef HAS_CPP_COROUTINES int_generator gen = my_generator_func(); std::coroutine_handle<> type_erased_hdl = gen.hdl; std::coroutine_handle<int> incorrectly_typed_hdl = @@ -48,4 +65,8 @@ int main() { gen.hdl.resume(); // Break at initial_suspend gen.hdl.resume(); // Break after co_yield empty_function_so_we_can_set_a_breakpoint(); // Break at final_suspend + return 0; +#else + return 0; // Break at initial_suspend +#endif // HAS_CPP_COROUTINES } diff --git a/lldb/test/API/functionalities/disassemble/aarch64-adrp-add/TestAArch64AdrpAdd.py b/lldb/test/API/functionalities/disassemble/aarch64-adrp-add/TestAArch64AdrpAdd.py index da9ce1b87d33..8a3bcf28a211 100644 --- a/lldb/test/API/functionalities/disassemble/aarch64-adrp-add/TestAArch64AdrpAdd.py +++ b/lldb/test/API/functionalities/disassemble/aarch64-adrp-add/TestAArch64AdrpAdd.py @@ -57,7 +57,7 @@ class TestAArch64AdrpAdd(TestBase): found_hi_string = True if "foo" in i.GetComment(target): found_foo = True - if found_hi_string == False or found_foo == False: + if not found_hi_string or not found_foo: print( 'Did not find "HI" string or "foo" in disassembly symbolication in %s' % binaryname diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerNoTargetXML.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerNoTargetXML.py index 5f6ed7d537af..8c5bad007f56 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerNoTargetXML.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerNoTargetXML.py @@ -1,3 +1,12 @@ +""" +Check that lldb falls back to default register layouts when the remote provides +no target XML. + +GPRS are passed to the responder to create register data to send back to lldb. +Registers in SUPPL are virtual registers based on those general ones. The tests +pass __file__ to FileCheck so any prefixes in this Python file will be checked. +""" + import lldb from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * @@ -6,14 +15,29 @@ from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase import binascii - -class TestGDBServerTargetXML(GDBRemoteTestBase): +class MyResponder(MockGDBServerResponder): @staticmethod def filecheck_to_blob(fc): for l in fc.strip().splitlines(): val = l.split("0x")[1] yield binascii.b2a_hex(bytes(reversed(binascii.a2b_hex(val)))).decode() + def __init__(self, reg_data, halt_reason): + super().__init__() + self.reg_data = "".join(self.filecheck_to_blob(reg_data)) + self.halt_reason = halt_reason + + def readRegister(self, regnum): + return "" + + def readRegisters(self): + return self.reg_data + + def haltReason(self): + return self.halt_reason + + +class TestGDBServerTargetXML(GDBRemoteTestBase): @skipIfRemote @skipIfLLVMTargetMissing("X86") def test_x86_64_regs(self): @@ -100,19 +124,10 @@ CHECK-AMD64-DAG: r14l = 0xe1 CHECK-AMD64-DAG: r15l = 0xf1 """ - class MyResponder(MockGDBServerResponder): - reg_data = "".join(self.filecheck_to_blob(GPRS)) - - def readRegister(self, regnum): - return "" - - def readRegisters(self): - return self.reg_data - - def haltReason(self): - return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;" - - self.server.responder = MyResponder() + self.server.responder = MyResponder( + GPRS, + "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;", + ) target = self.createTarget("basic_eh_frame.yaml") process = self.connect(target) @@ -216,19 +231,10 @@ CHECK-AARCH64-DAG: w30 = 0x22232425 CHECK-AARCH64-DAG: w31 = 0x23242526 """ - class MyResponder(MockGDBServerResponder): - reg_data = "".join(self.filecheck_to_blob(GPRS)) - - def readRegister(self, regnum): - return "" - - def readRegisters(self): - return self.reg_data - - def haltReason(self): - return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;" - - self.server.responder = MyResponder() + self.server.responder = MyResponder( + GPRS, + "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;", + ) target = self.createTarget("basic_eh_frame-aarch64.yaml") process = self.connect(target) @@ -300,19 +306,10 @@ CHECK-I386-DAG: sil = 0x61 CHECK-I386-DAG: dil = 0x71 """ - class MyResponder(MockGDBServerResponder): - reg_data = "".join(self.filecheck_to_blob(GPRS)) - - def readRegister(self, regnum): - return "" - - def readRegisters(self): - return self.reg_data - - def haltReason(self): - return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;" - - self.server.responder = MyResponder() + self.server.responder = MyResponder( + GPRS, + "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;", + ) target = self.createTarget("basic_eh_frame-i386.yaml") process = self.connect(target) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py b/lldb/test/API/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py index a51b228e917c..7d6b1afd94a1 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py @@ -61,7 +61,7 @@ class TestNoWatchpointSupportInfo(GDBRemoteTestBase): wp_opts = lldb.SBWatchpointOptions() wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify) wp = target.WatchpointCreateByAddress(0x100, 8, wp_opts, err) - if self.TraceOn() and (err.Fail() or wp.IsValid == False): + if self.TraceOn() and (err.Fail() or not wp.IsValid): strm = lldb.SBStream() err.GetDescription(strm) print("watchpoint failed: %s" % strm.GetData()) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py b/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py index e2c75970c2d2..2dbb2b5f5e3a 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py @@ -654,3 +654,405 @@ class TestXMLRegisterFlags(GDBRemoteTestBase): "register info cpsr", substrs=["| A< | B> | C' | D\" | E& |"], ) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_no_enum(self): + """Check that lldb does not try to print an enum when there isn't one.""" + + self.setup_flags_test('<field name="E" start="0" end="0">' "</field>") + + self.expect("register info cpsr", patterns=["E:.*$"], matching=False) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_type_not_found(self): + """Check that lldb uses the default format if we don't find the enum type.""" + self.setup_register_test( + """\ + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register read cpsr", patterns=["\(E = 1\)$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_duplicated_evalue(self): + """Check that lldb only uses the last instance of a evalue for each + value.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="abc" value="1"/> + <evalue name="def" value="1"/> + <evalue name="geh" value="2"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="1" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 1 = def, 2 = geh$"]) + self.expect("register read cpsr", patterns=["\(E = def \| geh\)$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_duplicated(self): + """Check that lldb only uses the last instance of enums with the same + id.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="abc" value="1"/> + </enum> + <enum id="some_enum" size="4"> + <evalue name="def" value="1"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 1 = def$"]) + self.expect("register read cpsr", patterns=["\(E = def\)$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_use_first_valid(self): + """Check that lldb uses the first enum that parses correctly and ignores + the rest.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"/> + <enum size="4"> + <evalue name="invalid" value="1"/> + </enum> + <enum id="some_enum" size="4"> + <evalue name="valid" value="1"/> + </enum> + <enum id="another_enum" size="4"> + <evalue name="invalid" value="1"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 1 = valid$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_empty_name(self): + """Check that lldb ignores evalues with an empty name.""" + + # The only potential use case for empty names is to shadow an evalue + # declared later so that it's name is hidden should the debugger only + # pick one of them. This behaviour would be debugger specific so the protocol + # would probably not care or leave it up to us, and I think it's not a + # useful thing to allow. + + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="" value="1"/> + <evalue name="valid" value="2"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="1" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 2 = valid$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_invalid_value(self): + """Check that lldb ignores evalues with an invalid value.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="negative_dec" value="-1"/> + <evalue name="negative_hex" value="-0x1"/> + <evalue name="negative_bin" value="-0b1"/> + <evalue name="negative_float" value="-0.5"/> + <evalue name="nan" value="aardvark"/> + <evalue name="dec" value="1"/> + <evalue name="hex" value="0x2"/> + <evalue name="octal" value="03"/> + <evalue name="float" value="0.5"/> + <evalue name="bin" value="0b100"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="2" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect( + "register info cpsr", patterns=["E: 1 = dec, 2 = hex, 3 = octal, 4 = bin$"] + ) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_out_of_range(self): + """Check that lldb will not use an enum type if one of its evalues + exceeds the size of the field it is applied to.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="A" value="0"/> + <evalue name="B" value="2"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + # The whole eunm is rejected even if just 1 value is out of range. + self.expect("register info cpsr", patterns=["E: 0 = "], matching=False) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_ignore_unknown_attributes(self): + """Check that lldb ignores unknown attributes on an enum or evalue.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4" foo=\"bar\"> + <evalue name="valid" value="1" colour=\"red"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 1 = valid$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_required_attributes(self): + """Check that lldb rejects any evalue missing a name and/or value.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="foo"/> + <evalue value="1"/> + <evalue /> + <evalue name="valid" value="1"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="0" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect("register info cpsr", patterns=["E: 1 = valid$"]) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_name_xml_reserved_characters(self): + """Check that lldb converts reserved character replacements like & + when found in evalue names.""" + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="A&" value="0"/> + <evalue name="B"" value="1"/> + <evalue name="C'" value="2"/> + <evalue name="D>" value="3"/> + <evalue name="E<" value="4"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="E" start="0" end="2" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + self.expect( + "register info cpsr", + patterns=["E: 0 = A&, 1 = B\", 2 = C', 3 = D>, 4 = E<$"], + ) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_enum_value_range(self): + """Check that lldb ignores enums whose values would not fit into + their field.""" + + self.setup_register_test( + """\ + <enum id="some_enum" size="4"> + <evalue name="A" value="0"/> + <evalue name="B" value="1"/> + <evalue name="C" value="2"/> + <evalue name="D" value="3"/> + <evalue name="E" value="4"/> + </enum> + <flags id="cpsr_flags" size="4"> + <field name="foo" start="0" end="1" type="some_enum"/> + <field name="bar" start="2" end="10" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + # some_enum can apply to foo + self.expect( + "register info cpsr", patterns=["bar: 0 = A, 1 = B, 2 = C, 3 = D, 4 = E$"] + ) + # but not to bar + self.expect("register info cpsr", patterns=["foo: "], matching=False) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_evalue_value_limits(self): + """Check that lldb can handle an evalue for a field up to 64 bits + in size and anything greater is ignored.""" + + self.setup_register_test( + """\ + <enum id="some_enum" size="8"> + <evalue name="min" value="0"/> + <evalue name="max" value="0xffffffffffffffff"/> + <evalue name="invalid" value="0xfffffffffffffffff"/> + </enum> + <flags id="x0_flags" size="8"> + <field name="foo" start="0" end="63" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64" type="x0_flags"/> + <reg name="cpsr" regnum="33" bitsize="32"/>""" + ) + + self.expect( + "register info x0", patterns=["foo: 0 = min, 18446744073709551615 = max$"] + ) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_field_size_limit(self): + """Check that lldb ignores any field > 64 bits. We can't handle those + correctly.""" + + self.setup_register_test( + """\ + <flags id="x0_flags" size="8"> + <field name="invalid" start="0" end="64"/> + <field name="valid" start="0" end="63"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64" type="x0_flags"/> + <reg name="cpsr" regnum="33" bitsize="32"/>""" + ) + + self.expect( + "register info x0", substrs=["| 63-0 |\n" "|-------|\n" "| valid |"] + ) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_many_fields_same_enum(self): + """Check that an enum can be reused by many fields, and fields of many + registers.""" + + self.setup_register_test( + """\ + <enum id="some_enum" size="8"> + <evalue name="valid" value="1"/> + </enum> + <flags id="x0_flags" size="8"> + <field name="f1" start="0" end="0" type="some_enum"/> + <field name="f2" start="1" end="1" type="some_enum"/> + </flags> + <flags id="cpsr_flags" size="4"> + <field name="f1" start="0" end="0" type="some_enum"/> + <field name="f2" start="1" end="1" type="some_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64" type="x0_flags"/> + <reg name="cpsr" regnum="33" bitsize="32" type="cpsr_flags"/>""" + ) + + expected_info = [ + dedent( + """\ + f2: 1 = valid + + f1: 1 = valid$""" + ) + ] + self.expect("register info x0", patterns=expected_info) + + self.expect("register info cpsr", patterns=expected_info) + + expected_read = ["\(f2 = valid, f1 = valid\)$"] + self.expect("register read x0", patterns=expected_read) + self.expect("register read cpsr", patterns=expected_read) + + @skipIfXmlSupportMissing + @skipIfRemote + def test_fields_same_name_different_enum(self): + """Check that lldb does something sensible when there are two fields with + the same name, but their enum types differ.""" + + # It's unlikely anyone would do this intentionally but it is allowed by + # the protocol spec so we have to cope with it. + self.setup_register_test( + """\ + <enum id="foo_enum" size="8"> + <evalue name="foo_0" value="1"/> + </enum> + <enum id="foo_alt_enum" size="8"> + <evalue name="foo_1" value="1"/> + </enum> + <flags id="x0_flags" size="8"> + <field name="foo" start="0" end="0" type="foo_enum"/> + <field name="foo" start="1" end="1" type="foo_alt_enum"/> + </flags> + <reg name="pc" bitsize="64"/> + <reg name="x0" regnum="0" bitsize="64" type="x0_flags"/> + <reg name="cpsr" regnum="33" bitsize="32"/>""" + ) + + self.expect( + "register info x0", + patterns=[ + dedent( + """\ + foo: 1 = foo_1 + + foo: 1 = foo_0$""" + ) + ], + ) + + self.expect("register read x0", patterns=["\(foo = foo_1, foo = foo_0\)$"]) diff --git a/lldb/test/API/functionalities/step_scripted/Steps.py b/lldb/test/API/functionalities/step_scripted/Steps.py index 7527607be847..3325dba75365 100644 --- a/lldb/test/API/functionalities/step_scripted/Steps.py +++ b/lldb/test/API/functionalities/step_scripted/Steps.py @@ -47,7 +47,7 @@ class StepScripted(StepWithChild): # This plan does a step-over until a variable changes value. class StepUntil(StepWithChild): - def __init__(self, thread_plan, args_data, dict): + def __init__(self, thread_plan, args_data): self.thread_plan = thread_plan self.frame = thread_plan.GetThread().frames[0] self.target = thread_plan.GetThread().GetProcess().GetTarget() @@ -99,7 +99,7 @@ class StepUntil(StepWithChild): class StepReportsStopOthers: stop_mode_dict = {} - def __init__(self, thread_plan, args_data, dict): + def __init__(self, thread_plan, args_data): self.thread_plan = thread_plan self.key = str(args_data.GetValueForKey("token").GetUnsignedIntegerValue(1000)) diff --git a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py index 9891a9c23b50..7a4992abd8fc 100644 --- a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py +++ b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py @@ -7,7 +7,6 @@ import lldbsuite.test.lldbutil as lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * - class StepScriptedTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @@ -16,12 +15,14 @@ class StepScriptedTestCase(TestBase): self.main_source_file = lldb.SBFileSpec("main.c") self.runCmd("command script import Steps.py") + @expectedFailureAll() def test_standard_step_out(self): """Tests stepping with the scripted thread plan laying over a standard thread plan for stepping out.""" self.build() self.step_out_with_scripted_plan("Steps.StepOut") + @expectedFailureAll() def test_scripted_step_out(self): """Tests stepping with the scripted thread plan laying over an another scripted thread plan for stepping out.""" @@ -44,6 +45,7 @@ class StepScriptedTestCase(TestBase): stop_desc = thread.GetStopDescription(1000) self.assertIn("Stepping out from", stop_desc, "Got right description") + @expectedFailureAll() def test_misspelled_plan_name(self): """Test that we get a useful error if we misspell the plan class name""" self.build() @@ -62,10 +64,12 @@ class StepScriptedTestCase(TestBase): # Make sure we didn't let the process run: self.assertEqual(stop_id, process.GetStopID(), "Process didn't run") + @expectedFailureAll() def test_checking_variable(self): """Test that we can call SBValue API's from a scripted thread plan - using SBAPI's to step""" self.do_test_checking_variable(False) + @expectedFailureAll() def test_checking_variable_cli(self): """Test that we can call SBValue API's from a scripted thread plan - using cli to step""" self.do_test_checking_variable(True) @@ -126,7 +130,7 @@ class StepScriptedTestCase(TestBase): cmd = "thread step-scripted -C Steps.StepReportsStopOthers -k token -v %s" % ( token ) - if run_mode != None: + if run_mode is not None: cmd = cmd + " --run-mode %s" % (run_mode) if self.TraceOn(): print(cmd) diff --git a/lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py b/lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py index 58205553154b..f68eb4196c12 100644 --- a/lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py +++ b/lldb/test/API/functionalities/stop-on-sharedlibrary-load/TestStopOnSharedlibraryEvents.py @@ -99,7 +99,7 @@ class TestStopOnSharedlibraryEvents(TestBase): backstop_bkpt_2.GetNumLocations(), 0, "Set our third breakpoint" ) - if bkpt_modifier == None: + if bkpt_modifier is None: process.Continue() self.assertState( process.GetState(), lldb.eStateStopped, "We didn't stop for the load" diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/Makefile b/lldb/test/API/functionalities/target-new-solib-notifications/Makefile index 99998b20bcb0..6c61d210eeb2 100644 --- a/lldb/test/API/functionalities/target-new-solib-notifications/Makefile +++ b/lldb/test/API/functionalities/target-new-solib-notifications/Makefile @@ -1,3 +1,23 @@ -CXX_SOURCES := main.cpp - -include Makefile.rules +CXX_SOURCES := main.cpp
+LD_EXTRAS := -L. -l_d -l_c -l_a -l_b +
+a.out: lib_b lib_a lib_c lib_d
+
+include Makefile.rules
+
+lib_a: lib_b
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \ + LD_EXTRAS="-L. -l_b" +
+lib_b:
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b +
+lib_c:
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c +
+lib_d:
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py index abf761fb3420..47af6909b728 100644 --- a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py +++ b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py @@ -9,22 +9,47 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +@skipUnlessPlatform(["linux"] + lldbplatformutil.getDarwinOSTriples()) class ModuleLoadedNotifysTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True # At least DynamicLoaderDarwin and DynamicLoaderPOSIXDYLD should batch up # notifications about newly added/removed libraries. Other DynamicLoaders may # not be written this way. - @skipUnlessPlatform(["linux"] + lldbplatformutil.getDarwinOSTriples()) def setUp(self): # Call super's setUp(). TestBase.setUp(self) # Find the line number to break inside main(). self.line = line_number("main.cpp", "// breakpoint") + def setup_test(self, solibs): + if lldb.remote_platform: + path = lldb.remote_platform.GetWorkingDirectory() + for f in solibs: + lldbutil.install_to_target(self, self.getBuildArtifact(f)) + else: + path = self.getBuildDir() + if self.dylibPath in os.environ: + sep = self.platformContext.shlib_path_separator + path = os.environ[self.dylibPath] + sep + path + self.runCmd( + "settings append target.env-vars '{}={}'".format(self.dylibPath, path) + ) + self.default_path = path + def test_launch_notifications(self): """Test that lldb broadcasts newly loaded libraries in batches.""" + + expected_solibs = [ + "lib_a." + self.platformContext.shlib_extension, + "lib_b." + self.platformContext.shlib_extension, + "lib_c." + self.platformContext.shlib_extension, + "lib_d." + self.platformContext.shlib_extension, + ] + self.build() + self.setup_test(expected_solibs) + exe = self.getBuildArtifact("a.out") self.dbg.SetAsync(False) @@ -70,6 +95,8 @@ class ModuleLoadedNotifysTestCase(TestBase): total_modules_added_events = 0 total_modules_removed_events = 0 already_loaded_modules = [] + max_solibs_per_event = 0 + max_solib_chunk_per_event = [] while listener.GetNextEvent(event): if lldb.SBTarget.EventIsTargetEvent(event): if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded: @@ -91,12 +118,17 @@ class ModuleLoadedNotifysTestCase(TestBase): "{} is already loaded".format(module), ) already_loaded_modules.append(module) - if self.TraceOn(): - added_files.append(module.GetFileSpec().GetFilename()) + added_files.append(module.GetFileSpec().GetFilename()) if self.TraceOn(): # print all of the binaries that have been added print("Loaded files: %s" % (", ".join(added_files))) + # We will check the latest biggest chunk of loaded solibs. + # We expect all of our solibs in the last chunk of loaded modules. + if solib_count >= max_solibs_per_event: + max_solib_chunk_per_event = added_files.copy() + max_solibs_per_event = solib_count + if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded: solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) total_modules_removed_events += 1 @@ -115,9 +147,7 @@ class ModuleLoadedNotifysTestCase(TestBase): # binaries in batches. Check that we got back more than 1 solib per event. # In practice on Darwin today, we get back two events for a do-nothing c # program: a.out and dyld, and then all the rest of the system libraries. - # On Linux we get events for ld.so, [vdso], the binary and then all libraries. - - avg_solibs_added_per_event = round( - float(total_solibs_added) / float(total_modules_added_events) - ) - self.assertGreater(avg_solibs_added_per_event, 1) + # On Linux we get events for ld.so, [vdso], the binary and then all libraries, + # but the different configurations could load a different number of .so modules + # per event. + self.assertLessEqual(set(expected_solibs), set(max_solib_chunk_per_event)) diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/a.cpp b/lldb/test/API/functionalities/target-new-solib-notifications/a.cpp new file mode 100644 index 000000000000..778b46ed5cef --- /dev/null +++ b/lldb/test/API/functionalities/target-new-solib-notifications/a.cpp @@ -0,0 +1,3 @@ +extern "C" int b_function();
+
+extern "C" int a_function() { return b_function(); }
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/b.cpp b/lldb/test/API/functionalities/target-new-solib-notifications/b.cpp new file mode 100644 index 000000000000..4f1a4032ee0e --- /dev/null +++ b/lldb/test/API/functionalities/target-new-solib-notifications/b.cpp @@ -0,0 +1 @@ +extern "C" int b_function() { return 500; }
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/c.cpp b/lldb/test/API/functionalities/target-new-solib-notifications/c.cpp new file mode 100644 index 000000000000..8abd1b155a75 --- /dev/null +++ b/lldb/test/API/functionalities/target-new-solib-notifications/c.cpp @@ -0,0 +1 @@ +extern "C" int c_function() { return 600; }
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/d.cpp b/lldb/test/API/functionalities/target-new-solib-notifications/d.cpp new file mode 100644 index 000000000000..58888a29ba32 --- /dev/null +++ b/lldb/test/API/functionalities/target-new-solib-notifications/d.cpp @@ -0,0 +1 @@ +extern "C" int d_function() { return 700; }
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/main.cpp b/lldb/test/API/functionalities/target-new-solib-notifications/main.cpp index 00130c93b886..77b38c5ccdc6 100644 --- a/lldb/test/API/functionalities/target-new-solib-notifications/main.cpp +++ b/lldb/test/API/functionalities/target-new-solib-notifications/main.cpp @@ -1,6 +1,16 @@ -#include <stdio.h> -int main () -{ - puts("running"); // breakpoint here - return 0; -} +#include <stdio.h>
+
+extern "C" int a_function();
+extern "C" int c_function();
+extern "C" int b_function();
+extern "C" int d_function();
+
+int main() {
+ a_function();
+ b_function();
+ c_function();
+ d_function();
+
+ puts("running"); // breakpoint here
+ return 0;
+}
diff --git a/lldb/test/API/functionalities/thread_plan/wrap_step_over.py b/lldb/test/API/functionalities/thread_plan/wrap_step_over.py index 802aaf2d3ffd..ebb795abfa0e 100644 --- a/lldb/test/API/functionalities/thread_plan/wrap_step_over.py +++ b/lldb/test/API/functionalities/thread_plan/wrap_step_over.py @@ -2,7 +2,7 @@ import lldb class WrapStepOver: - def __init__(self, thread_plan, args_data, dict): + def __init__(self, thread_plan, args_data): self.plan = thread_plan thread = thread_plan.GetThread() target = thread.GetProcess().GetTarget() diff --git a/lldb/test/API/functionalities/type_types/Makefile b/lldb/test/API/functionalities/type_types/Makefile new file mode 100644 index 000000000000..3d0b98f13f3d --- /dev/null +++ b/lldb/test/API/functionalities/type_types/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/lldb/test/API/functionalities/type_types/TestFindTypes.py b/lldb/test/API/functionalities/type_types/TestFindTypes.py new file mode 100644 index 000000000000..42b5c4cfaaf7 --- /dev/null +++ b/lldb/test/API/functionalities/type_types/TestFindTypes.py @@ -0,0 +1,66 @@ +""" +Test the SBModule and SBTarget type lookup APIs to find multiple types. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeFindFirstTestCase(TestBase): + def test_find_first_type(self): + """ + Test SBTarget::FindTypes() and SBModule::FindTypes() APIs. + + We had issues where our declaration context when finding types was + incorrectly calculated where a type in a namepace, and a type in a + function that was also in the same namespace would match a lookup. For + example: + + namespace a { + struct Foo { + int foo; + }; + + unsigned foo() { + typedef unsigned Foo; + Foo foo = 12; + return foo; + } + } // namespace a + + + Previously LLDB would calculate the declaration context of "a::Foo" + correctly, but incorrectly calculate the declaration context of "Foo" + from within the foo() function as "a::Foo". Adding tests to ensure this + works correctly. + """ + self.build() + target = self.createTestTarget() + exe_module = target.GetModuleAtIndex(0) + self.assertTrue(exe_module.IsValid()) + # Test the SBTarget and SBModule APIs for FindFirstType + for api in [target, exe_module]: + # We should find the "a::Foo" but not the "Foo" type in the function + types = api.FindTypes("a::Foo") + self.assertEqual(types.GetSize(), 1) + type_str0 = str(types.GetTypeAtIndex(0)) + self.assertIn('struct Foo {', type_str0) + + # When we search by type basename, we should find any type whose + # basename matches "Foo", so "a::Foo" and the "Foo" type in the + # function. + types = api.FindTypes("Foo") + self.assertEqual(types.GetSize(), 2) + type_str0 = str(types.GetTypeAtIndex(0)) + type_str1 = str(types.GetTypeAtIndex(1)) + # We don't know which order the types will come back as, so + self.assertEqual(set([str(t).split('\n')[0] for t in types]), set(["typedef Foo", "struct Foo {"])) + + # When we search by type basename with "::" prepended, we should + # only types in the root namespace which means only "Foo" type in + # the function. + types = api.FindTypes("::Foo") + self.assertEqual(types.GetSize(), 1) + type_str0 = str(types.GetTypeAtIndex(0)) + self.assertIn('typedef Foo', type_str0) diff --git a/lldb/test/API/functionalities/type_types/main.cpp b/lldb/test/API/functionalities/type_types/main.cpp new file mode 100644 index 000000000000..095328932cdc --- /dev/null +++ b/lldb/test/API/functionalities/type_types/main.cpp @@ -0,0 +1,15 @@ +namespace a { +struct Foo {}; + +unsigned foo() { + typedef unsigned Foo; + Foo foo = 12; + return foo; +} +} // namespace a + +int main() { + a::Foo f = {}; + a::foo(); + return 0; +} |
