This is an archive of the discontinued LLVM Phabricator instance.

[lldb][NFC] Allow range-based for loops over DWARFDIE's children
ClosedPublic

Authored by teemperor on May 26 2021, 8:39 AM.

Details

Summary

This patch adds the ability to get a DWARFDIE's children as an LLVM range.

This way we can use for range loops to iterate over them and we can use
LLVM's algorithms like llvm::all_of to query all children.

The implementation has to do some small shenanigans as the iterator
needs to store a DWARFDIE, but a DWARFDIE container is also a DWARFDIE
so it can't return the iterator by value. I just made the children getter a
templated function to avoid the cyclic dependency.

Diff Detail

Event Timeline

teemperor created this revision.May 26 2021, 8:39 AM
teemperor requested review of this revision.May 26 2021, 8:39 AM
shafik added inline comments.May 26 2021, 1:30 PM
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
117

I think:

bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) {
  return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
}

will do the same thing but maybe I am confused.

Maybe we should have a unit test?

teemperor updated this revision to Diff 352666.Jun 17 2021, 3:34 AM
  • Added a unit test (thanks Shafik!)
teemperor added inline comments.Jun 17 2021, 3:36 AM
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
117

That's the DWARFDIE::operator== implementation called below and this special case is because of the comment one line above (we need to match the end iterator if it's default constructed when GetSibling() returns a DWARFDIE that has a valid CU but a null DIE).

werat accepted this revision.Jul 7 2021, 5:26 AM
This revision is now accepted and ready to land.Jul 7 2021, 5:26 AM
This revision was landed with ongoing or failed builds.Jul 22 2021, 6:03 AM
This revision was automatically updated to reflect the committed changes.
dblaikie added inline comments.
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
97–105

rather than a temeplate, what if it were code something like this: https://godbolt.org/z/3abeK3EPx ?

wallace added subscribers: clayborg, wallace.EditedAug 4 2021, 1:09 AM

This breaks debugging in many cases :( Many of my users started reporting crashes in LLDB when setting source line breakpoints or printing out variables.

For example, a simple command like (lldb) b TransAttr.cpp:758 causes a crash and has the following stack trace

thread #1, name = 'lldb', stop reason = signal SIGSEGV: invalid address (fault address: 0x10)
 * frame #0: 0x00007f1c2b642caa liblldb.so.14`DWARFUnit::GetSymbolFileDWARF(this=0x0000000000000000) const at DWARFUnit.h:194:56
   frame #1: 0x00007f1c2bd46ce4 liblldb.so.14`SymbolFileDWARF::GetTypeSystem(unit=0x0000000000000000) at SymbolFileDWARF.cpp:3880:15
   frame #2: 0x00007f1c2bd3b29b liblldb.so.14`SymbolFileDWARF::GetDWARFParser(unit=0x0000000000000000) at SymbolFileDWARF.cpp:3884:29
   frame #3: 0x00007f1c2bd8cb87 liblldb.so.14`DWARFASTParserClang::CopyUniqueClassMethodTypes(this=0x0000000001eaa920, src_class_die=0x00007ffe9ff0ff38, dst_class_die=0x00007ffe9ff0fe48, class_type=0x0000000001d42c10, failures=size=0) at DWARFASTParserClang.cpp:3572:11
   frame #4: 0x00007f1c2bd891fd liblldb.so.14`DWARFASTParserClang::ParseSubroutine(this=0x0000000001eaa920, die=0x00007ffe9ff10778, attrs=0x00007ffe9ff101b0) at DWARFASTParserClang.cpp:1025:15
   frame #5: 0x00007f1c2bd85080 liblldb.so.14`DWARFASTParserClang::ParseTypeFromDWARF(this=0x0000000001eaa920, sc=0x00007ffe9ff105d0, die=0x00007ffe9ff10778, type_is_new_ptr=0x0000000000000000) at DWARFASTParserClang.cpp:522:15
   frame #6: 0x00007f1c2bd401fb liblldb.so.14`SymbolFileDWARF::ParseType(this=0x00000000004610a0, sc=0x00007ffe9ff105d0, die=0x00007ffe9ff10778, type_is_new_ptr=0x0000000000000000) at SymbolFileDWARF.cpp:2946:31
   frame #7: 0x00007f1c2bd3b70f liblldb.so.14`SymbolFileDWARF::GetTypeForDIE(this=0x00000000004610a0, die=0x00007ffe9ff10778, resolve_function_context=false) at SymbolFileDWARF.cpp:2560:17
   frame #8: 0x00007f1c2bd3a4bd liblldb.so.14`SymbolFileDWARF::ResolveType(this=0x00000000004610a0, die=0x00007ffe9ff10778, assert_not_being_parsed=true, resolve_function_context=false) at SymbolFileDWARF.cpp:1568:18
   frame #9: 0x00007f1c2bd17500 liblldb.so.14`DWARFDIE::ResolveType(this=0x00007ffe9ff10778) const at DWARFDIE.cpp:350:24
   frame #10: 0x00007f1c2bd3a365 liblldb.so.14`SymbolFileDWARF::ResolveTypeUID(this=0x00000000004610a0, type_uid=57283337) at SymbolFileDWARF.cpp:1437:21
   frame #11: 0x00007f1c2b73037e liblldb.so.14`lldb_private::Function::GetType(this=0x0000000001cd5ed0) at Function.cpp:515:24
   frame #12: 0x00007f1c2b73017a liblldb.so.14`lldb_private::Function::GetStartLineSourceInfo(this=0x0000000001cd5ed0, source_file=0x00007ffe9ff109e0, line_no=0x00007ffe9ff109dc) at Function.cpp:252:3
   frame #13: 0x00007f1c2b515a5e liblldb.so.14`lldb_private::BreakpointResolverFileLine::FilterContexts(this=0x0000000001f61c00, sc_list=0x00007ffe9ff10d00, is_relative=true) at BreakpointResolverFileLine.cpp:162:20
   frame #14: 0x00007f1c2b5163d3 liblldb.so.14`lldb_private::BreakpointResolverFileLine::SearchCallback(this=0x0000000001f61c00, filter=0x0000000001fab770, context=0x00007ffe9ff10d68, addr=0x0000000000000000) at BreakpointResolverFileLine.cpp:254:3
   frame #15: 0x00007f1c2b5cae2a liblldb.so.14`lldb_private::SearchFilter::DoModuleIteration(this=0x0000000001fab770, context=0x00007ffe9ff10f28, searcher=0x0000000001f61c00) at SearchFilter.cpp:271:20
   frame #16: 0x00007f1c2b5cabb9 liblldb.so.14`lldb_private::SearchFilter::Search(this=0x0000000001fab770, searcher=0x0000000001f61c00) at SearchFilter.cpp:216:3
   frame #17: 0x00007f1c2b50c24e liblldb.so.14`lldb_private::BreakpointResolver::ResolveBreakpoint(this=0x0000000001f61c00, filter=0x0000000001fab770) at BreakpointResolver.cpp:177:10
   frame #18: 0x00007f1c2b4e93e6 liblldb.so.14`lldb_private::Breakpoint::ResolveBreakpoint(this=0x00000000003c76d0) at Breakpoint.cpp:443:20
   frame #19: 0x00007f1c2b851596 liblldb.so.14`lldb_private::Target::AddBreakpoint(this=0x000000000044dad0, bp_sp=std::__shared_ptr<lldb_private::Breakpoint, __gnu_cxx::_S_atomic>::element_type @ 0x00000000003c76d0, internal=false) at Target.cpp:662:10
   frame #20: 0x00007f1c2b852f64 liblldb.so.14`lldb_private::Target::CreateBreakpoint(this=0x000000000044dad0, filter_sp=std::__shared_ptr<lldb_private::SearchFilter, __gnu_cxx::_S_atomic>::element_type @ 0x0000000001fab770, resolver_sp=std::__shared_ptr<lldb_private::BreakpointResolver, __gnu_cxx::_S_atomic>::element_type @ 0x0000000001f61c00, internal=false, request_hardware=false, resolve_indirect_symbols=true) at Target.cpp:641:5
   frame #21: 0x00007f1c2b85342f liblldb.so.14`lldb_private::Target::CreateBreakpoint(this=0x000000000044dad0, containingModules=0x0000000000348b80, file=0x00007ffe9ff11768, line_no=758, column=0, offset=0, check_inlines=eLazyBoolYes, skip_prologue=eLazyBoolYes, internal=false, hardware=false, move_to_nearest_code=eLazyBoolYes) at Target.cpp:384:10
   frame #22: 0x00007f1c2d6895f0 liblldb.so.14`CommandObjectBreakpointSet::DoExecute(this=0x0000000000348750, command=0x00007ffe9ff11908, result=0x00007ffe9ff123f8) at CommandObjectBreakpoint.cpp:581:22
   frame #23: 0x00007f1c2b6cfed4 liblldb.so.14`lldb_private::CommandObjectParsed::Execute(this=0x0000000000348750, args_string="--file 'TransAttr.cpp' --line 758", result=0x00007ffe9ff123f8) at CommandObject.cpp:995:19
   frame #24: 0x00007f1c2b6a5062 liblldb.so.14`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000000333650, command_line="breakpoint set --file 'TransAttr.cpp' --line 758", lazy_add_to_history=eLazyBoolCalculate, result=0x00007ffe9ff123f8) at CommandInterpreter.cpp:1804:14
   frame #25: 0x00007f1c2d700897 liblldb.so.14`lldb_private::CommandObjectRegexCommand::DoExecute(this=0x000000000038ab60, command=(Data = "TransAttr.cpp:758", Length = 17), result=0x00007ffe9ff123f8) at CommandObjectRegexCommand.cpp:56:28
   frame #26: 0x00007f1c2b6d0125 liblldb.so.14`lldb_private::CommandObjectRaw::Execute(this=0x000000000038ab60, args_string="TransAttr.cpp:758", result=0x00007ffe9ff123f8) at CommandObject.cpp:1017:17
   frame #27: 0x00007f1c2b6a5062 liblldb.so.14`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000000333650, command_line="b TransAttr.cpp:758", lazy_add_to_history=eLazyBoolCalculate, result=0x00007ffe9ff123f8) at CommandInterpreter.cpp:1804:14
   frame #28: 0x00007f1c2b6a9a7f liblldb.so.14`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x0000000000333650, io_handler=0x0000000001f44ee0, line=error: summary string parsing error) at CommandInterpreter.cpp:2848:3
   frame #29: 0x00007f1c2b5799de liblldb.so.14`lldb_private::IOHandlerEditline::Run(this=0x0000000001f44ee0) at IOHandler.cpp:579:22
   frame #30: 0x00007f1c2b53c323 liblldb.so.14`lldb_private::Debugger::RunIOHandlers(this=0x0000000000331ca0) at Debugger.cpp:877:16
   frame #31: 0x00007f1c2b6ab353 liblldb.so.14`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x0000000000333650, options=0x00007ffe9ff12750) at CommandInterpreter.cpp:3094:16
   frame #32: 0x00007f1c2aea5281 liblldb.so.14`lldb::SBDebugger::RunCommandInterpreter(this=0x00007ffe9ff12bd0, auto_handle_events=true, spawn_thread=false) at SBDebugger.cpp:1214:42
   frame #33: 0x000000000022c48e lldb`Driver::MainLoop(this=0x00007ffe9ff12bb0) at Driver.cpp:676:18
   frame #34: 0x000000000022d1c1 lldb`main(argc=2, argv=0x00007ffe9ff131c8) at Driver.cpp:944:26
   frame #35: 0x00007f1c266ddd95 libc.so.6`__libc_start_main(main=(lldb`main at Driver.cpp:870), argc=2, argv=0x00007ffe9ff131c8, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007ffe9ff131b8) at libc-start.c:308:16
   frame #36: 0x000000000022894a lldb`_start at start.S:120

An interesting part is frame 3:

(lldb) frame select 3
frame #3: 0x00007f1c2bd8cb87 liblldb.so.14`DWARFASTParserClang::CopyUniqueClassMethodTypes(this=0x0000000001eaa920, src_class_die=0x00007ffe9ff0ff38, dst_class_die=0x00007ffe9ff0fe48, class_type=0x0000000001d42c10, failures=size=0) at DWARFASTParserClang.cpp:3572:11
   3569
   3570   DWARFASTParserClang *src_dwarf_ast_parser =
   3571       static_cast<DWARFASTParserClang *>(
-> 3572           SymbolFileDWARF::GetDWARFParser(*src_die.GetCU()));
   3573   DWARFASTParserClang *dst_dwarf_ast_parser =
   3574       static_cast<DWARFASTParserClang *>(
   3575           SymbolFileDWARF::GetDWARFParser(*dst_die.GetCU()));
(lldb) p src_die
(DWARFDIE) $0 = {
  DWARFBaseDIE = {
    m_cu = nullptr
    m_die = nullptr
  }
}

This makes me think that at some points the iterator is leaking invalid DIEs. Reverting this diff fixes the issues locally. So I think we should revert this until we can make a more stable patch.

cc: @clayborg