This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Using the PLT for vtables (or not)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Brian Ryner <bryner at brianryner dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: Fri, 5 Dec 2003 07:46:41 +0100
- Subject: Re: Using the PLT for vtables (or not)
- References: <3FCFE464.7080404@brianryner.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Thu, Dec 04, 2003 at 05:50:28PM -0800, Brian Ryner wrote:
> Hi all,
>
> On ELF, the vtable contains pointers to PLT entries. I was wondering if
> anyone could comment on the reasons for constructing the vtable this
> way. In particular, it seems like you could make virtual method calls
> more efficient (by avoiding a load and jump) if you put the vtable into
> writable memory, and initialized it with the real address of every
> method the first time an instance of a class is created.
>
> Any thoughts?
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
c) otherwise to the actual method in the first shared library in given
symbol search scope which defines that method
For a) and c) you already get the direct call, for b) it is indirect
through PLT hop.
Until my very recent binutils patch (which has been for IA-32 only so far),
b) means if a method address is taken (e.g. its address stored into some
vtable in the binary or its address taken in some other way) or if it
has been called from the binary. With my patch calling from the binary
doesn't count, so b) happens only if method address is in a vtable or
stored somewhere, but not if just called from the binary.
The addresses in vtables really don't need to point to PLT slots, as
a conforming program really doesn't care about the pointer values in
vtables - this is invisible to the program.
Prelink even in lots of cases optimizes this out, which both kills thousands
of unneeded prelink conflicts and speeds up the prelinked application
slightly at runtime, not just at startup time[*].
If you can show there are many cases where b) still happens with current CVS
binutils (ie. when some vtable in the binary contains address of some method
defined only in shared libraries and vtables in shared libraries still
unnecessarily resolve to the PLT slot in the binary), maybe a new relocation
would be handy. As a quick hack the linker can be hacked though that it
would not consider R_386_32 relocations located in .gnu.linkonce.d._ZTV*
sections as taking of address, but similarly to R_386_PC32 relocs.
Or were you talking about vtables in the binary going through PLT
if a method they are referencing is not linked into the binary?
In that case I think it is more questionable if changing the current
state is desirable. Avoiding the PLT slot will mean huge growth of the
.rel*.dyn section (the R_*J{,U}MP_SLOT relocation would often have to stay
if the method is called also directly and newly you need one R_*_32 per
pointer in vtable), unless prelinked slower startup, the vtable will
need to be unnecessarily writable and thus per-process (i.e. non-shareable)
memory consumption will go up.
[*] See the C++ optimization chapter of my prelink paper draft at
ftp://people.redhat.com/jakub/prelink/prelink.pdf.
Jakub