Relocations:

** Interesting questions
    + *why* is it that (or even is it!?) that we export
      VTables stuffed full of relocations even when we're using
      a 'hidden' visiblity ?


    + we do 1 relocation, per virtual method, per class/sub-class
	+ ... fun ...
    + do we do -lots- of relocations for 'weak' / vtables that we
      can *know* will not be used ever (?)
	+ COMDAT support should eliminate them anyay (?)
	+ how many relocations take place inside (weak) objects ?
	+ what is the average size of a weak object ...
        + eg. the _ZTV15SvxCheckListBox is only defined in 1 place
	  ie. we prolly don't have tons of duplicate/redundant
	  vtables inc. relocations. vtable emitted as 1st virtual is
	  defined (?).

    + I remember [!] - the reason why we analyse only .rel.dyn
	+ it is processed immediately
	      + .rel.plt is lazily processed ...

    + interesting KDE related paper:
	+ http://www.suse.de/~bastian/Export/linking.txt
		+ everything called 'kdeinit' - linked & then forks
		  => still relocated etc. => upgrade libraries & no
		     change until kdeinit is restarted
		+ ... interesting solution ...
	+ speculation from related thread:
	
	    + by Johannes Sixt on Wednesday 09/May/2001, @02:35

	      AFAIK, Windows DLLs have a "preferred address". If the
	      dynamic linker finds that the preferred address is
	      unallocated and there's enough room to take up the DLL
	      at that address, it is loaded there, and no relocation
	      is needed. Otherwise, it loads the DLL at a different
	      address and relocates it.

	      I think that this is the best thing to do: When a
	      library is linked, it has to be decided in some way what
	      the preferred address is. This must take into account
	      the shared objects that the library depends on.  [ Reply
	      To This | View ]

	      + Re: An Analysis of KDE Speed
	      + by Erik Hensema on Wednesday 09/May/2001, @05:13

	        DLLs do have a preferred address. However, as soon as
	        a DLL has to be relocated, it can't be shared anymore,
	        because windows has no concept of Posistion
	        Independent Code (PIC): all function calls inside the
	        DLL have to be changed when it is relocated.

		Linux (and all other Unices I know of) does support
		PIC: it is essential to the ELF binary format,
		AFAIK. This means relocation isn't expensive: the
		pages of the libary won't have to be touched, making
		them shareable.

		The thing both the Windows and Unix dynlinkers have to
		do is to resolve the calls made by an application to a
		library (or lib -> lib): the app makes a call to a
		fixed address, inside the relocation table. The
		dynlinker generates a call on this fixed address to
		the dynamically linked function.

		The problem with KDE is the sheer number of function
		calls exposes the inefficiency of the dynlinker.

		Loading a library on a preferred address may speed up
		this proces. It may break ELF though.

    + Possible approaches:
	+ prelink
	    + similar to SGI's IRIX 'rebase' tool
	    + very fast, very ugly - slows system updates
	    + works for C, C++, system startup etc.
	+ shmem handshake with 'link-daemon': do the dlink in
	  another process via shared memory. - ie. system-wide
	  pre-linking / caching...
	    + all but 1st time very fast - demand built cache
	    + 1st time somewhat slower - to reduce handshaking
	      would want to do LD_BIND_NOW or equiv.
	    + works for C, C++, system startup etc.
	+ re-work gcc to ensure 
	+ add link hooks for 'idle-linkage' slots (?)
	    + can we get virtual methods into the plt ?
	    + instead of a vtable: a 'code-table'
		+ ie. jump edx + <shim-size>*foo
		+ that shim would be ? a ton of plt references ...
		+ ie. jump into the vtable itself - rather than 
		  the code
		    => bloat ? what is the size of a PLT entry ?
		+ [ compatibility ]:
		    + can keep the existing code & absolute offset ? -
		      have a non-symbol-driven pathetic relocation,
		      pointing to the end of the vtable ?
		    + at the end => no vicious vtable offset
		      calculation problems (?!)
	    + works only for C++
	    * elaboration *
		+ a re-linker that would add these slots post-compile
	+ fix g++/binutils to add 'export' (ie. -Bsymbolic) style
	  markup to all (non-weak?) symbols exported from a visibility
	  annotated class.
	    + partial solution - normally kills < 50% of the relocs
	    + works only for C++
	+ a new / PLT-like approach
	    + we do *maths* to calculate the offset into the vtable
	      anyway - before a virtual call, surely that logic must
	      consume a register or two we can rely on (?)
	    + can we not call a shim / dlink helper instead
		+ classes can have a table of PLT-like slots chained
		  from the vtable to build the table with.
		+ (or a single, initial relocation per vtable)
		+ => can relocate lazily ...
	    + ... PLT entry into the vtable ...



    + Tool to dump '.data' and '.got' sections (?)
	+ and unwind which relocations are in which symbols/elements
	  there precisely....
	+ tool to calculate how many vtables, their size, average
	  number of slots etc.
	    + Problem is:
		+ relocs for internal (hidden visibility)
		  *mostly* resolve internally - except for inherited
		  methods (from publicly exposed things)
		+ eg. SvXML

Gcc hack:
    + output location of PLT function instead of address
      of function - (easy?)
	#pragma push relocating_vtables
	#pragma pop relocating_vtables (?)
	+ -fvtable-via-plt
	    + no need to put code in the foo anyway [?]
	+ optimise parent/chain calls:
	    + switch to vtable usage (?) => relocation (?)
    + Can we use the 'call *(%eax)' instruction
	+ how bad is that wrt. stalling data fetch etc. ?

Interesting:
    + if we know what the type is; we do a 'direct' function call
	+ instead of the vtable lookup [wow]
	    + => in fact ~always slower than a vtable
	      lookup (surely)
	
    + work out how large a plt entry is & how many vtable
      entries we have.



    + analysing libsvx:
	+ objdump -R libsvx680li.so | grep -v '\*ABS\*' \
	          | cut -c 28-100 | sort | uniq -c | sort -n
    + result:
	+ 17k unique symbol 

    + questions:
	+ what are these symbols ?
	    + internal vs. external
	    + weak vs. strong
	    + & a better understanding of why we need
	      so - so many relocs.

    + Analysis of internal{weak/strong}/external gives:(relocstat)
	+ libsvx680li.so total relocs 17483 external 5204, internal weak 2888, internal strong 9391: saving 54%

    + KDE has a -far- smaller relocation count: why ? - deep/virtual trees ?

+ Random analysis of 20 relocs:

SvxRTFParser::CalcValue()	_ZN12SvxRTFParser9CalcValueEv
	+ svx/inc/svxrtf.hxx:
	    + virtual void CalcValue() - an internally resolvable / global symbol
		+ cost: 1 symbol, 1 relocation, etc.

SvTreeListBox::MakeVisible(SvLBoxEntry*)	_ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry
    + checklbx.hxx:class SVX_DLLPUBLIC SvxCheckListBox : public SvTreeListBox
autocdlg.o
000000e0 R_386_32          _ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry
cfg.o
000000e0 R_386_32          _ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry
000000e0 R_386_32          _ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry
    + ** fascinating ** - to see the vtable laid out, in all it's glory:
eg.
        .hidden _ZTV14MenuSaveInData
        .weak   _ZTV14MenuSaveInData
        .section        .gnu.linkonce.d._ZTV14MenuSaveInData,"awG",@progbits,_ZTV14MenuSaveInData,comdat
        .align 32
        .type   _ZTV14MenuSaveInData, @object
        .size   _ZTV14MenuSaveInData, 36
_ZTV14MenuSaveInData:
        .long   0
        .long   _ZTI14MenuSaveInData
        .long   _ZN10SaveInData8GetImageERKN3rtl8OUStringE
        .long   _ZN14MenuSaveInData6HasURLERKN3rtl8OUStringE
        .long   _ZN14MenuSaveInData11HasSettingsEv
        .long   _ZN14MenuSaveInData10GetEntriesEv
        .long   _ZN14MenuSaveInData10SetEntriesEPN4_STL6vectorIP14SvxConfigEntryNS0_9allocatorIS3_EEEE
        .long   _ZN14MenuSaveInData5ResetEv
        .long   _ZN14MenuSaveInData5ApplyEv

checklbx.o
000000e0 R_386_32          _ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry
    + implements SvxCheckListBox
	+ inherits from SvTreeListBox
	+ which implements:
		virtual void	MakeVisible( SvLBoxEntry* );
... tons of other SvxCheckListBox relocations ...
        .weak   _ZTV15SvxCheckListBox
        .section        .gnu.linkonce.d._ZTV15SvxCheckListBox,"awG",@progbits,_ZTV15SvxCheckListBox,comdat
        .align 32
        .type   _ZTV15SvxCheckListBox, @object
        .size   _ZTV15SvxCheckListBox, 540
    _ZTV15SvxCheckListBox:
        .long   0
        .long   _ZTI15SvxCheckListBox
        .long   _ZN15SvxCheckListBoxD1Ev
        .long   _ZN15SvxCheckListBoxD0Ev
        .long   _ZN13SvTreeListBox9MouseMoveERK10MouseEvent
        .long   _ZN15SvxCheckListBox15MouseButtonDownERK10MouseEvent
	...
        .long   _ZN13SvTreeListBox11MakeVisibleEP11SvLBoxEntry



non-virtual thunk to E3dView::~E3dView()        _ZThn16_N7E3dViewD1Ev
svt::EditBrowseBox::ResizeController(svt::CellControllerRef&, Rectangle const&) _ZN3svt13EditBrowseBox16ResizeControllerERNS_17CellControllerRefERK9Rectangle
non-virtual thunk to FmXGridPeer::disposing(com::sun::star::lang::EventObject const&)   _ZThn384_N11FmXGridPeer9disposingERKN3com3sun4star4lang11EventObjectE
SvxCaseMapItem::Store(SvStream&, unsigned short) const  _ZNK14SvxCaseMapItem5StoreER8SvStreamt
non-virtual thunk to SvxUnoText::~SvxUnoText()  _ZThn76_N10SvxUnoTextD0Ev
non-virtual thunk to accessibility::AccessibleShape::queryInterface(com::sun::star::uno::Type const&)   _ZThn36_N13accessibility15AccessibleShape14queryInterfaceERKN3com3sun4star3uno4TypeE
SdrModel::SetReadOnly(int)      _ZN8SdrModel11SetReadOnlyEi
SdrObject::NbcSetLogicRect(Rectangle const&)    _ZN9SdrObject15NbcSetLogicRectERK9Rectangle
Edit::LoseFocus()       _ZN4Edit9LoseFocusEv
typeinfo for sdr::contact::ViewContact  _ZTIN3sdr7contact11ViewContactE
non-virtual thunk to accessibility::AccessibleShape::queryInterface(com::sun::star::uno::Type const&)   _ZThn44_N13accessibility15AccessibleShape14queryInterfaceERKN3com3sun4star3uno4TypeE
svx::FormatPaintBrushToolBoxControl::Select(unsigned char)      _ZN3svx30FormatPaintBrushToolBoxControl6SelectEh
SvxUnoTextRangeBase::compareRegionStarts(com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&, com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&)  _ZN19SvxUnoTextRangeBase19compareRegionStartsERKN3com3sun4star3uno9ReferenceINS2_4text10XTextRangeEEES9_
SdrCircObj::CheckHit(Point const&, unsigned short, SetOfByte const*) const      _ZNK10SdrCircObj8CheckHitERK5PointtPK9SetOfByte
SvxRTFParser::UnknownAttrToken(int, SfxItemSet*)        _ZN12SvxRTFParser16UnknownAttrTokenEiP10SfxItemSet
non-virtual thunk to SvxShape::removePropertiesChangeListener(com::sun::star::uno::Reference<com::sun::star::beans::XPropertiesChangeListener> const&)      _ZThn40_N8SvxShape30removePropertiesChangeListenerERKN3com3sun4star3uno9ReferenceINS2_5beans25XPropertiesChangeListenerEEE
typeinfo for SvxFontMenuControl _ZTI18SvxFontMenuControl
SvxShadowItem::HasMetrics() const       _ZNK13SvxShadowItem10HasMetricsEv
non-virtual thunk to SvxFmDrawPage::~SvxFmDrawPage()    _ZThn48_N13SvxFmDrawPageD1Ev
typeinfo for XLineDashItem      _ZTI13XLineDashItem


+ Random selection of high hit-count symbols 8 or more (1170) ...
      8 _ZThn172_N12SvxShapeText14queryInterfaceERKN3com3sun4star3uno4TypeE
     54 _ZThn20_N17SfxToolBoxControl14queryInterfaceERKN3com3sun4star3uno4TypeE
    199 _ZN6Window8ActivateEv
     11 _ZN9E3dObject10NbcRotateZEd
      9 _ZN18TransferableHelper8dragOverERKN3com3sun4star12datatransfer3dnd19Drag
     14 _ZN9SdrObject9NbcMirrorERK5PointS2_
     11 _ZNK13SdrDragMethod7DrawXorER13XOutputDevicei
     10 _ZNK13SfxStringItem6CreateER8SvStreamt
     45 _ZNK11CntBoolItem17GetValueTextByValEh
     15 _ZTI12SvxColorItem


+ notes on layout foo:
	+ layout_decl (vtable) ? - call to the backend for layout ?
		+ stor-layout.c (layout_decl) - allocates storage.
		+ sets rtl - if known
  /* Make the rtl for any new vtables we have created, and unmark
     the base types we marked.  */
	+ class.c (finish_vtbls):

    + class.c (layout_class_type): interesting stuff...

    + class.c (create_vtable_ptr): interesting ...
	+ The initial code creates the TREE_LIST nodes for
	  the virtual functions:

  /* Collect the virtual functions declared in T.  */
  for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
    if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
	&& TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
      {
	tree new_virtual = make_node (TREE_LIST);

//	cp_warning_at ("create_vtable_ptr for method: %qD", fn);
	
	BV_FN (new_virtual) = fn;
	BV_DELTA (new_virtual) = integer_zero_node;
	BV_VCALL_INDEX (new_virtual) = NULL_TREE;

	TREE_CHAIN (new_virtual) = *virtuals_p;
	*virtuals_p = new_virtual;
      }

-> build_vtbl_initializer ...  
   + calls: 
	init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
vs
	init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);

tree.h:#define build1(c,t1,t2) build1_stat (c,t1,t2 MEM_STAT_INFO)
cp-tree.h:#define vfunc_ptr_type_node  vtable_entry_type

decl.c (cxx_init_decl_processing):
  {
    /* Make sure we get a unique function type, so we can give
       its pointer type a name.  (This wins for gdb.) */
    tree vfunc_type = make_node (FUNCTION_TYPE);
    TREE_TYPE (vfunc_type) = integer_type_node;
    TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
    layout_type (vfunc_type);

    vtable_entry_type = build_pointer_type (vfunc_type);
  }
  record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
#define VTBL_PTR_TYPE		"__vtbl_ptr_type"



tree.c (build_pointer_type):
  return build_pointer_type_for_mode (to_type, ptr_mode, false);

emit-rtl.c:
enum machine_mode ptr_mode;	/* Mode whose width is POINTER_SIZE.  */

'enum machine_mode' - never declared (apparently)

* Pointing to the PLT works well at the assembler level.

gcc/config/i386/i386.c:

static void
output_pic_addr_const (FILE *file, rtx x, int code)
    case SYMBOL_REF:
     /* Mark the decl as referenced so that cgraph will output the function.  */
     if (SYMBOL_REF_DECL (x))
       mark_decl_referenced (SYMBOL_REF_DECL (x));

      assemble_name (file, XSTR (x, 0));
      if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
	fputs ("@PLT", file);
      break;

from i386:print_operand():
/* Meaning of CODE:
...
   P -- if PIC, print an @PLT suffix.
 */

called from gcc/final.c (output_operand):

or config/i386/sol2.h:
#define ASM_OUTPUT_CALL(FILE, FN)				\
  do								\
    {								\
      fprintf (FILE, "\tcall\t");				\
      print_operand (FILE, XEXP (DECL_RTL (FN), 0), 'P');	\
      fprintf (FILE, "\n");					\
    }								\
  while (0)

These magic names come from some highly magic
printf style output macros; cf. final.c (output_asm_insn):

eg. config/i386/i386.md:

(define_insn "*call_pop_0"
  [(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
	 (match_operand:SI 1 "" ""))
   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
			    (match_operand:SI 2 "immediate_operand" "")))]
  "!TARGET_64BIT"
{
  if (SIBLING_CALL_P (insn))
    return "jmp\t%P0";
  else
    return "call\t%P0";
}

(define_insn "*call_1_rex64"
  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
	 (match_operand 1 "" ""))]
  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
{
  if (constant_call_address_operand (operands[0], Pmode))
    return "call\t%P0";
  return "call\t%A0";
}

is an '@PLT' reloc machine-specific ? - yes prolly; the 'P' has to
come from i386/ somewhere ...

** No current relocations use %P - so ... no use grepping for it **

* Interestingly builtins.c (build_function_call_expr)
    + Seems to have an 'ADDR_EXPR' as it's argument to 'CALL_EXPR'
    + PLT selection must be lower down ...

varasm.c (compute_reloc_for_constant) ?

varasm.c (assemble_variable): called for:
    assemble variable 'BaseClass::_ZTV9BaseClass'
    value of compute_reloc_for_constant 'BaseClass::_ZTV9BaseClass' is 2

    -> varasm.c (output_constant):

      if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
					   EXPAND_INITIALIZER),
			      MIN (size, thissize), align, 0))
	error ("initializer for integer value is too complicated");

expr.c (expand_expr) ->
	    (expand_expr_addr_expr) -> most likely 'default:' path.

Perhaps can hook via cp/expr.c (cxx_expand_expr): ?
    cf. langhooks-def.h -> cp/cp-lang.c (lang_hooks)

varasm.c:

bool
assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
{
  int aligned_p;

  aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT));

  /* See if the target hook can handle this kind of object.  */
  if (targetm.asm_out.integer (x, size, aligned_p))
    ** most likely down this path **

    -> varasm.c (default_assemble_integer):
	-> varasm.c (assemble_integer_with_op)
	    -> final.c (output_addr_const)

eg. vtable method:
varasm.c (assemble_integer) -> expand_expr_addr_expr_1 ->
    -> default_assemble_integer '      .long   '
    -> OutputAddrConst (SYMBOL_REF)
	-> assemble_name (file, XSTR (x, 0));
	    ** This is where our label is generated that
	       needs an appended '@PLT' **

** So - (perhaps) don't want to poke 'assemble_integer'
   unless we absolutely have to **

/* Used in VAR_DECLs to indicate that the variable is a vtable.
   Used in FIELD_DECLs for vtable pointers.
   Used in FUNCTION_DECLs to indicate that the function is virtual.  */
#define DECL_VIRTUAL_P(NODE) (DECL_CHECK (NODE)->decl.virtual_flag)


varasm.c(output_constant):
    at edge of assemble_integer call we have:
	exp == ADDR_EXPR
	    TREE_OPERAND(exp, 0) == FUNCTION_DECL 
	code == POINTER_TYPE
    

** Have patch to output PLT relocs for these...
    + But ... - PLT is not populated by linker (somehow).

    + The linker -appears- to fixup the @PLT relocation
      to point to something totally bogus ... ;-)
	+ should be an internal fixup + a non-symbol driven reloc ?

    + try calling across libraries ...

We end up with:
   + objdump -R app.o:

RELOCATION RECORDS FOR [.gnu.linkonce.d._ZTV8SubClass]:
OFFSET   TYPE              VALUE 
00000008 R_386_PLT32       _ZN9BaseClass5doFooEv
0000000c R_386_32          _ZN8SubClass10doFooOtherEv

With just an appended '@PLT' the vtable then holds:
    8049cc8: ff ff ea 38 [doFooEv] (broken)
    8049ccd: 08 04 87 d4 [doFooOtherEv] (correct)

suitable for a call <foo@plt> - but we want an absolute
label reference there.

bfd_howto_type -> (bfd/bfd.h) reloc_howto_struct:
cf. 
  HOWTO(R_386_PLT32, 0, 2, 32, TRUE /* pc_relative */, 0, complain_overflow_bitfield,
	bfd_elf_generic_reloc, "R_386_PLT32",
	TRUE, 0xffffffff, 0xffffffff, TRUE),
  HOWTO(R_386_JUMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
	bfd_elf_generic_reloc, "R_386_JUMP_SLOT",
	TRUE, 0xffffffff, 0xffffffff, FALSE),

  HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
	bfd_elf_generic_reloc, "R_386_32",
	TRUE, 0xffffffff, 0xffffffff, FALSE),

** We want to generate an R_386_JUMP_SLOT instead of R_386_PLT ...
    + how to do that ?

     RELOC_NUMBER (R_386_PLT32,	    4)	/* 32 bit PLT address */
     RELOC_NUMBER (R_386_JUMP_SLOT, 7)	/* Create PLT entry */

** Unfortunately - we can't do it ... - need a new suffix: @FOO ?
    + 

cf. binutils/gas/config/tc-i386.c (lex_got):
    + fixups.


So - somehow the @PLTABS relocation is getting clobbered
    + also there are 'extended' '-fvtable-gc' relocation types:

    + Can we piggy-back off this code ?:

`-fvtable-gc'
     Emit special relocations for vtables and virtual function
     references so that the linker can identify unused virtual
     functions and zero out vtable slots that refer to them.  This is
     most useful with `-ffunction-sections' and `-Wl,--gc-sections', in
     order to also discard the functions themselves.

     This optimization requires GNU as and GNU ld.  Not all systems
     support this option.  `-Wl,--gc-sections' is ignored without
     `-static'.


** So - patch works well for this case:

    + VTable & PLT slot in main app object, (method already had
      plt entry (?))
    + we should be generating a non-symbol-driven relocation
      *per* PLT slot (surely) - since these are not relative
      jumps at all - but absolute fixups.
	    + ... Hmm ...

** Function pointer equality -
    + already an issue with the PLT -> eg elf32-i386.c:

elf_i386_finish_dynamic_symbol:
      if (!h->def_regular)
	{
	  /* Mark the symbol as undefined, rather than as defined in
	     the .plt section.  Leave the value if there were any
	     relocations where pointer equality matters (this is a clue
	     for the dynamic linker, to make function pointer
	     comparisons work between an application and shared
	     library), otherwise set it to zero.  If a function is only
	     called from a binary, there is no need to slow down
	     shared libraries because of that.  */
	  sym->st_shndx = SHN_UNDEF;
	  if (!h->pointer_equality_needed)
	    sym->st_value = 0;
	}


** Fuzzy understanding:

	+ What is a 'JUMP_SLOT' relocation we have 3 things:
		+ a plt entry
		+ a relocation pointing to it (should be relative)
	+ Does the runtime fix up use the .dyn.plt relocation data
	  to do the fixup ?: most likely ...
		+ ie. we need to output 2 relocations: 1 JUMP_SLOT
		  (done per-symbol)
		  and also 1 RELATIVE relocation - per vtable entry.
	+ we must already output 1 fixup per PLT entry - to
	  point at that PLT entry - but this is not a relocation
	  but an immediate link-time fixup (?)
		

* elf32-i386.c (elf_i386_relocate_section):
	+ looks interesting - PLT code very light.

	+ bfd_elf32_swap_reloc_out -> (bfd/elflink.h)

/* Translate an ELF reloc from internal format to external format.  */
void
elf_swap_reloc_out (bfd *abfd,
		    const Elf_Internal_Rela *src,
		    bfd_byte *d)
{
  Elf_External_Rel *dst = (Elf_External_Rel *) d;
  H_PUT_WORD (abfd, src->r_offset, dst->r_offset);
  H_PUT_WORD (abfd, src->r_info, dst->r_info);
}

void
elf_swap_reloca_out (bfd *abfd,
		     const Elf_Internal_Rela *src,
		     bfd_byte *d)
{
  Elf_External_Rela *dst = (Elf_External_Rela *) d;
  H_PUT_WORD (abfd, src->r_offset, dst->r_offset);
  H_PUT_WORD (abfd, src->r_info, dst->r_info);
  H_PUT_SIGNED_WORD (abfd, src->r_addend, dst->r_addend);
}


* JUMP_SLOT relocation:
	+ offset points into .got.plt
		+ allows that to be fixed up idly.
		+ .rel.plt - contains symbol index to do fixup
	+ contents of <.got.plt> is
		+ <raw address> -> jump back into
		  equivalent PLT code

    ** creating a jump-slot (PLT) reloc **
	+ write reloc itself to /.rel.plt/
		-> /.got.plt/
		+ the reloc allows .got.plt to be relocated
		  with the library.
	+ create /.plt/ record
		+ assign index -> /.got.plt/ etc.
	+ write /.got.plt/ record
		+ initially points into relevant /.plt/ record
	+ <foreach referrer to symbol>
		+ create relative address to that code
		+ ie. call 790 <fprintf@plt> (pc-relative)

    ** normal PLT code: 

** The input code has:

RELOCATION RECORDS FOR [.gnu.linkonce.d._ZTV9BaseClass]:
OFFSET   TYPE              VALUE 
00000008 R_386_PLT32ABS    _ZN9BaseClass5doFooEv
0000000c R_386_PLT32ABS    _ZN9BaseClass5countEv
00000010 R_386_PLT32ABS    _ZN9BaseClassixEi
	 ie. the .d._ZTV9BaseClass is a section.
	 each of these is a location we want to add an
	 R_386_RELATIVE to.

** Dynamic linker:
   glibc/elf/do-rel.h: (elf_machine_lazy_rel)
   cf. glibc/sysdeps/i386/dl-machine.h
	+ a JUMP_SLOT reloc has:

__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
		      Elf32_Addr l_addr, const Elf32_Rel *reloc)
{
  Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
  /* Check for unexpected PLT reloc type.  */
  if (__builtin_expect (r_type == R_386_JMP_SLOT, 1))
    {
      if (__builtin_expect (map->l_mach.plt, 0) == 0)
	*reloc_addr += l_addr;
      else
	*reloc_addr = (map->l_mach.plt
		       + (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 4);
    }
  else
    _dl_reloc_bad_type (map, r_type, 1);
}
	This fixup occurs on the GOT reference.
called from dynamic-link.h: ELF_DYNAMIC_DO_REL,
and ELF_DYNAMIC_RELOCATE from glibc/elf/dl-reloc.c (_dl_relocate_object)

	'lazy' is only set for DT_PLTREL sections,
	not DT_RELOC ones.

	Otherwise (glibc/elf/do-rel.h):
	  for (; relative < r; ++relative)
	    DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);

	+ The runtime dylinker is very simple.


** The fixup of the original PLT32ABS address must be in
   elf32-i386.c [ or outside using the reloc_howto_type data ]

via: ?

** Callers of elf_i386_reloc_type_lookup:

	static reloc_howto_type *
	elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
				    bfd_reloc_code_real_type code)
	#define bfd_elf32_bfd_reloc_type_lookup	      elf_i386_reloc_type_lookup
		called via:
	reloc_howto_type *bfd_reloc_type_lookup
	   (bfd *abfd, bfd_reloc_code_real_type code);

bfd/elf.c (_bfd_elf_validate_reloc) calls this ...
	( just for convert non elf to elf relocs ? )

bfd/linker.c:
	/* Create a relocation.  */
	bfd_boolean
	_bfd_generic_reloc_link_order (bfd *abfd,
			       struct bfd_link_info *info,
			       asection *sec,
			       struct bfd_link_order *link_order)
bfd/reloc.c:
	+ (bfd_reloc_type_lookup): implemented - jump via vtable.

	* The hooks themselves point to:
		bfd_elf_generic_reloc

* TLS docs: (not useful): http://people.redhat.com/drepper/tls.pdf

linker.c: has some great docs at the top:

	+ it seems reloc processing all happens in the final
	  stage. (_bfd_generic_final_link)

	+ need to bump up bfd_get_reloc_upper_bound ...


*** ARGH - too much pain ...

A new approach ?
    + output: yet more inefficiency & brokenness:
	.long _Z.....Slot
    + later:
	.long _Z.....Slot attribute 'hidden' etc.
		jmp foo@plt
    + nasty: whacks a NULL in the vtable but does
             insert a relocation of the right type.

	.section        .text.stubs
	.align 2
_ZN8SubClass5doFooEvStub:
	jmp		_ZN8SubClass5doFooEv@plt

Wow - adds even, even more inefficiency ;-)

    * But trivial - requires no linker changes & => worthwhile.

