This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

[PATCH] VAX/ELF: Store all call-saved registers upon PLT stub entry


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@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 */


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