[cfe-dev] Vtable code generation options
John McCall via cfe-dev
cfe-dev at lists.llvm.org
Tue Aug 22 11:01:05 PDT 2017
> On Aug 21, 2017, at 11:35 AM, Serhii Huralnik via cfe-dev <cfe-dev at lists.llvm.org> wrote:
> Hey,
>
> First of all sorry if this mail should be targeted to some other list, but seems like no one except Clang people can help with my issue. I'm using OS X environment, but probably it is common to any ELF-based system.
>
> It is about how virtual tables are generated and which link relocations are needed to make them work. I have a very simple example that creates vtable with one slot for pure virtual:
>
> class Foo {
> public:
> virtual void bar() = 0;
> };
>
> class Baz : public Foo {
> public:
> virtual void bar() override;
> };
>
> void Baz::bar() {}
>
> void xyz() { Baz().bar(); }
>
> Compiler produces next vtable layout for Foo:
>
> __ZTV3Foo:
> .quad 0
> .quad __ZTI3Foo
> .quad ___cxa_pure_virtual
>
> It is easy to find that linker will produce absolute relocation for symbol ___cxa_pure_virtual. In most cases this relocation will be proceeded by dynamic linker. Lets now assume that our loadable module has a lot of similar vtables for miscellaneous classes. Each slot for pure method will cause new absolute relocation for the same symbol and we end up with binary that contains a huge bunch of relocation entries that refer to the same symbol. E.g. here are few relocation entries for Android dynamic library built with clang-3.6 from Android NDK:
>
> ...
> 00332fe4 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332fe8 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332fec 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332ff0 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332ff4 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332ff8 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 00332ffc 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 003330f4 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 003330f8 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> 003330fc 00030502 R_ARM_ABS32 00000000 __cxa_pure_virtual
> ...
>
> I guess such situation is pretty common for large projects. If dynamic linker is not clever enough to detect such situation - it will waste time with lookups for the same symbol over and over.
ELF will use a single symbol table entry for all of these relocations. By design, that makes it quite easy for the loader to only perform the lookup once. If we assume that the loader does its job efficiently, introducing an image-local thunk would only actually be beneficial in a pre-linked image. That could still be a reasonable feature request — "I'm going to prelink this image and would like the compiler + linker to generate code that optimizes load times with that in mind" — but I believe prelinking is somewhat disfavored, so you might have trouble getting traction on it.
Now, if you're actually profiling your loads and seeing redundant lookups — either because the linker is emitting redundant symbol table entries or because the loader isn't taking advantage of the entries being unique — that does sound like a bug, but it's a linker or loader bug, not a compiler bug.
John.
More information about the cfe-dev
mailing list