ooo-build r11255 - trunk/patches/test



Author: michael
Date: Mon Jan 14 16:06:09 2008
New Revision: 11255
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11255&view=rev

Log:
more work.


Modified:
   trunk/patches/test/binutils-vt-copy.diff
   trunk/patches/test/glibc-vt-reloc.diff

Modified: trunk/patches/test/binutils-vt-copy.diff
==============================================================================
--- trunk/patches/test/binutils-vt-copy.diff	(original)
+++ trunk/patches/test/binutils-vt-copy.diff	Mon Jan 14 16:06:09 2008
@@ -1,6 +1,600 @@
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/bfd/elf-bfd.h binutils-2.17.50/bfd/elf-bfd.h
---- binutils-2.17.50/bfd/elf-bfd.h	2007-07-19 09:51:03.000000000 +0100
-+++ binutils-2.17.50/bfd/elf-bfd.h	2008-01-09 12:42:12.000000000 +0000
+0a1,593
+> #include "sysdep.h"
+> #include "bfd.h"
+> #include "sysdep.h"
+> #include "bfdlink.h"
+> #include "libbfd.h"
+> #define ARCH_SIZE 0
+> #include "elf-bfd.h"
+> #include "safe-ctype.h"
+> #include "libiberty.h"
+> 
+> typedef struct _CopyEntry CopyEntry;
+> 
+> typedef struct {
+>     bfd       *abfd;
+>     CopyEntry *sorted;
+>     CopyEntry *unsorted;
+> } VtRelocs;
+> 
+> struct _CopyEntry {
+>     struct elf_link_hash_entry *src;
+>     bfd_vma                     src_offset;
+>     struct elf_link_hash_entry *dest;
+>     bfd_vma                     dest_offset;
+>     bfd_vma                     bitmask;
+> 
+>     /* chain */
+>     CopyEntry *next;
+> };
+> 
+> static void
+> prepend (CopyEntry **list, CopyEntry *p)
+> {
+>     p->next = *list;
+>     *list = p;
+> }
+> 
+> static int
+> copy_entry_equal (const CopyEntry *a, const CopyEntry *b)
+> {
+>     return (a->src == b->src &&
+>             a->src_offset == b->src_offset &&
+>             a->dest == b->dest &&
+>             a->dest_offset == b->dest_offset &&
+>             a->bitmask == b->bitmask);
+> }
+> 
+> /*
+>  * FIXME - should be a hash lookup / something fast.
+>  */
+> static CopyEntry *
+> find_with_dest (CopyEntry *list,
+>                 struct elf_link_hash_entry *e)
+> {
+>     while (list)
+>       {
+>         if (list->dest == e)
+>           break;
+>         list = list->next;
+>       }
+>     return list;
+> }
+> 
+> static CopyEntry *
+> find_equal_entry (CopyEntry *list, CopyEntry *e)
+> {
+>   while (list)
+>     {
+>       if (copy_entry_equal (list, e))
+>         break;
+>       list = list->next;
+>     }
+>   return list;
+> }
+> 
+> /*
+>  * Transfer from unsorted -> sorted.
+>  * NB. simple-minded algorithm, N^3 with degenerate case
+>  */
+> static void
+> sort_relocs (VtRelocs *vtr)
+> {
+>     CopyEntry *p;
+>     CopyEntry *pending;
+>     CopyEntry *next;
+> 
+>     fprintf (stderr, "Sorting ...");
+>     do
+>       {
+>         pending = NULL;
+>         
+>         for (p = vtr->unsorted; p; p = next)
+>           {
+>             next = p->next;
+>             if (!find_with_dest (vtr->unsorted, p->src))
+>             {
+>               /* FIXME: sorting by offset, to ensure as
+>                  good as possible contiguous access will
+>                  require a more complex node structure:
+>                  with aggregation per 'dest', and
+>                  internal sorting within that */
+>               prepend (&vtr->sorted, p);
+>             }
+>             else
+>               prepend (&pending, p);
+>           }
+>         vtr->unsorted = pending;
+>       }
+>     while (pending);
+>     fprintf (stderr, " done\n");
+> }
+> 
+> static void
+> check_reloc (Elf_Internal_Rela *rel, int type_mask)
+> {
+>   if ((rel->r_info & type_mask) != STT_OBJECT)
+>       fprintf (stderr, "broken vtreloc type\n");
+>   if (rel->r_addend != 0)
+>       fprintf (stderr, "unexpected reloc addend\n");
+> }
+> 
+> static void
+> print_rel (const char *type, 
+>            struct elf_link_hash_entry *target)
+> {
+>   fprintf (stderr, "%s '%s' %d %d %d %d i:%ld\n",
+>            type, target->root.root.string,
+>            target->ref_regular, target->def_regular,
+>            target->ref_dynamic, target->def_dynamic,
+>            target->dynindx);
+> }
+> 
+> static void
+> add_reloc (VtRelocs *vtr,
+>            bfd      *inputobj,
+>            Elf_Internal_Rela *src_rel,
+>            Elf_Internal_Rela *dest_rel,
+>            unsigned char     *data)
+> {
+>   unsigned r_sym_shift;
+>   unsigned r_type_mask;
+>   unsigned incr;
+>   unsigned symidx;
+>   const struct elf_backend_data *bed;
+>   struct elf_link_hash_entry *dest, *src;
+>   Elf_Internal_Shdr *hdr;
+>   CopyEntry *e;
+> 
+>   hdr = &elf_tdata (inputobj)->symtab_hdr;
+>   bed = get_elf_backend_data (inputobj);
+>   if (bed->s->arch_size == 32)
+>     {
+>       r_type_mask = 0xff;
+>       r_sym_shift = 8;
+>       incr = 4;
+>     }
+>   else
+>     {
+>       r_type_mask = 0xffffffff;
+>       r_sym_shift = 32;
+>       incr = 8;
+>     }
+> 
+>   check_reloc (src_rel, r_type_mask);
+>   check_reloc (dest_rel, r_type_mask);
+> 
+> /*
+> #define elf_sym_hashes(bfd)	(elf_tdata(bfd) -> sym_hashes)
+> #define elf_tdata(bfd)		((bfd) -> tdata.elf_obj_data)
+>   Elf
+>   cf. RELOC_FOR_GLOBAL_SYMBOL ...
+> */
+> 
+>   symidx = (dest_rel->r_info >> r_sym_shift);
+>   fprintf (stderr, "symidx %d (-%d)!\n", symidx, hdr->sh_info);
+> 
+>   if (symidx < hdr->sh_info) // local symbol ...
+>   {
+>       fprintf (stderr, "Error/FIXME: local dest symbol !");
+>       return;
+>   }
+> 
+>   symidx -= hdr->sh_info;
+>   dest = elf_sym_hashes (inputobj) [symidx];
+>   if (!dest) {
+>       fprintf (stderr, "no rel %d!\n", symidx);
+>       return;
+>   }
+> 
+>   /* Eliminate relocs to no longer present internal vtables. */
+>   if (!dest->def_regular)
+>     {
+>       print_rel ("Abandoning dest", dest);
+>       fprintf (stderr, "Ref count %ld %ld dynindx %d\n",
+>                dest->got.refcount, dest->plt.refcount,
+>                (int) dest->dynindx);
+>       /* unref the symbol somehow (!?) */
+>       return;
+>     }
+> 
+>   // FIXME: do we need something like this for indirect / warnings !?
+> /*    while (target->root.type == bfd_link_hash_indirect
+>            || target->root.type == bfd_link_hash_warning)
+>            target = (struct elf_link_hash_entry *) target->root.u.i.link; */
+>   fprintf (stderr, "dest link type %d\n", dest->root.type);
+>   if (dest->root.type == bfd_link_hash_undefined ||
+>       dest->root.type == bfd_link_hash_undefweak)
+>     {
+>       fprintf (stderr, "undefined dest sym '%s'\n", dest->root.root.string);
+>       return;
+>     }
+> 
+>   /* Consider: should we eliminate all internal -> internal
+>      copies ? it's possible we are more space / time
+>      efficient - so no for now. */
+> 
+>   symidx = (src_rel->r_info >> r_sym_shift);
+>   if (symidx < hdr->sh_info) // local symbol ...
+>   {
+>       fprintf (stderr, "Error/FIXME: local src symbol !");
+>       return;
+>   }
+>   symidx -= hdr->sh_info;
+>   src = elf_sym_hashes (inputobj) [symidx];
+>   if (src->root.type == bfd_link_hash_undefined ||
+>       src->root.type == bfd_link_hash_undefweak)
+>     {
+>       fprintf (stderr, "undefined src sym '%s'\n", src->root.root.string);
+>       return;
+>     }
+> 
+>   print_rel ("Src", src);
+>   print_rel ("Dst", dest);
+> 
+>   e = bfd_zalloc (vtr->abfd, sizeof (CopyEntry));
+> 
+>   e->src = src;
+>   e->dest = dest;
+> 
+>   if (dest_rel->r_offset - src_rel->r_offset != bed->s->arch_size / 8)
+>       fprintf (stderr, "Mis-paired vtrelocs\n");
+> 
+>   e->src_offset = bfd_get (bed->s->arch_size, inputobj, data);
+>   data += incr;
+>   e->dest_offset = bfd_get (bed->s->arch_size, inputobj, data);
+>   data += incr;
+>   e->bitmask = bfd_get (bed->s->arch_size, inputobj, data);
+> 
+>   /* Simple minded dupliates elision */
+>   if (find_equal_entry (vtr->unsorted, e))
+>     bfd_release (vtr->abfd, e);          
+>   else
+>     {
+>       prepend (&vtr->unsorted, e);  
+> 
+>       fprintf (stderr, "Copy: '%s'+%d -> '%s'+%d (0x%x)\n",
+>                e->src->root.root.string,
+>                (int)e->src_offset,
+>                e->dest->root.root.string,
+>                (int)e->dest_offset,
+>                (int)e->bitmask);
+>     }
+> }
+> 
+> static VtRelocs *global_vtr;
+> 
+> bfd_boolean _bfd_elf_vtreloc_accumulate (bfd *output_bfd,
+>                                          struct bfd_link_info *info)
+> {
+>   bfd *dynobj;
+>   dynobj = elf_hash_table (info)->dynobj;
+>   if (info->vtreloc)
+>     { // .vtrelocs
+>       bfd_size_type sec_size = 0;
+>       asection *vtreloc_sec;
+>       asection *vtrelrel;
+>       bfd *inputobj;
+>       VtRelocs *vtr;
+>       Elf_Internal_Rela last_rela;
+>       bfd_size_type num_relocs;
+> 
+>       vtr = bfd_zalloc (output_bfd, sizeof (VtRelocs));
+>       vtr->abfd = output_bfd;
+>       global_vtr = vtr;
+> 
+>       /* FIXME: we need to elide relocs that turn out
+>          to be purely internal:
+>          eg. internal -> internal copy src / dest,
+>          others are less troublesome - though removing
+>          empty ones would be nice (?).
+>          We want to trap every -named- reloc ...
+>       */
+>       for (inputobj = info->input_bfds;
+> 	   inputobj;
+> 	   inputobj = inputobj->link_next)
+> 	{
+> 	  asection *s;
+>           struct bfd_elf_section_data *es; /* elf-bfd.h */
+>           unsigned i;
+>           Elf_Internal_Rela *relocs, *p;
+>           unsigned char *sec_data;
+> 	  long storage_needed;
+> 	  asymbol **symtab;
+> 	  long number_of_symbols;
+> 	  const struct elf_backend_data *bed = get_elf_backend_data (inputobj);
+> 
+> 	  if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
+> 	    continue;
+> 	  s = bfd_get_section_by_name (inputobj, ".vtrelocs");
+>           if (!s)
+>             continue;
+> 	  /* XXX Hmm, this seems to generate many NONE relocs, probably from
+> 	     the original relocs to this section.  Perhaps discard them
+> 	     earlier.  */
+> 	  s->flags |= SEC_EXCLUDE;
+>           es = elf_section_data (s);
+>           if (!es)
+>             continue;
+> 
+>           if (!s->reloc_count)
+>             continue;
+> 
+>           fprintf (stderr, "Relocs: size %d, count %d contents %p\n",
+>                    (int)es->rel_hdr.sh_size, es->rel_count,
+>                    s->contents);
+>           
+> 
+>           /* Can't find this info anywhere else for some reason: */
+>           p = relocs = _bfd_elf_link_read_relocs (inputobj, s, NULL, NULL,
+>                                                   info->keep_memory);
+> 
+> 	  /* Experimental stuff to get at the BFD relocs (translated back
+> 	     from the real ELF relocs.  */
+> 	  storage_needed = bfd_get_symtab_upper_bound (inputobj);
+> 	  if (storage_needed <= 0)
+> 	    return FALSE;
+> 	  symtab = xmalloc (storage_needed);
+> 	  number_of_symbols = bfd_canonicalize_symtab (inputobj, symtab);
+> 	  if (number_of_symbols < 0)
+> 	    return FALSE;
+> 
+> 	  if (! bed->s->slurp_reloc_table (inputobj, s, symtab, FALSE))
+> 	    return FALSE;
+>           
+> 	  /* Now inputobj->relocation will contain BFD relocs.  */
+> 
+>           sec_data = bfd_malloc (es->this_hdr.sh_size);
+>           
+>           /* Slurp the data */
+>           if (bfd_seek (inputobj, es->this_hdr.sh_offset, SEEK_SET) != 0)
+>             return FALSE;
+>           if (bfd_bread (sec_data, es->this_hdr.sh_size, inputobj) != es->this_hdr.sh_size)
+>             return FALSE;
+> 
+>           if (es->this_hdr.sh_size % s->reloc_count != 0)
+>               fprintf (stderr, "ERROR: mismatching vtreloc sec & reloc count "
+>                        "0x%x, 0x%x -> %d\n",
+>                        (int)es->this_hdr.sh_size, (int)s->reloc_count,
+>                        (int)es->this_hdr.sh_size % s->reloc_count);
+> 
+>           /* Assumes an even number of relocs sorted by address ... */
+>           for (i = 0; i < s->reloc_count / 2; i++)
+>           {
+>               unsigned int entry_size;
+>               entry_size = (get_elf_backend_data (inputobj)->s->arch_size / 8) * 3;
+>               
+> 	      last_rela = *p;
+>               add_reloc (vtr, inputobj, p, p + 1,
+>                          sec_data + i * entry_size);
+>               p+=2;
+>           }
+>           free (sec_data);
+>           if (es->relocs != relocs)
+>               free (relocs);
+>         }
+> 
+>       /* So - we need to sort these guys as we work out the sizes */
+>       /* We need to generate an internal list of XYZ type 
+>            + eliminate all external -> external work ... 
+>            + add all external -> internal copies to 'sorted' list
+>               + [ fool-proof GC roots ]
+>            + add other symbols to 'pending' list.
+>            + read / generate src: [symbol + offset, dest: sym + offset, bitmask data]
+>       */
+>       sort_relocs (vtr);
+>       num_relocs = 0;
+>       sec_size = 0;
+>       {
+>         CopyEntry *e;
+> 	for (e = vtr->sorted; e; e = e->next)
+> 	  {
+> 	    sec_size += 3;  /* Word entries.  */
+> 	    num_relocs += 2;
+> 	  }
+>       }
+>       /*
+>          Finally:
+>            + build new custom section
+>            + emit new relocations for it ...
+>       */
+>       
+>       vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
+>       if (vtreloc_sec)
+>         {
+> 	  bfd_size_type rel_size;
+> 	  bfd_size_type size;
+> 	  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
+> 	  vtrelrel = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
+> 	  if (!vtrelrel)
+> 	    return FALSE;
+> 
+>           {
+>               unsigned int entry_size;
+>               entry_size = (bed->s->arch_size / 8);
+>               /* + 1 for null termination */
+>               vtreloc_sec->size = (sec_size + 1) * entry_size;
+>               vtreloc_sec->contents = bfd_zalloc (dynobj, vtreloc_sec->size);
+> //	      if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_VTRELOC, 0))
+> //	        return FALSE;
+>           }
+> 
+> 	  rel_size = bed->s->sizeof_rel;
+> 	  if (bed->default_use_rela_p)
+> 	    {
+> 	      rel_size = bed->s->sizeof_rela;
+> 	    }
+> 
+> 	  size = rel_size * num_relocs;
+> 	  fprintf (stderr, "Need %ld bytes of relocs rel-size %ld\n",
+>                    size, rel_size);
+> 	  vtrelrel->size = size;
+>         }
+>       else
+>         fprintf (stderr, "Horrendous error ! - no .suse.vtrelocs\n");
+> 
+>     }
+>   else
+>     {
+>       asection *vtreloc_sec;
+>       vtreloc_sec = bfd_get_section_by_name (dynobj, ".vtrelocs");
+>       if (vtreloc_sec)
+>         vtreloc_sec->flags |= SEC_EXCLUDE;
+>     }
+>   return TRUE;
+> }
+> 
+> static void
+> generate_reloc (bfd                        *dynobj,
+>                 struct elf_link_hash_entry *target,
+>                 asection                   *vtreloc_sec,
+>                 asection                   *vtrelrel,
+>                 bfd_vma                     num_entry,
+>                 int                         is_dest,
+>                 bfd_size_type              *adjust_relative)
+> {
+>     bfd_size_type sym_idx, rel_size;
+>     reloc_howto_type *howto;
+>     void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+>     bfd_byte *loc;
+>     Elf_Internal_Rela outrel;
+>     const struct elf_backend_data *bed;
+> 
+>     bed = get_elf_backend_data (dynobj);
+> 
+>     rel_size = bed->s->sizeof_rel;
+>     swap_out = bed->s->swap_reloc_out;
+>     if (bed->default_use_rela_p)
+>     {
+>         rel_size = bed->s->sizeof_rela;
+>         swap_out = bed->s->swap_reloca_out;
+>     }
+> 
+>     /* XXX: unwind this goodness etc. */
+>     while (target->root.type == bfd_link_hash_indirect
+>            || target->root.type == bfd_link_hash_warning)
+>       target = (struct elf_link_hash_entry *) target->root.u.i.link;
+> 
+>     fprintf (stderr, "Reloc '%s' %d %d %d %d i:%ld ",
+>              target->root.root.string,
+>              target->ref_regular, target->def_regular,
+>              target->ref_dynamic, target->def_dynamic,
+>              target->dynindx);
+>     if (is_dest /* force relative */ || target->dynindx <= 0)
+>       fprintf (stderr, "'%s' vma 0x%lx offset %ld output off %ld\n",
+>                target->root.u.def.section->name,
+>                target->root.u.def.section->output_section->vma,
+>                target->root.u.def.value,
+>                target->root.u.def.section->output_offset);
+>     else
+>       fprintf (stderr, "\n");
+> 
+>     /* XXX: RELOC64 too */
+>     if (is_dest /* force relative */ || target->dynindx <= 0)
+>       { /* do a relative reloc ... */
+>         howto = bfd_reloc_type_lookup (dynobj, BFD_RELOC_386_RELATIVE);
+>         sym_idx = 0;
+>         BFD_ASSERT (target->root.type == bfd_link_hash_defweak);
+>         *adjust_relative = (target->root.u.def.section->output_section->vma +
+>                             target->root.u.def.section->output_offset);
+>       }
+>     else
+>       {
+>         howto = bfd_reloc_type_lookup (dynobj, BFD_RELOC_32);
+>         sym_idx = target->dynindx;
+>         *adjust_relative = 0;
+>       }
+> 
+>     /* generate relocation */
+>     outrel.r_offset = vtreloc_sec->output_section->vma;
+>     outrel.r_offset += num_entry * 3 * 4; // XXX: 4 ?
+>     if (is_dest) outrel.r_offset += 4; // XXX: 4
+>     outrel.r_info = ELF32_R_INFO (sym_idx, howto->type);
+>     outrel.r_addend = 0;
+> 
+>     loc = vtrelrel->contents + (vtrelrel->reloc_count++ * rel_size);
+>     swap_out (dynobj, &outrel, loc);
+> }
+> 
+> bfd_boolean _bfd_elf_vtreloc_fill (bfd *output_bfd,
+>                                    struct bfd_link_info *info)
+> {
+>   bfd *dynobj;
+>   dynobj = elf_hash_table (info)->dynobj;
+> 
+>   fprintf (stderr, "Foo: generate .suse.vtrelocs relocs\n");
+> 
+>   if (info->vtreloc)
+>     {
+>       asection *vtreloc_sec;
+>       asection *vtrelrel;
+> 
+>       vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
+>       if (vtreloc_sec)
+>         {
+> 	  CopyEntry *e;
+> 	  bfd_size_type entries, adjust_relative, entry_size;
+> 	  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
+>           bfd_byte *data;
+> 
+>           entry_size = (bed->s->arch_size / 8);
+> 
+> 	  vtrelrel = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
+> 	  if (!vtrelrel)
+> 	    return FALSE;
+> 	  if (!vtrelrel->contents)
+> 	    {
+> 	      fprintf (stderr, "Nothing allocated for relocs\n");
+> 	      return FALSE;
+> 	    }
+> 
+> 	  BFD_ASSERT (vtreloc_sec->output_offset == 0);
+> 	  entries = 0;
+> 	  vtrelrel->reloc_count = 0;
+>           data = vtreloc_sec->contents;
+> 	  for (e = global_vtr->sorted; e; e = e->next)
+> 	    {
+> 	      /* Source */
+>               generate_reloc (output_bfd, e->src, vtreloc_sec, vtrelrel,
+>                               entries, FALSE, &adjust_relative);
+>               bfd_put(bed->s->arch_size, output_bfd,
+>                       e->src_offset + adjust_relative, data);
+>               data += entry_size;
+> 
+>               /* Dest */
+>               generate_reloc (output_bfd, e->dest, vtreloc_sec, vtrelrel,
+>                               entries, TRUE, &adjust_relative);
+>               bfd_put(bed->s->arch_size, output_bfd,
+>                       e->dest_offset + adjust_relative, data);
+>               data += entry_size;
+> 
+>               bfd_put(bed->s->arch_size, dynobj, e->bitmask, data);
+>               data += entry_size;
+> 
+>               entries++;
+>             }
+>           BFD_ASSERT (vtrelrel->reloc_count * (bed->default_use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel)
+>                       == vtrelrel->size);
+>         }
+>       else
+>         fprintf (stderr, "Horrendous error ! - no .suse.vtrelocs\n");
+>     }
+>   else
+>     {
+>       asection *vtreloc_sec;
+>       fprintf (stderr, "TESTME: exclude .vtrelocs if none present\n");
+>       vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
+>       if (vtreloc_sec)
+>         vtreloc_sec->flags |= SEC_EXCLUDE;
+>       vtreloc_sec = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
+>       if (vtreloc_sec)
+>         vtreloc_sec->flags |= SEC_EXCLUDE;
+>     }
+>   return TRUE;
+> }
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/bfd/elf-bfd.h binutils-2.17.50/bfd/elf-bfd.h
+--- pristine-binutils-2.17.50/bfd/elf-bfd.h	2008-01-09 16:45:22.000000000 +0000
++++ binutils-2.17.50/bfd/elf-bfd.h	2008-01-09 17:04:17.000000000 +0000
 @@ -1787,6 +1787,12 @@
  extern void _bfd_elf_init_2_index_sections
    (bfd *, struct bfd_link_info *);
@@ -14,434 +608,140 @@
  extern bfd_boolean _bfd_elfcore_make_pseudosection
    (bfd *, char *, size_t, ufile_ptr);
  extern char *_bfd_elfcore_strndup
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/bfd/elf.c binutils-2.17.50/bfd/elf.c
---- binutils-2.17.50/bfd/elf.c	2007-07-24 10:50:16.000000000 +0100
-+++ binutils-2.17.50/bfd/elf.c	2008-01-09 12:44:13.000000000 +0000
-@@ -1240,6 +1240,7 @@
- 	    case DT_USED: name = "USED"; break;
- 	    case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
- 	    case DT_GNU_HASH: name = "GNU_HASH"; break;
-+        case DT_SUSE_VTRELOC: name = "SUSE_VTRELOC"; break;
- 	    }
- 
- 	  fprintf (f, "  %-11s ", name);
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/bfd/elflink.c binutils-2.17.50/bfd/elflink.c
---- binutils-2.17.50/bfd/elflink.c	2007-07-25 09:33:23.000000000 +0100
-+++ binutils-2.17.50/bfd/elflink.c	2008-01-09 12:46:24.000000000 +0000
-@@ -148,6 +148,34 @@
-   return TRUE;
- }
- 
-+static int
-+_bfd_elf_create_vtreloc_sections (struct bfd_link_info *info)
-+{
-+  bfd *abfd;
-+  asection *s;
-+  flagword flags;
-+  const struct elf_backend_data *bed;
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/bfd/elf-vtreloc.c binutils-2.17.50/bfd/elf-vtreloc.c
+--- pristine-binutils-2.17.50/bfd/elf-vtreloc.c	2008-01-09 16:54:44.000000000 +0000
++++ binutils-2.17.50/bfd/elf-vtreloc.c	2008-01-14 15:07:15.000000000 +0000
+@@ -0,0 +1,593 @@
++#include "sysdep.h"
++#include "bfd.h"
++#include "sysdep.h"
++#include "bfdlink.h"
++#include "libbfd.h"
++#define ARCH_SIZE 0
++#include "elf-bfd.h"
++#include "safe-ctype.h"
++#include "libiberty.h"
 +
-+  abfd = elf_hash_table (info)->dynobj;
-+  bed = get_elf_backend_data (abfd);
-+  flags = bed->dynamic_sec_flags;
++typedef struct _CopyEntry CopyEntry;
 +
-+  s = bfd_make_section (abfd, ".suse.vtrelocs");
-+  if (s == NULL
-+      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
-+      || ! bfd_set_section_alignment (abfd, s, 2))
-+    return FALSE;
-+  s = bfd_make_section (abfd, ".rel.suse.vtrelocs");
-+  if (s == NULL
-+      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY
-+                                  | SEC_HAS_CONTENTS
-+                                  | SEC_IN_MEMORY | SEC_LINKER_CREATED)
-+      || ! bfd_set_section_alignment (abfd, s, 2))
-+      return FALSE;
++typedef struct {
++    bfd       *abfd;
++    CopyEntry *sorted;
++    CopyEntry *unsorted;
++} VtRelocs;
 +
-+  return TRUE;
++struct _CopyEntry {
++    struct elf_link_hash_entry *src;
++    bfd_vma                     src_offset;
++    struct elf_link_hash_entry *dest;
++    bfd_vma                     dest_offset;
++    bfd_vma                     bitmask;
++
++    /* chain */
++    CopyEntry *next;
++};
++
++static void
++prepend (CopyEntry **list, CopyEntry *p)
++{
++    p->next = *list;
++    *list = p;
 +}
 +
- /* Create some sections which will be filled in with dynamic linking
-    information.  ABFD is an input file which requires dynamic sections
-    to be created.  The dynamic sections take up virtual memory space
-@@ -2266,6 +2294,7 @@
- 	return FALSE;
- 
-       elf_section_data (o)->rel_hashes = p;
-+      fprintf (stderr, "allocated rel_hashes for asec %p\n", o);
-     }
- 
-   return TRUE;
-@@ -3291,7 +3320,24 @@
-   bed = get_elf_backend_data (abfd);
- 
-   if ((abfd->flags & DYNAMIC) == 0)
-+  {
-+    asection *vtrel_sec;
++static int
++copy_entry_equal (const CopyEntry *a, const CopyEntry *b)
++{
++    return (a->src == b->src &&
++            a->src_offset == b->src_offset &&
++            a->dest == b->dest &&
++            a->dest_offset == b->dest_offset &&
++            a->bitmask == b->bitmask);
++}
 +
-     dynamic = FALSE;
++/*
++ * FIXME - should be a hash lookup / something fast.
++ */
++static CopyEntry *
++find_with_dest (CopyEntry *list,
++                struct elf_link_hash_entry *e)
++{
++    while (list)
++      {
++        if (list->dest == e)
++          break;
++        list = list->next;
++      }
++    return list;
++}
 +
-+    vtrel_sec = bfd_get_section_by_name (abfd, ".vtrelocs");
-+    if (vtrel_sec)
++static CopyEntry *
++find_equal_entry (CopyEntry *list, CopyEntry *e)
++{
++  while (list)
++    {
++      if (copy_entry_equal (list, e))
++        break;
++      list = list->next;
++    }
++  return list;
++}
++
++/*
++ * Transfer from unsorted -> sorted.
++ * NB. simple-minded algorithm, N^3 with degenerate case
++ */
++static void
++sort_relocs (VtRelocs *vtr)
++{
++    CopyEntry *p;
++    CopyEntry *pending;
++    CopyEntry *next;
++
++    fprintf (stderr, "Sorting ...");
++    do
 +      {
-+        fprintf (stderr, "Has vtrelocs ! %d\n", (int)vtrel_sec->size);
-+        if (!info->vtreloc)
++        pending = NULL;
++        
++        for (p = vtr->unsorted; p; p = next)
 +          {
-+            info->vtreloc = 1;
-+            if (!_bfd_elf_create_vtreloc_sections (info))
-+              goto error_return;
++            next = p->next;
++            if (!find_with_dest (vtr->unsorted, p->src))
++            {
++              /* FIXME: sorting by offset, to ensure as
++                 good as possible contiguous access will
++                 require a more complex node structure:
++                 with aggregation per 'dest', and
++                 internal sorting within that */
++              prepend (&vtr->sorted, p);
++            }
++            else
++              prepend (&pending, p);
 +          }
-+        vtrel_sec->flags |= SEC_EXCLUDE;
++        vtr->unsorted = pending;
 +      }
-+  }
-   else
-     {
-       dynamic = TRUE;
-@@ -3603,6 +3649,7 @@
-   else
-     hdr = &elf_tdata (abfd)->dynsymtab_hdr;
- 
-+/* FIXME: cut/paste this ! ....*/
-   symcount = hdr->sh_size / bed->s->sizeof_sym;
- 
-   /* The sh_info field of the symtab header tells us where the
-@@ -4978,8 +5025,14 @@
-   switch (bfd_get_format (abfd))
-     {
-     case bfd_object:
-+      fprintf (stderr, "add_symbols from %s object '%s'\n",
-+               abfd->flags & DYNAMIC ? "dynamic" : "static",
-+               abfd->filename);
-+      // from an .o or .so file ...
-       return elf_link_add_object_symbols (abfd, info);
-     case bfd_archive:
-+      fprintf (stderr, "add_symbols from archive '%s'\n", abfd->filename);
-+      // from a .a file ...
-       return elf_link_add_archive_symbols (abfd, info);
-     default:
-       bfd_set_error (bfd_error_wrong_format);
-@@ -5372,6 +5425,8 @@
- 	}
-     }
- 
-+  _bfd_elf_vtreloc_accumulate (output_bfd, info);
-+
-   /* Any syms created from now on start with -1 in
-      got.refcount/offset and plt.refcount/offset.  */
-   elf_hash_table (info)->init_got_refcount
-@@ -7159,6 +7214,8 @@
-   size_t symbuf_size;
-   /* And same for symshndxbuf.  */
-   size_t shndxbuf_size;
-+  /* .suse.vtreloc section.  */
-+  asection *vtreloc_sec;
- };
- 
- /* This struct is used to pass information to elf_link_output_extsym.  */
-@@ -7902,6 +7959,8 @@
-   bfd_vma r_type_mask;
-   int r_sym_shift;
- 
-+  fprintf (stderr, "elf_link_adjust_relocs ... %p\n", rel_hash);
++    while (pending);
++    fprintf (stderr, " done\n");
++}
 +
-   if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
-     {
-       swap_in = bed->s->swap_reloc_in;
-@@ -10038,6 +10097,7 @@
-       finfo.dynsym_sec = NULL;
-       finfo.hash_sec = NULL;
-       finfo.symver_sec = NULL;
-+      finfo.vtreloc_sec = NULL;
-     }
-   else
-     {
-@@ -10045,6 +10105,7 @@
-       finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
-       BFD_ASSERT (finfo.dynsym_sec != NULL);
-       finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
-+      finfo.vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
-       /* Note that it is OK if symver_sec is NULL.  */
-     }
- 
-@@ -10104,6 +10165,10 @@
-   max_sym_count = 0;
-   max_sym_shndx_count = 0;
-   merged = FALSE;
++static void
++check_reloc (Elf_Internal_Rela *rel, int type_mask)
++{
++  if ((rel->r_info & type_mask) != STT_OBJECT)
++      fprintf (stderr, "broken vtreloc type\n");
++  if (rel->r_addend != 0)
++      fprintf (stderr, "unexpected reloc addend\n");
++}
 +
-+  if (dynobj && !info->relocatable)
-+    _bfd_elf_vtreloc_fill (finfo.output_bfd, info);
-+
-   for (o = abfd->sections; o != NULL; o = o->next)
-     {
-       struct bfd_elf_section_data *esdo = elf_section_data (o);
-@@ -10732,6 +10797,10 @@
-       if ((o->flags & SEC_RELOC) == 0)
- 	continue;
- 
-+      fprintf (stderr, "rel_hashes for asec %p is %d, %p\n", o,
-+               (int)elf_section_data (o)->rel_count,
-+               elf_section_data (o)->rel_hashes);
-+
-       elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr,
- 			      elf_section_data (o)->rel_count,
- 			      elf_section_data (o)->rel_hashes);
-@@ -10869,6 +10938,9 @@
- 	    case DT_VERNEED:
- 	      name = ".gnu.version_r";
- 	      goto get_vma;
-+	    case DT_SUSE_VTRELOC:
-+	      name = ".suse.vtrelocs";
-+	      goto get_vma;
- 	    case DT_VERSYM:
- 	      name = ".gnu.version";
- 	    get_vma:
-@@ -11129,6 +11201,8 @@
-   bfd_boolean is_eh;
-   asection *group_sec;
- 
-+/* #warning "Do we want to ignore relocs inside .suse.vtreloc ?" */
-+
-   sec->gc_mark = 1;
- 
-   /* Mark all the sections in the group.  */
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/include/bfdlink.h binutils-2.17.50/include/bfdlink.h
---- binutils-2.17.50/include/bfdlink.h	2007-07-10 12:10:44.000000000 +0100
-+++ binutils-2.17.50/include/bfdlink.h	2008-01-09 12:42:12.000000000 +0000
-@@ -293,6 +293,10 @@
-   /* TRUE if the new ELF dynamic tags are enabled. */
-   unsigned int new_dtags: 1;
- 
-+  /* TRUE if we want to produce copy-based vtable relocation
-+     data. This saves both space and time.  */
-+  unsigned int vtreloc: 1;
-+
-   /* TRUE if non-PLT relocs should be merged into one reloc section
-      and sorted so that relocs against the same symbol come together.  */
-   unsigned int combreloc: 1;
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/include/elf/common.h binutils-2.17.50/include/elf/common.h
---- binutils-2.17.50/include/elf/common.h	2007-07-10 12:10:44.000000000 +0100
-+++ binutils-2.17.50/include/elf/common.h	2008-01-09 13:19:01.000000000 +0000
-@@ -624,6 +624,13 @@
- #define DT_USED		0x7ffffffe
- #define DT_FILTER	0x7fffffff
- 
-+/* SUSE specific pieces - at a random OS specific address, after
-+   previous 2 (direct/hashvals) development sections  */
-+#define DT_SUSE_LO (0x6cbdd030 + 2)
-+#define DT_SUSE_VTRELOC   DT_SUSE_LO
-+#define DT_SUSE_HI 0x6cbdd040
-+#define DT_SUSE_TAGIDX(tag) (tag - DT_SUSE_LO)
-+#define DT_SUSENUM 1
- 
- /* Values used in DT_FEATURE .dynamic entry.  */
- #define DTF_1_PARINIT	0x00000001
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/ld/ldmain.c binutils-2.17.50/ld/ldmain.c
---- binutils-2.17.50/ld/ldmain.c	2008-01-09 11:23:41.000000000 +0000
-+++ binutils-2.17.50/ld/ldmain.c	2008-01-09 12:42:11.000000000 +0000
-@@ -1105,6 +1105,7 @@
- 	    asection *section,
- 	    bfd_vma value)
- {
-+  fprintf (stderr, "add_to_set '%s'\n", h->root.string);
-   if (config.warn_constructors)
-     einfo (_("%P: warning: global constructor %s used\n"),
- 	   h->root.string);
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/ld/lexsup.c binutils-2.17.50/ld/lexsup.c
---- binutils-2.17.50/ld/lexsup.c	2008-01-09 11:23:41.000000000 +0000
-+++ binutils-2.17.50/ld/lexsup.c	2008-01-09 12:42:11.000000000 +0000
-@@ -157,6 +157,7 @@
-   OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
-   OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH,
-   OPTION_PIE,
-+  OPTION_VTRELOC,
-   OPTION_UNRESOLVED_SYMBOLS,
-   OPTION_WARN_UNRESOLVED_SYMBOLS,
-   OPTION_ERROR_UNRESOLVED_SYMBOLS,
-@@ -409,6 +410,8 @@
-   { {"no-undefined", no_argument, NULL, OPTION_NO_UNDEFINED},
-     '\0', NULL, N_("Do not allow unresolved references in object files"),
-     TWO_DASHES },
-+  { {"vtreloc", no_argument, NULL, OPTION_VTRELOC},
-+    '\0', NULL, N_("Build vtable copy reloc data"), TWO_DASHES },
-   { {"allow-shlib-undefined", no_argument, NULL, OPTION_ALLOW_SHLIB_UNDEFINED},
-     '\0', NULL, N_("Allow unresolved references in shared libaries"),
-     TWO_DASHES },
-@@ -1171,6 +1174,9 @@
- 	case OPTION_DEFAULT_SCRIPT:
- 	  command_line.default_script = optarg;
- 	  break;
-+	case OPTION_VTRELOC:
-+	  link_info.vtreloc = TRUE;
-+	  break;
- 	case OPTION_SECTION_START:
- 	  {
- 	    char *optarg2;
-diff -u -r -x cc-nptl -x build-dir -x '*.orig' -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.17.50/ld/scripttempl/elf.sc binutils-2.17.50/ld/scripttempl/elf.sc
---- binutils-2.17.50/ld/scripttempl/elf.sc	2007-07-10 12:10:44.000000000 +0100
-+++ binutils-2.17.50/ld/scripttempl/elf.sc	2008-01-09 12:42:12.000000000 +0000
-@@ -285,6 +285,7 @@
- eval $COMBRELOCCAT <<EOF
-   .rel.init     ${RELOCATING-0} : { *(.rel.init) }
-   .rela.init    ${RELOCATING-0} : { *(.rela.init) }
-+  .rel.suse.vtrelocs     ${RELOCATING-0} : { *(.rel.suse.vtrelocs) }
-   .rel.text     ${RELOCATING-0} : { *(.rel.text${RELOCATING+ .rel.text.* .rel.gnu.linkonce.t.*}) }
-   .rela.text    ${RELOCATING-0} : { *(.rela.text${RELOCATING+ .rela.text.* .rela.gnu.linkonce.t.*}) }
-   .rel.fini     ${RELOCATING-0} : { *(.rel.fini) }
-@@ -321,7 +322,7 @@
-     {
- EOF
- sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/      \1/' $COMBRELOC
--cat <<EOF
-+cat <<EOF 
-     }
-   .rela.dyn     ${RELOCATING-0} :
-     {
-@@ -410,6 +411,13 @@
-   ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}}
-   .jcr          ${RELOCATING-0} : { KEEP (*(.jcr)) }
- 
-+  /* Virtual table copy relocation tables */
-+  __vtrelocs = .;
-+  .suse.vtrelocs  :
-+  {
-+    KEEP (*(.suse.vtrelocs))
-+  }
-+
-   ${RELOCATING+${DATARELRO}}
-   ${OTHER_RELRO_SECTIONS}
-   ${TEXT_DYNAMIC-${DYNAMIC}}
---- /dev/null	2007-09-21 22:50:58.000000000 +0100
-+++ binutils-2.17.50/bfd/elf-vtreloc.c	2008-01-10 15:52:00.000000000 +0000
-@@ -0,0 +1,552 @@
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "sysdep.h"
-+#include "bfdlink.h"
-+#include "libbfd.h"
-+#define ARCH_SIZE 0
-+#include "elf-bfd.h"
-+#include "safe-ctype.h"
-+#include "libiberty.h"
-+
-+typedef struct _CopyEntry CopyEntry;
-+
-+typedef struct {
-+    bfd       *abfd;
-+    CopyEntry *sorted;
-+    CopyEntry *unsorted;
-+} VtRelocs;
-+
-+struct _CopyEntry {
-+    struct elf_link_hash_entry *src;
-+    bfd_vma                     src_offset;
-+    struct elf_link_hash_entry *dest;
-+    bfd_vma                     dest_offset;
-+    bfd_vma                     bitmask;
-+
-+    /* chain */
-+    CopyEntry *next;
-+};
-+
-+static void
-+prepend (CopyEntry **list, CopyEntry *p)
-+{
-+    p->next = *list;
-+    *list = p;
-+}
-+
-+static int
-+copy_entry_equal (const CopyEntry *a, const CopyEntry *b)
-+{
-+    return (a->src == b->src &&
-+            a->src_offset == b->src_offset &&
-+            a->dest == b->dest &&
-+            a->dest_offset == b->dest_offset &&
-+            a->bitmask == b->bitmask);
-+}
-+
-+/*
-+ * FIXME - should be a hash lookup / something fast.
-+ */
-+static CopyEntry *
-+find_with_dest (CopyEntry *list,
-+                struct elf_link_hash_entry *e)
-+{
-+    while (list)
-+      {
-+        if (list->dest == e)
-+          break;
-+        list = list->next;
-+      }
-+    return list;
-+}
-+
-+static CopyEntry *
-+find_equal_entry (CopyEntry *list, CopyEntry *e)
-+{
-+  while (list)
-+    {
-+      if (copy_entry_equal (list, e))
-+        break;
-+      list = list->next;
-+    }
-+  return list;
-+}
-+
-+/*
-+ * Transfer from unsorted -> sorted.
-+ * NB. simple-minded algorithm, N^3 with degenerate case
-+ */
-+static void
-+sort_relocs (VtRelocs *vtr)
-+{
-+    CopyEntry *p;
-+    CopyEntry *pending;
-+    CopyEntry *next;
-+
-+    fprintf (stderr, "Sorting ...");
-+    do
-+      {
-+        pending = NULL;
-+        
-+        for (p = vtr->unsorted; p; p = next)
-+          {
-+            next = p->next;
-+            if (!find_with_dest (vtr->unsorted, p->src))
-+            {
-+              /* FIXME: sorting by offset, to ensure as
-+                 good as possible contiguous access will
-+                 require a more complex node structure:
-+                 with aggregation per 'dest', and
-+                 internal sorting within that */
-+              prepend (&vtr->sorted, p);
-+            }
-+            else
-+              prepend (&pending, p);
-+          }
-+        vtr->unsorted = pending;
-+      }
-+    while (pending);
-+    fprintf (stderr, " done\n");
-+}
-+
-+static void
-+check_reloc (Elf_Internal_Rela *rel, int type_mask)
-+{
-+  if ((rel->r_info & type_mask) != STT_OBJECT)
-+      fprintf (stderr, "broken vtreloc type\n");
-+  if (rel->r_addend != 0)
-+      fprintf (stderr, "unexpected reloc addend\n");
-+}
-+
-+static void
-+print_rel (const char *type, 
-+           struct elf_link_hash_entry *target)
-+{
-+  fprintf (stderr, "%s '%s' %d %d %d %d i:%ld\n",
-+           type, target->root.root.string,
-+           target->ref_regular, target->def_regular,
-+           target->ref_dynamic, target->def_dynamic,
-+           target->dynindx);
-+}
++static void
++print_rel (const char *type, 
++           struct elf_link_hash_entry *target)
++{
++  fprintf (stderr, "%s '%s' %d %d %d %d i:%ld\n",
++           type, target->root.root.string,
++           target->ref_regular, target->def_regular,
++           target->ref_dynamic, target->def_dynamic,
++           target->dynindx);
++}
 +
 +static void
 +add_reloc (VtRelocs *vtr,
@@ -477,10 +777,24 @@
 +  check_reloc (src_rel, r_type_mask);
 +  check_reloc (dest_rel, r_type_mask);
 +
-+  symidx = (dest_rel->r_info >> r_sym_shift) - hdr->sh_info;
-+  fprintf (stderr, "symidx %d!\n", symidx);
-+  dest = elf_sym_hashes (inputobj) [symidx];
++/*
++#define elf_sym_hashes(bfd)	(elf_tdata(bfd) -> sym_hashes)
++#define elf_tdata(bfd)		((bfd) -> tdata.elf_obj_data)
++  Elf
++  cf. RELOC_FOR_GLOBAL_SYMBOL ...
++*/
++
++  symidx = (dest_rel->r_info >> r_sym_shift);
++  fprintf (stderr, "symidx %d (-%d)!\n", symidx, hdr->sh_info);
 +
++  if (symidx < hdr->sh_info) // local symbol ...
++  {
++      fprintf (stderr, "Error/FIXME: local dest symbol !");
++      return;
++  }
++
++  symidx -= hdr->sh_info;
++  dest = elf_sym_hashes (inputobj) [symidx];
 +  if (!dest) {
 +      fprintf (stderr, "no rel %d!\n", symidx);
 +      return;
@@ -497,12 +811,36 @@
 +      return;
 +    }
 +
-+  /* Consider: should we eliminate all internal -> internal
-+     copies ? it's possible we are more space / time
-+     efficient - so no for now. */
++  // FIXME: do we need something like this for indirect / warnings !?
++/*    while (target->root.type == bfd_link_hash_indirect
++           || target->root.type == bfd_link_hash_warning)
++           target = (struct elf_link_hash_entry *) target->root.u.i.link; */
++  fprintf (stderr, "dest link type %d\n", dest->root.type);
++  if (dest->root.type == bfd_link_hash_undefined ||
++      dest->root.type == bfd_link_hash_undefweak)
++    {
++      fprintf (stderr, "undefined dest sym '%s'\n", dest->root.root.string);
++      return;
++    }
++
++  /* Consider: should we eliminate all internal -> internal
++     copies ? it's possible we are more space / time
++     efficient - so no for now. */
 +
-+  symidx = (src_rel->r_info >> r_sym_shift) - hdr->sh_info;
++  symidx = (src_rel->r_info >> r_sym_shift);
++  if (symidx < hdr->sh_info) // local symbol ...
++  {
++      fprintf (stderr, "Error/FIXME: local src symbol !");
++      return;
++  }
++  symidx -= hdr->sh_info;
 +  src = elf_sym_hashes (inputobj) [symidx];
++  if (src->root.type == bfd_link_hash_undefined ||
++      src->root.type == bfd_link_hash_undefweak)
++    {
++      fprintf (stderr, "undefined src sym '%s'\n", src->root.root.string);
++      return;
++    }
 +
 +  print_rel ("Src", src);
 +  print_rel ("Dst", dest);
@@ -628,7 +966,10 @@
 +            return FALSE;
 +
 +          if (es->this_hdr.sh_size % s->reloc_count != 0)
-+              fprintf (stderr, "ERROR: mismatching vtreloc sec & reloc count\n");
++              fprintf (stderr, "ERROR: mismatching vtreloc sec & reloc count "
++                       "0x%x, 0x%x -> %d\n",
++                       (int)es->this_hdr.sh_size, (int)s->reloc_count,
++                       (int)es->this_hdr.sh_size % s->reloc_count);
 +
 +          /* Assumes an even number of relocs sorted by address ... */
 +          for (i = 0; i < s->reloc_count / 2; i++)
@@ -645,6 +986,7 @@
 +          if (es->relocs != relocs)
 +              free (relocs);
 +        }
++
 +      /* So - we need to sort these guys as we work out the sizes */
 +      /* We need to generate an internal list of XYZ type 
 +           + eliminate all external -> external work ... 
@@ -708,7 +1050,6 @@
 +  else
 +    {
 +      asection *vtreloc_sec;
-+      fprintf (stderr, "TESTME: exclude .vtrelocs if none present\n");
 +      vtreloc_sec = bfd_get_section_by_name (dynobj, ".vtrelocs");
 +      if (vtreloc_sec)
 +        vtreloc_sec->flags |= SEC_EXCLUDE;
@@ -864,24 +1205,8 @@
 +    }
 +  return TRUE;
 +}
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/bfd/elf-bfd.h binutils-2.17.50/bfd/elf-bfd.h
---- /usr/src/packages/BUILD/binutils-2.17.50/bfd/elf-bfd.h	2007-07-19 09:51:03.000000000 +0100
-+++ binutils-2.17.50/bfd/elf-bfd.h	2008-01-09 17:04:17.000000000 +0000
-@@ -1787,6 +1787,12 @@
- extern void _bfd_elf_init_2_index_sections
-   (bfd *, struct bfd_link_info *);
- 
-+/* elf-vtreloc */
-+extern bfd_boolean _bfd_elf_vtreloc_accumulate
-+  (bfd *, struct bfd_link_info *);
-+extern bfd_boolean _bfd_elf_vtreloc_fill
-+  (bfd *, struct bfd_link_info *);
-+
- extern bfd_boolean _bfd_elfcore_make_pseudosection
-   (bfd *, char *, size_t, ufile_ptr);
- extern char *_bfd_elfcore_strndup
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/bfd/elf.c binutils-2.17.50/bfd/elf.c
---- /usr/src/packages/BUILD/binutils-2.17.50/bfd/elf.c	2007-07-24 10:50:16.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/bfd/elf.c binutils-2.17.50/bfd/elf.c
+--- pristine-binutils-2.17.50/bfd/elf.c	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/bfd/elf.c	2008-01-09 17:04:17.000000000 +0000
 @@ -1240,6 +1240,7 @@
  	    case DT_USED: name = "USED"; break;
@@ -891,9 +1216,9 @@
  	    }
  
  	  fprintf (f, "  %-11s ", name);
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/bfd/elflink.c binutils-2.17.50/bfd/elflink.c
---- /usr/src/packages/BUILD/binutils-2.17.50/bfd/elflink.c	2007-07-25 09:33:23.000000000 +0100
-+++ binutils-2.17.50/bfd/elflink.c	2008-01-10 15:54:03.000000000 +0000
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/bfd/elflink.c binutils-2.17.50/bfd/elflink.c
+--- pristine-binutils-2.17.50/bfd/elflink.c	2008-01-09 16:45:22.000000000 +0000
++++ binutils-2.17.50/bfd/elflink.c	2008-01-14 14:28:26.000000000 +0000
 @@ -148,6 +148,34 @@
    return TRUE;
  }
@@ -1085,8 +1410,27 @@
    sec->gc_mark = 1;
  
    /* Mark all the sections in the group.  */
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/include/bfdlink.h binutils-2.17.50/include/bfdlink.h
---- /usr/src/packages/BUILD/binutils-2.17.50/include/bfdlink.h	2007-07-10 12:10:44.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/bfd/elflink.c~ binutils-2.17.50/bfd/elflink.c~
+--- pristine-binutils-2.17.50/bfd/elflink.c~	2008-01-09 12:42:12.000000000 +0000
++++ binutils-2.17.50/bfd/elflink.c~	2008-01-09 17:04:17.000000000 +0000
+@@ -10097,6 +10097,7 @@
+       finfo.dynsym_sec = NULL;
+       finfo.hash_sec = NULL;
+       finfo.symver_sec = NULL;
++      finfo.vtreloc_sec = NULL;
+     }
+   else
+     {
+@@ -10104,6 +10105,7 @@
+       finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
+       BFD_ASSERT (finfo.dynsym_sec != NULL);
+       finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
++      finfo.vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
+       /* Note that it is OK if symver_sec is NULL.  */
+     }
+ 
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/include/bfdlink.h binutils-2.17.50/include/bfdlink.h
+--- pristine-binutils-2.17.50/include/bfdlink.h	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/include/bfdlink.h	2008-01-09 17:04:17.000000000 +0000
 @@ -293,6 +293,10 @@
    /* TRUE if the new ELF dynamic tags are enabled. */
@@ -1099,8 +1443,8 @@
    /* TRUE if non-PLT relocs should be merged into one reloc section
       and sorted so that relocs against the same symbol come together.  */
    unsigned int combreloc: 1;
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/include/elf/common.h binutils-2.17.50/include/elf/common.h
---- /usr/src/packages/BUILD/binutils-2.17.50/include/elf/common.h	2007-07-10 12:10:44.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/include/elf/common.h binutils-2.17.50/include/elf/common.h
+--- pristine-binutils-2.17.50/include/elf/common.h	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/include/elf/common.h	2008-01-09 17:04:17.000000000 +0000
 @@ -624,6 +624,13 @@
  #define DT_USED		0x7ffffffe
@@ -1116,8 +1460,8 @@
  
  /* Values used in DT_FEATURE .dynamic entry.  */
  #define DTF_1_PARINIT	0x00000001
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/ld/ldmain.c binutils-2.17.50/ld/ldmain.c
---- /usr/src/packages/BUILD/binutils-2.17.50/ld/ldmain.c	2008-01-09 11:23:41.000000000 +0000
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/ld/ldmain.c binutils-2.17.50/ld/ldmain.c
+--- pristine-binutils-2.17.50/ld/ldmain.c	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/ld/ldmain.c	2008-01-09 17:04:17.000000000 +0000
 @@ -1105,6 +1105,7 @@
  	    asection *section,
@@ -1127,8 +1471,8 @@
    if (config.warn_constructors)
      einfo (_("%P: warning: global constructor %s used\n"),
  	   h->root.string);
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/ld/lexsup.c binutils-2.17.50/ld/lexsup.c
---- /usr/src/packages/BUILD/binutils-2.17.50/ld/lexsup.c	2008-01-09 11:23:41.000000000 +0000
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/ld/lexsup.c binutils-2.17.50/ld/lexsup.c
+--- pristine-binutils-2.17.50/ld/lexsup.c	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/ld/lexsup.c	2008-01-09 17:04:17.000000000 +0000
 @@ -157,6 +157,7 @@
    OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
@@ -1157,8 +1501,8 @@
  	case OPTION_SECTION_START:
  	  {
  	    char *optarg2;
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/binutils-2.17.50/ld/scripttempl/elf.sc binutils-2.17.50/ld/scripttempl/elf.sc
---- /usr/src/packages/BUILD/binutils-2.17.50/ld/scripttempl/elf.sc	2007-07-10 12:10:44.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' pristine-binutils-2.17.50/ld/scripttempl/elf.sc binutils-2.17.50/ld/scripttempl/elf.sc
+--- pristine-binutils-2.17.50/ld/scripttempl/elf.sc	2008-01-09 16:45:22.000000000 +0000
 +++ binutils-2.17.50/ld/scripttempl/elf.sc	2008-01-09 17:04:17.000000000 +0000
 @@ -285,6 +285,7 @@
  eval $COMBRELOCCAT <<EOF
@@ -1191,558 +1535,3 @@
    ${RELOCATING+${DATARELRO}}
    ${OTHER_RELRO_SECTIONS}
    ${TEXT_DYNAMIC-${DYNAMIC}}
---- /dev/null	2007-09-21 22:50:58.000000000 +0100
-+++ binutils-2.17.50/bfd/elf-vtreloc.c	2008-01-10 15:52:00.000000000 +0000
-@@ -0,0 +1,552 @@
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "sysdep.h"
-+#include "bfdlink.h"
-+#include "libbfd.h"
-+#define ARCH_SIZE 0
-+#include "elf-bfd.h"
-+#include "safe-ctype.h"
-+#include "libiberty.h"
-+
-+typedef struct _CopyEntry CopyEntry;
-+
-+typedef struct {
-+    bfd       *abfd;
-+    CopyEntry *sorted;
-+    CopyEntry *unsorted;
-+} VtRelocs;
-+
-+struct _CopyEntry {
-+    struct elf_link_hash_entry *src;
-+    bfd_vma                     src_offset;
-+    struct elf_link_hash_entry *dest;
-+    bfd_vma                     dest_offset;
-+    bfd_vma                     bitmask;
-+
-+    /* chain */
-+    CopyEntry *next;
-+};
-+
-+static void
-+prepend (CopyEntry **list, CopyEntry *p)
-+{
-+    p->next = *list;
-+    *list = p;
-+}
-+
-+static int
-+copy_entry_equal (const CopyEntry *a, const CopyEntry *b)
-+{
-+    return (a->src == b->src &&
-+            a->src_offset == b->src_offset &&
-+            a->dest == b->dest &&
-+            a->dest_offset == b->dest_offset &&
-+            a->bitmask == b->bitmask);
-+}
-+
-+/*
-+ * FIXME - should be a hash lookup / something fast.
-+ */
-+static CopyEntry *
-+find_with_dest (CopyEntry *list,
-+                struct elf_link_hash_entry *e)
-+{
-+    while (list)
-+      {
-+        if (list->dest == e)
-+          break;
-+        list = list->next;
-+      }
-+    return list;
-+}
-+
-+static CopyEntry *
-+find_equal_entry (CopyEntry *list, CopyEntry *e)
-+{
-+  while (list)
-+    {
-+      if (copy_entry_equal (list, e))
-+        break;
-+      list = list->next;
-+    }
-+  return list;
-+}
-+
-+/*
-+ * Transfer from unsorted -> sorted.
-+ * NB. simple-minded algorithm, N^3 with degenerate case
-+ */
-+static void
-+sort_relocs (VtRelocs *vtr)
-+{
-+    CopyEntry *p;
-+    CopyEntry *pending;
-+    CopyEntry *next;
-+
-+    fprintf (stderr, "Sorting ...");
-+    do
-+      {
-+        pending = NULL;
-+        
-+        for (p = vtr->unsorted; p; p = next)
-+          {
-+            next = p->next;
-+            if (!find_with_dest (vtr->unsorted, p->src))
-+            {
-+              /* FIXME: sorting by offset, to ensure as
-+                 good as possible contiguous access will
-+                 require a more complex node structure:
-+                 with aggregation per 'dest', and
-+                 internal sorting within that */
-+              prepend (&vtr->sorted, p);
-+            }
-+            else
-+              prepend (&pending, p);
-+          }
-+        vtr->unsorted = pending;
-+      }
-+    while (pending);
-+    fprintf (stderr, " done\n");
-+}
-+
-+static void
-+check_reloc (Elf_Internal_Rela *rel, int type_mask)
-+{
-+  if ((rel->r_info & type_mask) != STT_OBJECT)
-+      fprintf (stderr, "broken vtreloc type\n");
-+  if (rel->r_addend != 0)
-+      fprintf (stderr, "unexpected reloc addend\n");
-+}
-+
-+static void
-+print_rel (const char *type, 
-+           struct elf_link_hash_entry *target)
-+{
-+  fprintf (stderr, "%s '%s' %d %d %d %d i:%ld\n",
-+           type, target->root.root.string,
-+           target->ref_regular, target->def_regular,
-+           target->ref_dynamic, target->def_dynamic,
-+           target->dynindx);
-+}
-+
-+static void
-+add_reloc (VtRelocs *vtr,
-+           bfd      *inputobj,
-+           Elf_Internal_Rela *src_rel,
-+           Elf_Internal_Rela *dest_rel,
-+           unsigned char     *data)
-+{
-+  unsigned r_sym_shift;
-+  unsigned r_type_mask;
-+  unsigned incr;
-+  unsigned symidx;
-+  const struct elf_backend_data *bed;
-+  struct elf_link_hash_entry *dest, *src;
-+  Elf_Internal_Shdr *hdr;
-+  CopyEntry *e;
-+
-+  hdr = &elf_tdata (inputobj)->symtab_hdr;
-+  bed = get_elf_backend_data (inputobj);
-+  if (bed->s->arch_size == 32)
-+    {
-+      r_type_mask = 0xff;
-+      r_sym_shift = 8;
-+      incr = 4;
-+    }
-+  else
-+    {
-+      r_type_mask = 0xffffffff;
-+      r_sym_shift = 32;
-+      incr = 8;
-+    }
-+
-+  check_reloc (src_rel, r_type_mask);
-+  check_reloc (dest_rel, r_type_mask);
-+
-+  symidx = (dest_rel->r_info >> r_sym_shift) - hdr->sh_info;
-+  fprintf (stderr, "symidx %d!\n", symidx);
-+  dest = elf_sym_hashes (inputobj) [symidx];
-+
-+  if (!dest) {
-+      fprintf (stderr, "no rel %d!\n", symidx);
-+      return;
-+  }
-+
-+  /* Eliminate relocs to no longer present internal vtables. */
-+  if (!dest->def_regular)
-+    {
-+      print_rel ("Abandoning dest", dest);
-+      fprintf (stderr, "Ref count %ld %ld dynindx %d\n",
-+               dest->got.refcount, dest->plt.refcount,
-+               (int) dest->dynindx);
-+      /* unref the symbol somehow (!?) */
-+      return;
-+    }
-+
-+  /* Consider: should we eliminate all internal -> internal
-+     copies ? it's possible we are more space / time
-+     efficient - so no for now. */
-+
-+  symidx = (src_rel->r_info >> r_sym_shift) - hdr->sh_info;
-+  src = elf_sym_hashes (inputobj) [symidx];
-+
-+  print_rel ("Src", src);
-+  print_rel ("Dst", dest);
-+
-+  e = bfd_zalloc (vtr->abfd, sizeof (CopyEntry));
-+
-+  e->src = src;
-+  e->dest = dest;
-+
-+  if (dest_rel->r_offset - src_rel->r_offset != bed->s->arch_size / 8)
-+      fprintf (stderr, "Mis-paired vtrelocs\n");
-+
-+  e->src_offset = bfd_get (bed->s->arch_size, inputobj, data);
-+  data += incr;
-+  e->dest_offset = bfd_get (bed->s->arch_size, inputobj, data);
-+  data += incr;
-+  e->bitmask = bfd_get (bed->s->arch_size, inputobj, data);
-+
-+  /* Simple minded dupliates elision */
-+  if (find_equal_entry (vtr->unsorted, e))
-+    bfd_release (vtr->abfd, e);          
-+  else
-+    {
-+      prepend (&vtr->unsorted, e);  
-+
-+      fprintf (stderr, "Copy: '%s'+%d -> '%s'+%d (0x%x)\n",
-+               e->src->root.root.string,
-+               (int)e->src_offset,
-+               e->dest->root.root.string,
-+               (int)e->dest_offset,
-+               (int)e->bitmask);
-+    }
-+}
-+
-+static VtRelocs *global_vtr;
-+
-+bfd_boolean _bfd_elf_vtreloc_accumulate (bfd *output_bfd,
-+                                         struct bfd_link_info *info)
-+{
-+  bfd *dynobj;
-+  dynobj = elf_hash_table (info)->dynobj;
-+  if (info->vtreloc)
-+    { // .vtrelocs
-+      bfd_size_type sec_size = 0;
-+      asection *vtreloc_sec;
-+      asection *vtrelrel;
-+      bfd *inputobj;
-+      VtRelocs *vtr;
-+      Elf_Internal_Rela last_rela;
-+      bfd_size_type num_relocs;
-+
-+      vtr = bfd_zalloc (output_bfd, sizeof (VtRelocs));
-+      vtr->abfd = output_bfd;
-+      global_vtr = vtr;
-+
-+      /* FIXME: we need to elide relocs that turn out
-+         to be purely internal:
-+         eg. internal -> internal copy src / dest,
-+         others are less troublesome - though removing
-+         empty ones would be nice (?).
-+         We want to trap every -named- reloc ...
-+      */
-+      for (inputobj = info->input_bfds;
-+	   inputobj;
-+	   inputobj = inputobj->link_next)
-+	{
-+	  asection *s;
-+          struct bfd_elf_section_data *es; /* elf-bfd.h */
-+          unsigned i;
-+          Elf_Internal_Rela *relocs, *p;
-+          unsigned char *sec_data;
-+	  long storage_needed;
-+	  asymbol **symtab;
-+	  long number_of_symbols;
-+	  const struct elf_backend_data *bed = get_elf_backend_data (inputobj);
-+
-+	  if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
-+	    continue;
-+	  s = bfd_get_section_by_name (inputobj, ".vtrelocs");
-+          if (!s)
-+            continue;
-+	  /* XXX Hmm, this seems to generate many NONE relocs, probably from
-+	     the original relocs to this section.  Perhaps discard them
-+	     earlier.  */
-+	  s->flags |= SEC_EXCLUDE;
-+          es = elf_section_data (s);
-+          if (!es)
-+            continue;
-+
-+          if (!s->reloc_count)
-+            continue;
-+
-+          fprintf (stderr, "Relocs: size %d, count %d contents %p\n",
-+                   (int)es->rel_hdr.sh_size, es->rel_count,
-+                   s->contents);
-+          
-+
-+          /* Can't find this info anywhere else for some reason: */
-+          p = relocs = _bfd_elf_link_read_relocs (inputobj, s, NULL, NULL,
-+                                                  info->keep_memory);
-+
-+	  /* Experimental stuff to get at the BFD relocs (translated back
-+	     from the real ELF relocs.  */
-+	  storage_needed = bfd_get_symtab_upper_bound (inputobj);
-+	  if (storage_needed <= 0)
-+	    return FALSE;
-+	  symtab = xmalloc (storage_needed);
-+	  number_of_symbols = bfd_canonicalize_symtab (inputobj, symtab);
-+	  if (number_of_symbols < 0)
-+	    return FALSE;
-+
-+	  if (! bed->s->slurp_reloc_table (inputobj, s, symtab, FALSE))
-+	    return FALSE;
-+          
-+	  /* Now inputobj->relocation will contain BFD relocs.  */
-+
-+          sec_data = bfd_malloc (es->this_hdr.sh_size);
-+          
-+          /* Slurp the data */
-+          if (bfd_seek (inputobj, es->this_hdr.sh_offset, SEEK_SET) != 0)
-+            return FALSE;
-+          if (bfd_bread (sec_data, es->this_hdr.sh_size, inputobj) != es->this_hdr.sh_size)
-+            return FALSE;
-+
-+          if (es->this_hdr.sh_size % s->reloc_count != 0)
-+              fprintf (stderr, "ERROR: mismatching vtreloc sec & reloc count\n");
-+
-+          /* Assumes an even number of relocs sorted by address ... */
-+          for (i = 0; i < s->reloc_count / 2; i++)
-+          {
-+              unsigned int entry_size;
-+              entry_size = (get_elf_backend_data (inputobj)->s->arch_size / 8) * 3;
-+              
-+	      last_rela = *p;
-+              add_reloc (vtr, inputobj, p, p + 1,
-+                         sec_data + i * entry_size);
-+              p+=2;
-+          }
-+          free (sec_data);
-+          if (es->relocs != relocs)
-+              free (relocs);
-+        }
-+      /* So - we need to sort these guys as we work out the sizes */
-+      /* We need to generate an internal list of XYZ type 
-+           + eliminate all external -> external work ... 
-+           + add all external -> internal copies to 'sorted' list
-+              + [ fool-proof GC roots ]
-+           + add other symbols to 'pending' list.
-+           + read / generate src: [symbol + offset, dest: sym + offset, bitmask data]
-+      */
-+      sort_relocs (vtr);
-+      num_relocs = 0;
-+      sec_size = 0;
-+      {
-+        CopyEntry *e;
-+	for (e = vtr->sorted; e; e = e->next)
-+	  {
-+	    sec_size += 3;  /* Word entries.  */
-+	    num_relocs += 2;
-+	  }
-+      }
-+      /*
-+         Finally:
-+           + build new custom section
-+           + emit new relocations for it ...
-+      */
-+      
-+      vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
-+      if (vtreloc_sec)
-+        {
-+	  bfd_size_type rel_size;
-+	  bfd_size_type size;
-+	  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
-+	  vtrelrel = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
-+	  if (!vtrelrel)
-+	    return FALSE;
-+
-+          {
-+              unsigned int entry_size;
-+              entry_size = (bed->s->arch_size / 8);
-+              /* + 1 for null termination */
-+              vtreloc_sec->size = (sec_size + 1) * entry_size;
-+              vtreloc_sec->contents = bfd_zalloc (dynobj, vtreloc_sec->size);
-+//	      if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_VTRELOC, 0))
-+//	        return FALSE;
-+          }
-+
-+	  rel_size = bed->s->sizeof_rel;
-+	  if (bed->default_use_rela_p)
-+	    {
-+	      rel_size = bed->s->sizeof_rela;
-+	    }
-+
-+	  size = rel_size * num_relocs;
-+	  fprintf (stderr, "Need %ld bytes of relocs rel-size %ld\n",
-+                   size, rel_size);
-+	  vtrelrel->size = size;
-+        }
-+      else
-+        fprintf (stderr, "Horrendous error ! - no .suse.vtrelocs\n");
-+
-+    }
-+  else
-+    {
-+      asection *vtreloc_sec;
-+      fprintf (stderr, "TESTME: exclude .vtrelocs if none present\n");
-+      vtreloc_sec = bfd_get_section_by_name (dynobj, ".vtrelocs");
-+      if (vtreloc_sec)
-+        vtreloc_sec->flags |= SEC_EXCLUDE;
-+    }
-+  return TRUE;
-+}
-+
-+static void
-+generate_reloc (bfd                        *dynobj,
-+                struct elf_link_hash_entry *target,
-+                asection                   *vtreloc_sec,
-+                asection                   *vtrelrel,
-+                bfd_vma                     num_entry,
-+                int                         is_dest,
-+                bfd_size_type              *adjust_relative)
-+{
-+    bfd_size_type sym_idx, rel_size;
-+    reloc_howto_type *howto;
-+    void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
-+    bfd_byte *loc;
-+    Elf_Internal_Rela outrel;
-+    const struct elf_backend_data *bed;
-+
-+    bed = get_elf_backend_data (dynobj);
-+
-+    rel_size = bed->s->sizeof_rel;
-+    swap_out = bed->s->swap_reloc_out;
-+    if (bed->default_use_rela_p)
-+    {
-+        rel_size = bed->s->sizeof_rela;
-+        swap_out = bed->s->swap_reloca_out;
-+    }
-+
-+    /* XXX: unwind this goodness etc. */
-+    while (target->root.type == bfd_link_hash_indirect
-+           || target->root.type == bfd_link_hash_warning)
-+      target = (struct elf_link_hash_entry *) target->root.u.i.link;
-+
-+    fprintf (stderr, "Reloc '%s' %d %d %d %d i:%ld ",
-+             target->root.root.string,
-+             target->ref_regular, target->def_regular,
-+             target->ref_dynamic, target->def_dynamic,
-+             target->dynindx);
-+    if (is_dest /* force relative */ || target->dynindx <= 0)
-+      fprintf (stderr, "'%s' vma 0x%lx offset %ld output off %ld\n",
-+               target->root.u.def.section->name,
-+               target->root.u.def.section->output_section->vma,
-+               target->root.u.def.value,
-+               target->root.u.def.section->output_offset);
-+    else
-+      fprintf (stderr, "\n");
-+
-+    /* XXX: RELOC64 too */
-+    if (is_dest /* force relative */ || target->dynindx <= 0)
-+      { /* do a relative reloc ... */
-+        howto = bfd_reloc_type_lookup (dynobj, BFD_RELOC_386_RELATIVE);
-+        sym_idx = 0;
-+        BFD_ASSERT (target->root.type == bfd_link_hash_defweak);
-+        *adjust_relative = (target->root.u.def.section->output_section->vma +
-+                            target->root.u.def.section->output_offset);
-+      }
-+    else
-+      {
-+        howto = bfd_reloc_type_lookup (dynobj, BFD_RELOC_32);
-+        sym_idx = target->dynindx;
-+        *adjust_relative = 0;
-+      }
-+
-+    /* generate relocation */
-+    outrel.r_offset = vtreloc_sec->output_section->vma;
-+    outrel.r_offset += num_entry * 3 * 4; // XXX: 4 ?
-+    if (is_dest) outrel.r_offset += 4; // XXX: 4
-+    outrel.r_info = ELF32_R_INFO (sym_idx, howto->type);
-+    outrel.r_addend = 0;
-+
-+    loc = vtrelrel->contents + (vtrelrel->reloc_count++ * rel_size);
-+    swap_out (dynobj, &outrel, loc);
-+}
-+
-+bfd_boolean _bfd_elf_vtreloc_fill (bfd *output_bfd,
-+                                   struct bfd_link_info *info)
-+{
-+  bfd *dynobj;
-+  dynobj = elf_hash_table (info)->dynobj;
-+
-+  fprintf (stderr, "Foo: generate .suse.vtrelocs relocs\n");
-+
-+  if (info->vtreloc)
-+    {
-+      asection *vtreloc_sec;
-+      asection *vtrelrel;
-+
-+      vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
-+      if (vtreloc_sec)
-+        {
-+	  CopyEntry *e;
-+	  bfd_size_type entries, adjust_relative, entry_size;
-+	  const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
-+          bfd_byte *data;
-+
-+          entry_size = (bed->s->arch_size / 8);
-+
-+	  vtrelrel = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
-+	  if (!vtrelrel)
-+	    return FALSE;
-+	  if (!vtrelrel->contents)
-+	    {
-+	      fprintf (stderr, "Nothing allocated for relocs\n");
-+	      return FALSE;
-+	    }
-+
-+	  BFD_ASSERT (vtreloc_sec->output_offset == 0);
-+	  entries = 0;
-+	  vtrelrel->reloc_count = 0;
-+          data = vtreloc_sec->contents;
-+	  for (e = global_vtr->sorted; e; e = e->next)
-+	    {
-+	      /* Source */
-+              generate_reloc (output_bfd, e->src, vtreloc_sec, vtrelrel,
-+                              entries, FALSE, &adjust_relative);
-+              bfd_put(bed->s->arch_size, output_bfd,
-+                      e->src_offset + adjust_relative, data);
-+              data += entry_size;
-+
-+              /* Dest */
-+              generate_reloc (output_bfd, e->dest, vtreloc_sec, vtrelrel,
-+                              entries, TRUE, &adjust_relative);
-+              bfd_put(bed->s->arch_size, output_bfd,
-+                      e->dest_offset + adjust_relative, data);
-+              data += entry_size;
-+
-+              bfd_put(bed->s->arch_size, dynobj, e->bitmask, data);
-+              data += entry_size;
-+
-+              entries++;
-+            }
-+          BFD_ASSERT (vtrelrel->reloc_count * (bed->default_use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel)
-+                      == vtrelrel->size);
-+        }
-+      else
-+        fprintf (stderr, "Horrendous error ! - no .suse.vtrelocs\n");
-+    }
-+  else
-+    {
-+      asection *vtreloc_sec;
-+      fprintf (stderr, "TESTME: exclude .vtrelocs if none present\n");
-+      vtreloc_sec = bfd_get_section_by_name (dynobj, ".suse.vtrelocs");
-+      if (vtreloc_sec)
-+        vtreloc_sec->flags |= SEC_EXCLUDE;
-+      vtreloc_sec = bfd_get_section_by_name (dynobj, ".rel.suse.vtrelocs");
-+      if (vtreloc_sec)
-+        vtreloc_sec->flags |= SEC_EXCLUDE;
-+    }
-+  return TRUE;
-+}

Modified: trunk/patches/test/glibc-vt-reloc.diff
==============================================================================
--- trunk/patches/test/glibc-vt-reloc.diff	(original)
+++ trunk/patches/test/glibc-vt-reloc.diff	Mon Jan 14 16:06:09 2008
@@ -1,5 +1,5 @@
 diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/glibc-2.6.1/elf/dl-load.c glibc-2.6.1/elf/dl-load.c
---- /usr/src/packages/BUILD/glibc-2.6.1/elf/dl-load.c	2008-01-08 20:45:11.000000000 +0000
+--- glibc-2.6.1/elf/dl-load.c	2008-01-08 20:45:11.000000000 +0000el 
 +++ glibc-2.6.1/elf/dl-load.c	2008-01-11 15:23:16.000000000 +0000
 @@ -1200,9 +1200,13 @@
  
@@ -16,9 +16,9 @@
  	if (__builtin_expect ((void *) l->l_map_start == MAP_FAILED, 0))
  	  {
  	  map_error:
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/glibc-2.6.1/elf/dl-reloc.c glibc-2.6.1/elf/dl-reloc.c
---- /usr/src/packages/BUILD/glibc-2.6.1/elf/dl-reloc.c	2007-05-18 09:37:39.000000000 +0100
-+++ glibc-2.6.1/elf/dl-reloc.c	2008-01-11 16:06:10.000000000 +0000
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.6.1/elf/dl-reloc.c glibc-2.6.1/elf/dl-reloc.c
+--- glibc-2.6.1/elf/dl-reloc.c	2007-05-18 09:37:39.000000000 +0100
++++ glibc-2.6.1/elf/dl-reloc.c	2008-01-14 10:33:11.000000000 +0000
 @@ -27,6 +27,9 @@
  #include <sys/types.h>
  #include "dynamic-link.h"
@@ -29,7 +29,7 @@
  /* Statistics function.  */
  #ifdef SHARED
  # define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
-@@ -133,6 +136,67 @@
+@@ -133,6 +136,68 @@
  	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
  }
  
@@ -54,9 +54,10 @@
 +      return;
 +    }
 +  rel = (ElfW(VtReloc) *)(D_PTR (map, l_info[SUSEIDX(DT_SUSE_VTRELOC)]));
-+  _dl_debug_printf ("vtreloc section found in '%s' at 0x%x (0x%x) mapped at 0x%x\n",
-+                    map->l_name, rel, ((ElfW(Addr))rel - map->l_addr),
-+                    map->l_addr);
++  if (debug_output)
++    _dl_debug_printf ("vtreloc section found in '%s' at 0x%x (0x%x) mapped at 0x%x\n",
++                      map->l_name, rel, ((ElfW(Addr))rel - map->l_addr),
++                      map->l_addr);
 +  while (rel->r_src != 0)
 +    {
 +      ElfW(Addr) **src, **dest;
@@ -97,7 +98,7 @@
  
  void
  _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
-@@ -174,11 +238,15 @@
+@@ -174,11 +239,15 @@
    /* DT_TEXTREL is now in level 2 and might phase out at some time.
       But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
       testing easier and therefore it will be available at all time.  */
@@ -114,7 +115,7 @@
        for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
  	if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
  	  {
-@@ -293,9 +361,12 @@
+@@ -293,9 +362,12 @@
  #endif
    }
  
@@ -127,7 +128,7 @@
    /* Undo the segment protection changes.  */
    while (__builtin_expect (textrels != NULL, 0))
      {
-@@ -307,6 +378,7 @@
+@@ -307,6 +379,7 @@
  
        textrels = textrels->next;
      }
@@ -135,8 +136,8 @@
  
    /* In case we can protect the data now that the relocations are
       done, do it.  */
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/glibc-2.6.1/elf/dynamic-link.h glibc-2.6.1/elf/dynamic-link.h
---- /usr/src/packages/BUILD/glibc-2.6.1/elf/dynamic-link.h	2006-07-10 22:52:18.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.6.1/elf/dynamic-link.h glibc-2.6.1/elf/dynamic-link.h
+--- glibc-2.6.1/elf/dynamic-link.h	2006-07-10 22:52:18.000000000 +0100
 +++ glibc-2.6.1/elf/dynamic-link.h	2008-01-10 18:08:21.000000000 +0000
 @@ -65,6 +65,10 @@
  #ifndef VERSYMIDX
@@ -167,8 +168,8 @@
        ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
  		       + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
  # undef ADJUST_DYN_INFO
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/glibc-2.6.1/elf/elf.h glibc-2.6.1/elf/elf.h
---- /usr/src/packages/BUILD/glibc-2.6.1/elf/elf.h	2007-05-18 09:37:39.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.6.1/elf/elf.h glibc-2.6.1/elf/elf.h
+--- glibc-2.6.1/elf/elf.h	2007-05-18 09:37:39.000000000 +0100
 +++ glibc-2.6.1/elf/elf.h	2008-01-09 16:43:02.000000000 +0000
 @@ -518,6 +518,22 @@
    Elf64_Sxword	r_addend;		/* Addend */
@@ -208,8 +209,8 @@
  /* Sun added these machine-independent extensions in the "processor-specific"
     range.  Be compatible.  */
  #define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
-diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' /usr/src/packages/BUILD/glibc-2.6.1/include/link.h glibc-2.6.1/include/link.h
---- /usr/src/packages/BUILD/glibc-2.6.1/include/link.h	2007-08-03 14:57:06.000000000 +0100
+diff -u -r -x testsuite -x libjava -x cc-nptl -x build-dir -x '*.orig' -x obj-i586-suse-linux -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.6.1/include/link.h glibc-2.6.1/include/link.h
+--- glibc-2.6.1/include/link.h	2007-08-03 14:57:06.000000000 +0100
 +++ glibc-2.6.1/include/link.h	2008-01-09 16:43:02.000000000 +0000
 @@ -121,7 +121,7 @@
         are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>.  */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]