[LV] [PATCH] VAX/ELF: Store all call-saved registers upon PLT stub entry
Maciej W. Rozycki
macro at linux-mips.org
Fri Jun 5 02:15:52 CEST 2009
Hello,
For the VAX processor the list of registers to be preserved across
procedure calls is specified by the 16-bit word at the entry point, called
the entry mask. That word is interpreted by the procedure call
instruction and the registers requested are stored on the stack together
with a copy of the entry mask before control is transferred. Later on,
this data is used by the return instruction to restore the registers
previously saved.
This poses a problem with PLT stubs used for lazy run-time resolving.
The stubs are called as if they were actual procedures, so they have to
provide information about which registers to store. That information
is not available at the static link time as PLT entries are normally only
created for global symbol references to shared objects and such symbols,
even if available from the same binary, are subject to preemption.
Therefore this information has to be orchestrated somehow.
I could see two possible solutions:
1. Either to create a fake mask to include the call-saved registers the
lazy resolver actually clobbers. This approach has a potential
advantage of not requiring unnecessary stack transfers. Unfortunately
the advantage is quickly flushed down the drain as the piece of code
called by the PLT stub has to recreate the stack frame manually by
retrieving the mask from the address to be called once it has been
resolved, determining which registers have to be saved, copying part of
the stack frame already created down the stack, inserting the extra
registers and updating the mask stored on the stack.
2. Always save all the call-saved registers. This has a potential
performance disadvantage, but I believe it to be negligible as the area
near the stack pointer is typically hot in the cache and the lazy
resolver is only called at most once per function per program
execution. The advantage is simplicity. All the stores are done by
the call instruction, which has been designed (and undoubtedly
optimised) for this kind of operation. There is no need to do fragile
fiddling with the stack in the lazy resolver and on average the actual
performance may not be worse at all. The difference is going to be
lost in the lazy resolver's overhead anyway.
The current approach in BFD seems to be #1 above and I would like to get
it changed to the #2. Given the issues with the VAX/ELF backend I'm not
sure if the PLT stubs have already been used in actual software, raising
binary compatibility concerns. If so, I would limit this change to Linux
(regrettably creating an incompatible ELF flavour), otherwise I suggest it
to be applied universally.
While the standard VAX ABI only defines <R11:R6> as call-saved, the mask
I chose includes <R5:R2> too due to the -fcall-saved-REG GCC option -- the
information about which registers are consider call-saved is not carried
along binaries. OTOH, <R1:R0> are skipped as they are result registers
and must never be saved across calls.
bfd/
2009-06-04 Maciej W. Rozycki <macro at linux-mips.org>
* elf32-vax.c (elf_vax_plt_entry): Set the entry mask to
include <R11:R2>.
Comments?
Maciej
binutils-2.19.1-vax-plt-mask.patch
diff -up --recursive --new-file binutils-2.19.1.macro/bfd/elf32-vax.c binutils-2.19.1/bfd/elf32-vax.c
--- binutils-2.19.1.macro/bfd/elf32-vax.c 2008-01-11 09:07:03.000000000 +0000
+++ binutils-2.19.1/bfd/elf32-vax.c 2009-04-20 20:11:20.000000000 +0000
@@ -368,7 +368,7 @@ static const bfd_byte elf_vax_plt0_entry
static const bfd_byte elf_vax_plt_entry[PLT_ENTRY_SIZE] =
{
- 0x40, 0x00, /* .word ^M<r6> */
+ 0xfc, 0x0f, /* .word ^M<r11:r2> */
0x16, 0xef, /* jsb L^(pc) */
0, 0, 0, 0, /* replaced with offset to start of .plt */
0, 0, 0, 0, /* index into .rela.plt */
_______________________________________________
Linux-Vax mailing list
Linux-Vax at mail.pergamentum.com
http://mail.pergamentum.com/mailman/listinfo/linux-vax
More information about the Vax-linux
mailing list