Performance:
    + create a small test library
    + find some genuinely weak / duplicate symbols in OO.o ...
    + add annotation etc. to that
    + checkout vtable instantation etc.


We are still doing too much work with symbol lookup
    + most of it highly avoidable.

    + ~95% is relocation processing ...
	+ fn relocations ...
    + populating vtable:
	+ looking up global / weak symbols [ why ? ]
	+ [ can they not be -Bsymbolic or something ? ]
	+ if 'dllexport' or the visibility attribute are 
	  used - we should/could hide local vtable
	  lookup bits ?
	+ we want the symbols to be 'protected' so they
	  are exported - by are resolved internally to
	  symbol-freea relocations
	+ The whole thing is crazy:
	    + we need only 1 'get-vtable' method per class ...
	+ Mark all 'virtual' methods of (SPECIFIED && DEFAULT)
	  linkage as 'protected' - ditto for generated thunks (?)
    + Understand the weak symbol issue [!?]
	+ add a throw/catch ...
	  fprintf (file, " %c%c%c%c%c%c%c",
	    ((type & BSF_LOCAL)
	    ? (type & BSF_GLOBAL) ? '!' : 'l'
	    : (type & BSF_GLOBAL) ? 'g' : ' '),
	   (type & BSF_WEAK) ? 'w' : ' ',
	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
	   (type & BSF_WARNING) ? 'W' : ' ',
	   (type & BSF_INDIRECT) ? 'I' : ' ',
	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
	   ((type & BSF_FUNCTION)
	    ? 'F'
	    : ((type & BSF_FILE)
	       ? 'f'
	       : ((type & BSF_OBJECT) ? 'O' : ' '))));
	+ Weak symbols generated by:
	    + Templates ...
	    + Reference<Foo> type stuff ...
	    	    + non-virtual thunks
		    + type info (_ZTI)
		    + vtables (_ZTV)

    + [all to do with typeinfo behavior]
	+ re-read: http://www.nedprod.com/programs/gccvisibility.html
	  very carefully ...
    + Can we annotate the source with 'protected' for most methods ?

    + parent chaining ?
	+ doesn't go via vtable - but direct fn. call ...

    + Looks like we do all those bindings (relocs?)
	+ at dlopen time [!?] [ 10k relocations building vtables ? ]

    + need to check vs. gcc-4.x ...
	[ should be able to prune ... ]

Thoughts: (problem/soln/problem/...)
    + the deep / vcl OutputDevice -> Window -> Control -> ...
      vtable building issue is bad, bad news.
	+ why can't we get/copy the parent's vtable
	  with 'memcpy' ? instead of lots of lookups ?
    + can we parallelise the linker ?
	+ this problem is easily partitionable, surely ...
	    + [ no thread support in the linker ... ]

    + a 'thunk' fn does:
	+ adjust 'this' pointer & call method [ and MI feature ]

+ Things to check:
	+ anonymous namespaces ... - file path mangled in ?



** Parent / Copy VTables ... **
    + Use: options to dump tree data to aid debugging.

	-fdump-class-hierarchy[-N]
    + With this we get:
	cp/class.c (dump_vtable):

eg.

Vtable for SubClass
SubClass::_ZTV8SubClass: 9u entries
0     (int (*)(...))0
4     (int (*)(...))(& _ZTI8SubClass)
8     SubClass::doFoo
12    BaseClass::count
16    BaseClass::operator[]
20    SubClass::doAnother
24    (int (*)(...))-0x000000008
28    (int (*)(...))(& _ZTI8SubClass)
32    SubClass::_ZThn8_N8SubClass9doAnotherEi

Called from:
    + cp/class.c (initialize_vtable)
	+ We need to identify simple cases somewhere
	  here & eliminate sillies.

/* Make BINFO's vtable have N entries, including RTTI entries,
   vbase and vcall offsets, etc.  Set its type and call the backend
   to lay it out.  */

static void
layout_vtable_decl (tree binfo, int n)

/* Virtual function table initialization.  */

/* Create all the necessary vtables for T and its base classes.  */

static void
finish_vtbls (tree t)

Calls:

/* Initialize the vtable for BINFO with the INITS.  */

static void
initialize_vtable (tree binfo, tree inits)

* It seems initializer ordering is unpredictable:

works:

extern ParamFoo aBaa;
ParamFoo aBaa;
StaticInit aStatic(aBaa);

doesn't work:

extern ParamFoo aBaa;
StaticInit aStatic(aBaa);
ParamFoo aBaa;

* Initialization etc. bits:

http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gccint/Initialization.html

.ctors section.
    + find something that puts code in
      the .ctors section (?)

Emit a fn. that will do the construction (?)
    + make it a .ctor (?)


*/

static void
finish_vtbls (tree t)

Calls:

/* Initialize the vtable for BINFO with the INITS.  */

static void
initialize_vtable (tree binfo, tree inits)

* It seems initializer ordering is unpredictable:

works:

extern ParamFoo aBaa;
ParamFoo aBaa;
StaticInit aStatic(aBaa);

doesn't work:

extern ParamFoo aBaa;
StaticInit aStatic(aBaa);
ParamFoo aBaa;

* Initialization etc. bits:

http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gccint/Initialization.html

.ctors section.
    + find something that puts code in
      the .ctors section (?)

Emit a fn. that will do the construction (?)


* Avoid duplicate VTable construction:

    + need to hook the vague linkage constructs:

http://m68hc11.serveftp.org/doc/gcc_6.html

    + but for methods [ ie. same as 'inline' methods ?! ;-]


+ 1st step:
    + get gcc to emit a constructor call to
      a custom fn ...

+ 2nd step
    + generate bit-masks &
      impl. that function to do a copy

+ 3rd step
    + generate that fn. internally



** Ordering:
    + absolutely critical ...
	+ to make it efficient:
	    + have to copy from direct parents only
		=> have to ensure the parent is initialized
		   (copied) itself first ...
	    + have to copy only once
    + Linker support ...

** Assumption:
    + it will ~always be more compact and
      efficient to do vtable copies ourself
      (in shared libraries)
	    + we can make this dependent on -fPIC ...

** Minimality
    + is it possible to do the ordering without
      binutils support ?
	+ we could call a 'weak'
	  parent 'copyVTable' method (if present)
	+ each constructor:
	    + initVTable<Name>
	    + emit a constructor call to that
		+ let initialization sort it out (?)
		+ [ would that break stuff ?]
	    + how bad would that be ?
		+ can we add support to elide
		  duplicate constructors in binutils ?

    + could we do (idle) vtable construction on 1st
      class instance use ?
	+ might be somewhat bloating & evil.
	+ OTOH currently ~valid - since no parent
	  use without foo ?

    + With binutils support:
	+ can call a minimal number of fn's ...
	    + but more difficult (?) ...
	+ the 'sort' is easy
	    + need code walk-through;
		+ where are vtables emitted (by the backend) [!?]
	+ can be made more succinct
	    + can be made .rodata (?)
		+ then needs glibc support [?]
		    + [ for symbol lookup ? ]

** Questions:
    + what forms of symbol / invocation ellision can we use ?

    + I -like- the idea of an 'initVTable' method
      being called (with ~weak stuff?)
	+ isolates the fix in g++ itself, with no
	  binutils/glibc pain.

    + in gcc: where is the vtable building code ?
	+ class.c: initialize_vtable
	    + [ initialize_artificial_var (...)
	+ class.c: (build_vtbl_initializer)
	    + sets up BINFO_VTABLE -
	      (an expression that points at an
	      offset into the vtable ].
	+ class.c (

    + in gcc: where is the vtable emission code ?
	+ 


    + helpful blurb:

   Define accessor macros for information about type inheritance
   and basetypes.

   A "basetype" means a particular usage of a data type for inheritance
   in another type.  Each such basetype usage has its own "binfo"
   object to describe it.  The binfo object is a TREE_VEC node.

   Inheritance is represented by the binfo nodes allocated for a
   given type.  For example, given types C and D, such that D is
   inherited by C, 3 binfo nodes will be allocated: one for describing
   the binfo properties of C, similarly one for D, and one for
   describing the binfo properties of D as a base type for C.
   Thus, given a pointer to class C, one can get a pointer to the binfo
   of D acting as a basetype for C by looking at C's binfo's basetypes.  */



* Considerations:
    + Information
    + Representaiton
    + Data sharing
    + Space efficiency

M-x set-variable\ntab-width 8



<micha> What I implemented until then was just some dumping routines
in the frontend to see how and where it put together the member method
decls, and if it were a overrider, or something inherited.  Then I
thought about it, and thought the whole complicateness is not needed
anymore anyway, then we spoke about it, then I thought again that it's
needed, but never returned to do something on it.  But the patch for
getting a feel in cp/class.c is somewhere

<micha> ...
<micha> ~matz/copy-vtable/diff

<micha> What's left is a multitude of stuff: 1) remembering in
lists-per-class, where the overriders were, 2) emitting a decl for
that list, which could be interpreted at runtime, 3) writing the
runtime support to interpret all these lists, 4) make ld.so call that
runtime support before everything else (also before other static
ctors)

* So
    + we can (I think correctly) identify the slots we want to copy

* Next:
    + generating a new section:
	+ read the constructor code ...

+ decl2.c - remember ? - RTL generation etc. ? :-)

./gcc/cp/decl2.c:#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
./gcc/cp/decl2.c:  char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
./gcc/cp/decl2.c:     SSDF_IDENTIFIER_<number>.  */
./gcc/cp/decl2.c:  sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);

./gcc/cp/cp-tree.h:extern GTY(()) tree static_aggregates;



    static_aggregates = tree_cons (init, decl, static_aggregates);

  while (*var)
    {
      tree t = *var;
      tree decl = TREE_VALUE (t);
      tree init = TREE_PURPOSE (t);

      *var = TREE_CHAIN (t);
      TREE_CHAIN (t) = result;
    }


** We need an intermediate representation (!?)
    + trees of what ?
	+ 2 tree pairs ?
	+ source & dest ?
	    + source == ptr to vtable + offset ...
		+ [ can we make an offset expression ? - perhaps ... ]
	    + dest == ptr to vtable + offset ...

	+ can we use DECL_VINDEX instead ?
	    [ then we have it all ]
	    + just store the fn ptr ?
		+ do we duplicate the fn. decls
		  per vtable ?

    + Then sort/crunch these on output ...
	+ 

    + cp_finish_decl builds 'static_aggregates'

+ Question:
    + is there a different fn. decl per vtable slot
      assignment ? - with a different DECL_VINDEX ?
	+ since we assign DECL_VINDEX on a BV_FN(fn):
	    + it must be ...
      for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
	{
	  tree fndecl = BV_FN (fn);
	  ...
	    DECL_VINDEX (fndecl) = build_int_cst (NULL_TREE, vindex);
	}

        + in vtbl_initialize - 'fn' - is the BV_FN ...

    + Is there already a list of vtables we can
      come back to & operate on later (at emission time ?)
	... 
	+ why not build one ? & operate on it later ?
	+ First build simple list:
	    + then re-consider: can we post-generate this ?

    + can we just sort binutils to ensure that no source
      address is read before a dest is written (?)
	+ then sort read/writes etc.


** Global vars etc. & sorting

+ interestingly a compile emits:

.globl __gxx_personality_v0


Foo aGlobal;
Baa aBaa;

compiles to:

	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:

	.text
	.align 2
	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB9:
	pushl	%ebp
.LCFI14:
	movl	%esp, %ebp
.LCFI15:
	subl	$24, %esp
.LCFI16:
	movl	%eax, -4(%ebp)
	movl	%edx, -8(%ebp)
	cmpl	$1, -4(%ebp)
	jne	.L13
	cmpl	$65535, -8(%ebp)
	jne	.L13
	movl	$aGlobal, (%esp)
	call	_ZN3FooC1Ev
	movl	$aBaa, (%esp)
	call	_ZN3BaaC1Ev
.L13:
	leave
	ret
.LFE9:
	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
	.align 2
	.type	_GLOBAL__I_aGlobal, @function
_GLOBAL__I_aGlobal:
.LFB10:
	pushl	%ebp
.LCFI17:
	movl	%esp, %ebp
.LCFI18:
	subl	$8, %esp
.LCFI19:
	movl	$65535, %edx
	movl	$1, %eax
	call	_Z41__static_initialization_and_destruction_0ii
	leave
	ret
.LFE10:
	.size	_GLOBAL__I_aGlobal, .-_GLOBAL__I_aGlobal


binutils/ld/ldctor.c (ctor_prio):
    + gets the priority of a g++ global constructor
      (or destructor) from the symbol name
        + [ gets an integer prio. from the symbol name ]
    + these functions are sorted (somehow)
    + ldctor_build_sets:
	+ this is what builds the constructor_list ...
	    + [ linker script 'CONSTRUCTORS' command (?) ]

    + FIXME: what good are linker scripts ?
	+ what function do they serve ?

binutils:
http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_chapter/ld_3.html

gcc/collect2.c:
/* Collect static initialization info into data structures that can be
   traversed by C++ initialization and finalization routines. */
    + Interesting [!]


** Generate at least some data out ... &
   a _GLOBAL_<foo> thing ...


* Debugging:
eg. gdb /data/opt/gcc/bin/../libexec/gcc/i686-pc-linux-gnu/4.1.0/cc1plus


* COMDAT linkage
    /* With weak symbols, we simply make the variable COMDAT;
       that will cause copies in multiple translations units to
       be merged.  */
    comdat_linkage (decl);
    + Question: is this an overlaying merge or can it
      be more complex ? [ appending eg. ]

* Assertion failed:

4079      if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
4080        {
4081          /* An automatic variable with an incomplete type: that is an error.
4082             Don't talk about array types here, since we took care of that
4083             message in grokdeclarator.  */
4084          error ("storage size of %qD isn't known", decl);


** We initialize the artificial var
    + but ... how is it output ?

** Have we got the initialization for this thing right ?!


** TODO:
    + emit a '_GLOBAL_...?' fixup function - with
      a 'magic' priority ? so it gets sorted
      first-of-all (!?)
    + terminate the copy constructor foo ...
    + run a simple test with a single constructor ?
    + create a .ctors section ?


** binutils/ld/ldctor.c:
    + ldctor_add_set_entry is called a lot ...
    + can we trigger the binutils feature on the
      presence of compiler emitted 'magic'
      symbols ? [ fun ... ] (nicer for sure !)


    + Can we re-arrange the sections ?
	+ or is this information lost by this time ?
	+ can we extract & move stuff ?
	+ what is possible at link time ?

crtbegin.c:
/* Specialized bits of code needed to support construction and
   destruction of file-scope objects in C++ code.
   Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998,
   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
   Contributed by Ron Guilmette (rfg@monkeys.com).

** Wow - gcc/crtstuff.c
    + looks like an ideal place to put this stuff ...

eg.:

STATIC func_ptr __CTOR_END__[1]
  __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
  = { (func_ptr) 0 };


** Generating our own section:
    + gcc/except.c (default_exception_section)
    + named_section_flags (".gcc_except_table", flags);
    + -> TARGET_ASM_EXCEPTION_SECTION
	-> target-def.h (

We get std. decls into other sections (somehow) with:
surely ?
TARGET_ASM_CONSTRUCTOR,			\
TARGET_ASM_DESTRUCTOR,                  \

gcc/c-decl.c:
    c_expand_body ...


varasm.c: hmm ...

/* Switch to section for variable DECL.  RELOC is the same as the
   argument to SELECT_SECTION.  */

void
variable_section (tree decl, int reloc)
{
  if (IN_NAMED_SECTION (decl))
    named_section (decl, NULL, reloc);
  else
    targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));


elflink.c:
     + check elf_gc_propagate_vtable_entries_used
also + elf_gc_smash_unused_vtentry_relocs

Can we hook into:
    bfd_boolean
    bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
    

/* Called from check_relocs to record the existence of a VTINHERIT reloc.  */

.vtable_inherit & .vtable_entry - pseudo-ops from old 'gas'
http://sources.redhat.com/ml/binutils/2001-02/msg00485.html

gas/config/obj-elf.c:
  /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
  {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
  {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},

* Interesting ! :-) *
    + [ ... neato ...]

* To understand the linker:

  read binutils/include/bfdlink.h

<micha> You just have to make sure, that it's called before static ctors.  So either before __do_global_ctors, or before the call to frame_dummy (which in turn calls __register_frame_info).
<micha> So it's perhaps enough if you put that call to fixup_inheritance (or the like) in crtstuff.c right before here:
<micha> #ifdef INIT_SECTION_ASM_OP
<micha> CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
<micha> #else /* defined(INIT_SECTION_ASM_OP) */
<micha> static func_ptr __frame_dummy_init_array_entry[]
<micha>   __attribute__ ((__unused__, section(".init_array")))
<micha>   = { frame_dummy };
<micha> #endif /* !defined(INIT_SECTION_ASM_OP) */
<micha> #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
<micha> Perhaps outside the USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME ifdef
<michael_> hokay :-)

Looking at:
    + ld/eelf_i386.c ... (interesting)
          assigns: ld_elf_i386_emulation =
	    -> ldemul-list.h EMULATION_LIST
    

/* Do the final step of an ELF link.  */

bfd_boolean
bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)

binutils overview:
    + ldmain.c:469
	+ yyparse (); [ on linker script ]

Most of the action is here:
	+ lang_process [ldlang.c]
	    + open_input_bfds:
		+ load_symbols [ end ]
		    + ... ->
elflink.c		+ "bfd_elf_link_add_symbols"
			+ all symbols end up in:
			    + elf_link_add_object_symbols
			    ** hack here ! **
	    + ldemul_after_open
	    + ldctor_build_sets [ .ctor handling ? ]
	    + ldemul_before_allocation
		+ by this stage we -know- all the sizes
		    + including relocation count etc. ? [!]

 -> ldwrite.c:577

** elf_link_add_object:
    + we can detect & start to accumulate
      information on relocs
	+ but we need all symbols in-place
	  first (surely) ?

    + bfdlink.h (bfd_link_info)
	+ input_bfds -> link_next list ...
	    + we have to 'size' sections
	      later (surely)


    + bfd_elf_size_dynamic_sections ...
	+ Need to do the calcl here
	    + while walking over the
	      input_bfds ... [! :-]


** TODO:
    + remove vtreloc cmdline ...
    + Can we set SEC_MERGE on the gcc version section ?
      [!?] (.comment?)

    + the data we need to do the relocs -
      is fetched with (?) elfcode.h (elf_slurp_reloc_table)
	+ nah - our relocs are somewhere else ...


Interesting fn: for generating linker sourced relocs:

static bfd_boolean
elf_reloc_link_order (bfd *output_bfd,
		      struct bfd_link_info *info,
		      asection *output_section,
		      struct bfd_link_order *link_order)

** Where are the relocations ?
   + how do we get at them ?

** FIXME:
   + what about re-writing these tables when
     they are in-use [!]
	+ inevitably some of the symbols will be 'vague' (?)
	+ [ we can easily check the value of the relocs vs.
	    our own section address / size
	    [ if we're in glibc ... ] ]


** FIXME:
    + problem 1: emitting our own reloc
    + problem 2: removing existing relocs ! ;-)


** Strategy:
    + generate a new / bogus section in the Input (!?)
	+ pack it full of relocs (?)
	+ copy it to the output (?)

* look at linker maps [!]

* consider other sections ?
    + .rel.plt ? - how does it get built ?
    + .dynsym
	+ copy relocs from in -> out (?)
	+ _bfd_elf_link_output_relocs [ Called from Where !? ]
		+ from elflink.c (elf_link_input_bfd)
		    called via (elf_backend_emit_relocs)
	    + this is just building the binary rel section...
	    + can we just do this ourselves for
	      our custom section at the end ?
	    + just call bed->swap_reloc_out [ a lot ourselves ]
	    + have some custom logic ... [ and a custom offset ]
	+ that will let us build a .vtrelocs section ourselves.
	+ input_section->output_section ...
	    + rels ?

    + then we just need to start killing relocations in other
      sections :-) ... [ easier ? ] swap_in/out etc.

* Keep track of external & internal relocs [!?]
    + [hmm]

asection->output_section
    + _bfd_elf_link_size_reloc_section ...
	+ pad them out ? [...]
    + [ symbols? ]

** FIXME:
    + how does the init_list stuff get relocated !?
    + how does it get NULL terminated ?
	+ can we use a similar mechanism ?
    + can we just update the linker file & let it
      copy / aggregate the sections in ?
	+ [ No ? ] we have to re-write the
	  relocations (?) - dupliate inits ?
	  [ same problem ? ]

    + Where do we calculate how many external
      relocations we need ?
	+ we must calculate this for all modules [!]

    + eelf_i386.c - Very complicated linker scripts ... (?)

<micha> Right normally relocations are only created by the assembler.
<micha> Well, not only, though.  Also by the ELF link editor of
course.  But that directly generates ELF relocations, not BFD relocs.
<micha> <Bother>, I'll have competency one-2-ones with my team in 10
minutes, must prepare ...

    + .got.plt : has a -load- of custom relocations ?
	+ or are they done by glibc automagically ?


[ Micha ]

I tried this since some hours now (adding relocations), and nearly 
succeeded...

Couple things:
1) the c++ patch outputs the three entries in the opposite order (the list 
   you build for initialization will be walked from the back, because 
   there is somewhere an nreverse() call on that list), I've changed the 
   binutils part for me, instead of correction the C++ part to the 
   documented format

2) there were a couple mixups in naming the sections .suse.vtrelocs 
   section (sometimes missing the plural 's')

Anyway, as you can see in the patch (attached) I was trying hard to not 
only add the new section (no problem), but also generating relocations for 
it.  Getting the storage for those relocs (I tried to only emit ELF relocs 
directly, not going over the generic BFD routines) is no problem, filling 
it with relocs is also not so much a problem (on has to adjust the symbol 
indices from the incoming relocs to the final symbol indices of the 
output).

So, with that being merely work, I tried to simply add _one_ hard coded 
relocation into a clean .suse.vtrelocs section.  For that one has to first 
set the ->relocs member (of the elf specific section data) to an array of 
ELF relocs.  But then it's not yet used, one has to remove the 
~SEC_LINKER_CREATED flag too (and set SEC_RELOC).  Otherwise 
elf_link_input_bfd() will ignore that section.

[A note: all those artificial sections generated by the linker will 
conceptually be generated as if coming from the first input file BFD, 
_not_ directly in the output_bfd, and by that then also be linked into the 
output file.  That object file (the first with certain properties) is 
stored elf_hash_table (info)->dynobj all the time.]

Unfortunately the above is not enough.  Such input section containing 
relocation entries will be processed by elf_xxx_relocate_section().  The 
relocs of such section which have to be copied to the output file (in 
possibly mangled form) will be stored in another artificial section (i.e. 
hanging off of ->dynobj).  But these sections also have to be created 
first, normally done in check_relocs (goes over a whole section plus 
relocs and decides if such output section holding reloc copies needs to be 
created).

Unfortunately check_relocs is not prepared to handle generated sections, 
only sections really coming from an input file.  First problem is already 
with the name.  As ".suse.vtrelocs" was not in the original input file 
(crti.o in most cases) it will have no corresponding ELF section header, 
and also no name in the ELF string table.  That already prevents 
generation of a ".rel.suse.vtrelocs" section (see 
elf32-i386.c:...check_relocs, the handinling of 'sreloc').  With a hack I 
can generate that section anyway, but then the next problem surfaces.

Because, if such section then is generated, it won't have any output 
section corresponding to it.  All other such "fake" .rel.* sections 
(generated for copying over dynamic relocs) will have .rel.dyn as output 
section assigned.  That assignment unfortunately seems to be done in 
generic linker code, right after reading in the input files, hence 
sections generated afterwards (at least not these .rel section, which seem 
to be special somehow).

So, we can also generate that ".rel.suse.vtrelocs" section in parallel to 
the .suse.vtrelocs section itself.  That it will get stored into the 
output file as separate .rel.suse.vtrelocs section (i.e. not joined with 
.rel.dyn, one can fix that with an entry in the linker script).

And so, finally, we have a new section .suse.vtrelocs, with relocations 
against it.  Something doesn't yet seem to be right with the contents of 
thsoe relocs, but it's a start.

I'm too tired to continue poking for today, though :)

[ /Micha ]

... Foo ...

Crash with section name !? == '-2' ...
    + [hmm]:
	+ need it to be something else ?

'elf_fake_sections' ? ...



<micha> Paste of my log:
<micha> [17:46:26] >micha< my testcase was just two files of the same content:
<micha> [17:46:52] >micha< struct A {
<micha> [17:46:52] >micha<   virtual void f(void);
<micha> [17:46:52] >micha<   virtual void g(void);
<micha> [17:46:53] >micha<   virtual void h(void);
<micha> [17:46:53] >micha< };
<micha> [17:46:54] >micha< struct B : public A {
<micha> [17:46:54] >micha<   virtual void g(void);
<micha> [17:46:55] >micha< };
<micha> [17:47:10] [michael_] ah ok :-)
<micha> [17:47:26] [michael_] so - I don't see the section getting output;
<micha> [17:47:36] >micha< Compiled without -fPIC to asm, copied the asm file, changed the __vtbl_something symbol (as it's global to not clash), and linking with -shared -o -t.so.
<micha> [17:47:50] [michael_] ah - ok ;_)
<micha> [17:47:59] >micha< Relevant details of readelf -e t.so:
<micha> [17:48:03]  michael_ is linking to an unshared binary - perhaps that is the problem.
<micha> [17:48:07] >micha<   [ 6] .rel.dyn          REL             000003d4 0003d4 000050 08   A  2   0  4
<micha> [17:48:07] >micha<   [ 7] .rel.plt          REL             00000424 000424 000010 08   A  2   9  4
<micha> [17:48:13] >micha<   [12] .suse.vtrelocs    PROGBITS        000005a0 0005a0 000030 00   A  0   0  4
<micha> [17:48:25] >micha< And readelf -r:
<micha> [17:48:31] >micha< 000016d8  00000008 R_386_RELATIVE
<micha> [17:48:31] >micha< 000016dc  00000008 R_386_RELATIVE
<micha> [17:48:31] >micha< 00000b40  00001701 R_386_32          00000000   __gmon_start__
<micha> [17:48:32] >micha< 000016c0  00001706 R_386_GLOB_DAT    00000000   __gmon_start__
<micha> [17:48:44] >micha< The relocation to 00000b40 is the new one.



output_section ? - creation ? 
    + 1 assignment: _bfd_elf_link_just_syms ...
...

elflink.c:
	  /* Set the output_section field so that lang_add_section
	     does not create a lang_input_section structure for this
	     section.  Since there might be a symbol in the section
	     being discarded, we must retain a pointer to the section
	     which we are really going to use.  */
	  sec->output_section = bfd_abs_section_ptr;
	  sec->kept_section = l->sec;


** To setup sh_name correctly:
	+ we need to call 'elf_fake_sections' earlier ...
	+ [ when we know we will need the section ? ]

#0  elf_fake_sections (abfd=0x810f160, asect=0x8110620, failedptrarg=0xbfae99c4) at elf.c:2657
#1  0x080702e9 in bfd_map_over_sections (abfd=0x810f160, operation=0x8086b70 <elf_fake_sections>, user_storage=0xbfae99c4) at section.c:1226
#2  0x08089408 in _bfd_elf_compute_section_file_positions (abfd=0x810f160, link_info=0x8103e60) at elf.c:3464
#3  0x08092ce2 in bfd_elf_final_link (abfd=0x810f160, info=0x8103e60) at elflink.c:8392
#4  0x0805d07a in ldwrite () at ldwrite.c:557
#5  0x0805c6df in main (argc=0, argv=0x19) at .././ld/ldmain.c:469


** Looking up the string name - just doesn't work ...
    + crashes: no string table etc.

#0  _bfd_elf_strtab_add (tab=0x0, str=0x80f6446 ".rel.suse.vtrelocs", copy=0) at elf-strtab.c:155
#1  0x08086bbc in elf_fake_sections (abfd=0x8117510, asect=0x8119c44, failedptrarg=0xbfed8718) at elf.c:2675
#2  0x0809dea4 in _bfd_elf_vtreloc_accumulate (output_bfd=0x810f160, info=0x8103e20) at elf-vtreloc.c:322
#3  0x0809769e in bfd_elf_size_dynamic_sections (output_bfd=0x810f160, soname=0x0, rpath=0x0, filter_shlib=0x0, auxiliary_filters=0x0, info=0x8103e20, 
    sinterpptr=0xbfed8868, verdefs=0x0) at elflink.c:5231
#4  0x0806343c in gldelf_i386_before_allocation () at eelf_i386.c:1030
#5  0x080587b1 in lang_process () at ldlang.c:5474
#6  0x0805c6c3 in main (argc=0, argv=0x19) at .././ld/ldmain.c:460


** So - where does:

  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
							  asect->name, FALSE);
#define elf_shstrtab(bfd)	(elf_tdata(bfd) -> strtab_ptr)

	+ start working ?

    /* prep headers will not be called for a bit -
       this defeats a section naming assertion in the backend code,
       that is not experienced with faked sections */
 {
     struct elf_strtab_hash *orig_ptr;
     orig_ptr = elf_shstrtab (dynobj);
     elf_shstrtab (dynobj) = _bfd_elf_strtab_init ();
     

     elf_section_data (vtreloc_sec)->rel_hdr.sh_name =
         (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (dynobj),
                                             ".rel.suse.vtrelocs", FALSE);
 {
     const char *check;
     unsigned int strndx = elf_elfheader (dynobj)->e_shstrndx;
     unsigned int shnam = elf_section_data (vtreloc_sec)->rel_hdr.sh_name;
     check = bfd_elf_string_from_elf_section (dynobj, strndx, shnam);
     fprintf (stderr, "Check '%s'\n", check);
 }
#endif

elflink.c: link_add_symbols
    -> calls check_relocs ...


** If we do this ourself:
    + have to manage the dynsym table ourselves.
    + have to manage the reloc table sizes ourself etc. ...
	+ £"$"£$"£4ing all done in the backend specific code.

Longer term:
    + re-write to use glibc ... [ nurgh - so, so bad ... ]
	+ no hackish mprotect nasties (etc.)
	+ move VTables from .got -> .data [!?]
    + re-write sorting algorithm to be:
	a) fast,
	b) sort by address, to ensure linear src/dest walks.

TODO:
    + 64bit testing
	+ bitmasks: 32 vs. 64bit (etc.)
    + patch review
    + catch & eliminate fixups of remote
      vtables: need to do a range/bound check on
      all of .data [! :-] (useful for the mprotect too (?) ...)
	+ read the glibc mprotect code
    + *Or* - emit each one as R_386_RELATIVE [etc.]
	+ is this a 'BFD_RELOC_.._PCREL ?
	+ also need a RELOC_32 and RELOC_64 [!] ...
    + fix detection of incoming things ...

To test size savings:
    + need to be able to turn off vtable relocation :-) [!] ....
	+ insert 0xdeadbeef instead ?
    + Send patches to the Matzster ...

    + 'static' storage definition ...
	+ gets GC'd by the compiler [somehow]

    + most of the size savings - ephemeral ...
	+ swallowed - since symbols are still emitted [!]
	+ (gack)

    Call some methods in the tests: do some arithmetic to validate the
result etc. ...

TODO:
    + undo some of the cunning that makes it call virtual
      functions directly in many cases (!?) - gives excessive
      symbol churn.

    + Test size savings with 'tests' ...

    + mail Micha ...
	+ http://go-oo.org/~michael/tests.tar.bz2

real-world: VCL:

Copy: 0xb7f5376c -> 0xb5e66bec, (0x3)
Copy: 0xb7f53a0c -> 0xb5e66b8c, (0x33ff9)
Copy: 0xb7f5b908 -> 0xb5e66b28, (0x67ffb)
Copy: 0xb7f56430 -> 0xb5e671b0, (0x7ffffff)
Copy: 0xb7f563b0 -> 0xb5e67130, (0xffffffff)
Copy: 0xb5e671b0 -> 0xb5e67090, (0x7ffffff)
Copy: 0xb5e67130 -> 0xb5e67010, (0xffbfffff)


* Strongly suspect copies of data:

08094348  w   DO .bss   000000f8    _ZTV8OKButton

    ** URGH - this is in .bss
	+ it is *copied* wholesale from elsewhere
	    + *before* the linker has a go & =>
	    + we're screwed, we have to do this in glibc ... [!]
		+ ugh ...
	+ or are we (!?) ;-)
	+ 'COPY' relocs ... [!?]

    ** HAH!
	+ we can install a signal handler (perhaps)
	    + take a fault ...
	+ then (somehow)?
	    + process relocations [hmm]

    ** Interaction between:
	+ glibc-2.4/sysdeps/i386/dl-machine.h
from	  + dl-reloc.c (_dl_relocate_object)
from	    + rtld.c - hmm ...

    ** Create a test that we know fails:
	+ copying vtable foo ... into main object ...