This is an archive of the discontinued LLVM Phabricator instance.

[lldb][DWARFASTParserClang] Attach linkage name to ctors/dtors if missing
AcceptedPublic

Authored by Michael137 on Feb 9 2023, 7:26 AM.

Details

Summary

Summary

This patch addresses the case where we have a DW_AT_external
subprogram for a constructor (and/or destructor) that doesn't carry
a DW_AT_linkage_name attribute. The corresponding DIE(s) that
represent the definition will have a linkage name, but if the name
contains constructs that LLDBs fallback mechanism for guessing mangled
names to resolve external symbols doesn't support (e.g., abi-tags)
then we end up failing to resolve the function call.

We address this by trying to find the linkage name before we create
the constructor/destructor decl, which will get attached using
an AsmLabelAttr to make symbol resolution easier.

This is useful for cases where we try to evaluate expressions that return libcxx
types whose constructors/destructors are labelled with ABI tags (e.g., std::shared_ptr)

Testing

  • Added API test

Diff Detail

Event Timeline

Michael137 created this revision.Feb 9 2023, 7:26 AM
Herald added a project: Restricted Project. · View Herald Transcript
Michael137 requested review of this revision.Feb 9 2023, 7:26 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 9 2023, 7:26 AM
Michael137 edited the summary of this revision. (Show Details)Feb 9 2023, 7:27 AM
Michael137 updated this revision to Diff 496127.Feb 9 2023, 7:34 AM
  • clang-format
  • Minor cleanup
Michael137 updated this revision to Diff 496128.Feb 9 2023, 7:37 AM
  • add CHECK-NEXT to test
  • reword commit
Michael137 retitled this revision from [WIP][lldb][DWARFASTParserClang] Attach linkage name to ctors/dtors if missing to [lldb][DWARFASTParserClang] Attach linkage name to ctors/dtors if missing.Feb 9 2023, 7:37 AM
Michael137 updated this revision to Diff 496131.Feb 9 2023, 7:46 AM
  • Simplify test
aprantl accepted this revision.Feb 9 2023, 11:24 AM

Nice!

lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
3

This sentence misses a verb :-)

This revision is now accepted and ready to land.Feb 9 2023, 11:24 AM
JDevlieghere added inline comments.Feb 9 2023, 1:55 PM
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
914–915
Michael137 updated this revision to Diff 496300.Feb 9 2023, 5:46 PM
  • Reduce scope of local var
Michael137 marked an inline comment as done.Feb 9 2023, 5:47 PM
Michael137 added a comment.EditedFeb 9 2023, 5:49 PM

On a release build, for a type instantiated with 50,000 distinct types I get the following results:

Benchmark 1: ./lldb-build-release-with-patch/bin/lldb a.out -o "b main" -o "r" -o "p b.sinkWrapper(b.getWrapper())"
  Time (mean ± σ):      7.599 s ±  0.125 s    [User: 6.836 s, System: 0.371 s]
  Range (min … max):    7.392 s …  7.762 s    10 runs

Benchmark 1: ./lldb-build-release-no-patch/bin/lldb a.out -o "b main" -o "r" -o "p b.sinkWrapper(b.getWrapper())"
  Time (mean ± σ):      7.303 s ±  0.113 s    [User: 6.563 s, System: 0.348 s]
  Range (min … max):    7.073 s …  7.468 s    10 runs

So a 0.3s slowdown (but including startup)

This seems to cause many lldb failures https://lab.llvm.org/buildbot/#/builders/68/builds/47790

Argh thanks for reporting, let me revert for now and try on my linux machine

labath added inline comments.Feb 13 2023, 6:07 AM
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
29

I think this could be a bit of a problem, because (as you've probably found out by now) there are multiple versions of a single constructor, and the asm label seems to cause clang to coalesce them. In the simple test case below that doesn't matter, as the two constructors are identical, but things might be different if the class had virtual bases. (i.e., it could cause us to call the wrong constructor and blow up).

lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h
7

superfluous semicolon

Michael137 added inline comments.Feb 13 2023, 7:26 AM
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
29

I may be misunderstanding, but wouldn't they just get added as extra CXXConstructorDecls on the AST with distinct AsmLabels? Each constructor subprogram DIE links to some specification, which is the definition of the constructor we should call. That's where we get the linkage name from. Playing around with virtual bases I didn't yet manage to come up with a counterexample of where we would pick the wrong constructor

Although I did now notice that there's an extra destructor call in some cases where I didn't expect one before. Maybe that's a manifestation of the issue you describe. Investigating...

Michael137 added inline comments.Feb 13 2023, 7:29 AM
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
29

You probably mean multiple constructor definitions can point to the same specification DIE? In which case we would choose the first one happen to see. To what extent can these definitions differ?

labath added inline comments.Feb 13 2023, 9:30 AM
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
29

I mean the "subobject" and "full" constructor (and destructor) variants. There is only a single DIE for the constructor (presumably, because there is only one constructor at the source level), but there are two functions in the object.

You can try the following program to get an idea of what's happening:

struct A {
  A(int) {}
  A(float) {}
};

struct B : virtual A {
  B();
};
B::B() : A(47) {}

struct C : B {
  C() : A(4.7f) {}
};

int main() {
  B b;
  C c;
}

In this program, the b constructor calls the full object constructor for B (_ZN1BC1Ev), whereas the B object constructed as a part of the c full object calls the base object constructor for B (_ZN1BC2Ev).

Michael137 added inline comments.Feb 13 2023, 9:51 AM
lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py
29

Ok that's very useful, thanks!
That does indeed look problematic. Will again revert for now. If we want to go down the linkage-name path I'd have to see if there's more context in DWARFASTParserClang that we can use to filter down to the correct definition. Maybe there's a better way to get these symbols resolved. Don't think the fallback to a guessed mangled name can save us here though

Michael137 reopened this revision.Feb 13 2023, 10:10 AM
This revision is now accepted and ready to land.Feb 13 2023, 10:10 AM