This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Using the PLT for vtables (or not)


On Fri, Dec 05, 2003 at 02:14:36AM -0800, Brian Ryner wrote:
> Jakub Jelinek wrote:
> >Actually this is not completely true.
> >Pointers in vtables normally resolve to:
> >a) the actual method in the binary if it has been linked into the binary
> >b) to the PLT slot in the binary if it was not linked into the binary
> >   but is referenced from the binary
> 
> Just trying to clarify a bit -- by "referenced from the binary", do you 
> mean:
> 
> class A { virtual void Foo(); };
> A a;
> a.Foo();

This one is a call to _ZN1A3FooEv (on IA-32 R_386_PC32 reloc).
With older binutils, this acts as any other reference in the binary
and thus, although _ZN1A3FooEv is not defined in the binary, the
SHN_UNDEF _ZN1A3FooEv symbol has non-zero st_value pointing to the
PLT slot.  With CVS binutils this doesn't happen.

> or do you mean calling through the vtable:
> 
> A *a;
> a->Foo();

This doesn't count as any reference from the binary to _ZN1A3FooEv.
The compiler doesn't output the A's virtual table (_ZTV1A) into test1.o
at all.  It happens to be in the binary as COPY reloc because of the
_ZTV1A pointer being used, but e.g. in the shared library you'd just
have a _ZTV1A relocation in GOT.

By reference from the binary other than call I mean something like:

#include "foo.h"

void func(A *a)
{
  a->Foo();
}

class B : public A {};

int main(int argc, char **argv)
{
  A a;
  B b;
  func(&a);
  func(&b);
  return 0;
}

where although A's virtual table is not output into test3.o, B's vtable
(_ZTV1B) is and it contains _ZN1A3FooEv.
In this case, the _ZTV1A virtual table (in the shared library and after the
copy relocation is resolved also in the binary) will unnecessarily point to
the _ZN1A3FooEv PLT slot (which could be fixed by adding a new relocation
R_386_32V or whatever) or by hacking up linker to treat
.gnu.linkonce.[dr]._ZTV* relocations specially (probably not a good idea).

The other thing I talked about is whether _ZTV1B's pointer to _ZN1A3FooEv
should resolve to the PLT slot in the binary or a new dynamic relocation
should be added.  In the above exact case adding a dynamic relocation
for _ZTV1B's _ZN1A3FooEv would mean the PLT slot can go away and
R_386_JMP_SLOT reloc as well, but already when you add func2 as you had
in your test2 case PLT would need to stay.

> One more question -- does any of this change if the "binary" is a DSO 
> which links against the original DSO?

This doesn't change just with -fpic.  But if the binary is a DSO
(whether PIE or you have echo '' | g++ -xc - ... binary and link the
testX.cpp into a new shared library) then there is no such thing
as jumping through PLT unnecessarily.

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]