[llvm-bugs] [Bug 40202] New: LTO COMDAT elimination can eliminate prevailing symbols

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Jan 2 04:30:18 PST 2019


https://bugs.llvm.org/show_bug.cgi?id=40202

            Bug ID: 40202
           Summary: LTO COMDAT elimination can eliminate prevailing
                    symbols
           Product: libraries
           Version: 7.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Linker
          Assignee: unassignedbugs at nondot.org
          Reporter: CFSworks at gmail.com
                CC: llvm-bugs at lists.llvm.org

Created attachment 21283
  --> https://bugs.llvm.org/attachment.cgi?id=21283&action=edit
A minimal example project that crashes Clang

I've attached an example project that demonstrates this bug. When building it
(w/ make), the following error is reported:

Alias must point to a definition
void (%class.X*)* @_ZN1XIiED1Ev
LLVM ERROR: Broken module found, compilation aborted!

---

As I understand it, what's happening is:

common.h contains a template class X (which, being a template, is subject to
instantiation in multiple translation units under the ODR) with a virtual
destructor and a base class with a destructor of its own. This means that the
class would contain the complete set of D0, D1, and D2 destructors.

b.cpp performs an explicit instantiation of X<int> - so b.o contains all 3
destructors (grouped under the D5 COMDAT).

a.cpp contains an inline (due to -O1) copy of the X<int> constructor, which
means a.o contains a copy of X<int>'s vtable and X<int>'s D0 destructor.

When it comes time to link, if a.o's D0 symbol prevails over b.o's copy of the
same, https://reviews.llvm.org/D34803 means that the entire D5 COMDAT from b.o
must be eliminated. This happens by converting all affected symbols to
available_externally linkage and deleting the COMDAT.

The crash, as seen, is caused by the fact that D1 is an alias of D2, and the
logic that eliminates the COMDAT doesn't check if D2 is an aliasee first.

However, just handling aliased symbols isn't good enough here: even if D1 was a
full definition rather than an alias, then COMDAT elimination would mean that
the prevailing copies of the D1/D2 destructors aren't getting included in the
output binary. This negates the whole purpose of the explicit instantiation in
b.cpp (a user of the shared library might be relying on that instantiation),
and could even result in a broken binary if b.cpp contained a non-inline call
to D1/D2.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190102/e328a771/attachment.html>


More information about the llvm-bugs mailing list