Bogus unresolved references to vtable when building with lto

Dave Gittins
Wed Jun 15 12:29:00 GMT 2016


I have a program that unexpectedly hit a linker error when building on
x86_64 Linux with ld / gcc 6 and using LTO.

Sorry but I have not managed to extract a sensible test case so far
due to the large size (and sensitivity) of the code base. I am still
trying to chop it down without losing the result. Meanwhile I'll
describe the setup and hope someone can help me.

 * the main program builds with LTO and aggressive optimisation
 * it links against a library libfoo, built elsewhere with gcc but without LTO
 * foo.h contains:
class Foo { virtual ~Foo() {}; virtual blah() = 0; };
 * libfoo.a contains the vtable for Foo in multiple object files
(using comdat groups)
 * classes that inherit from Foo are used in the program

 1. with gcc 5.2 using -flto -O3: OK
 2. with gcc 6.1 using -O3 (no LTO): OK
 3. with gcc 6.1 using -flto -O3 -fno-strict-aliasing: OK
 4. with gcc 6.1 using -flto -O3: linker error: unresolved reference
to vtable for Foo

I am not very familiar with the inner workings of LTO, but re-running
the link step with --save-temps and looking at the output files, I can
see one difference between cases 3 and 4: in case 3 the vtable symbol
is present in a .s file for the target (e.g. _ZTVN3FooE seems to be
defined) but in the failing case 4 it is called
_ZTVN3FooE.lto_priv.7288. In both cases, the lm.res file contains
something like this:

lm.res:194 857f97bd35affadb PREVAILING_DEF _ZTVN3FooE
lm.res:9895 38fe32bfc94fb92d PREEMPTED_IR _ZTVN3FooE
lm.res:461 979b2bacd9a23781 PREEMPTED_IR _ZTVN3FooE
lm.res:403 d7cb462ac76ae78f PREEMPTED_IR _ZTVN3FooE
lm.res:1625 1c237136eccb8e22 PREEMPTED_IR _ZTVN3FooE
lm.res:194 dc12ecd964eef823 PREEMPTED_IR _ZTVN3FooE
lm.res:194 b0ceb27c32d02e6b PREEMPTED_IR _ZTVN3FooE
lm.res:194 f7293254f09d2c44 PREEMPTED_IR _ZTVN3FooE
lm.res:9490 fa5a2b6c2738a867 PREEMPTED_IR _ZTVN3FooE

I also added this as a comment on this bug report but now I am not
sure if it's really directly related:

I think the LTO script is telling the linker that it will provide this
symbol, and then providing it as a global symbol in the working case,
but then in the failing case it is making it local, or something like
that? I assume the optimiser came to some relevant conclusion about
the required visibility of the vtable...?

Any help appreciated.


More information about the Gcc-help mailing list