ooo-build r11242 - trunk/patches/test



Author: michael
Date: Thu Jan 10 17:50:19 2008
New Revision: 11242
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11242&view=rev

Log:
more work - finally doing something useful.


Modified:
   trunk/patches/test/binutils-vt-copy.diff
   trunk/patches/test/gcc-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	Thu Jan 10 17:50:19 2008
@@ -1,5 +1,5 @@
-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' /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
+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
 @@ -1787,6 +1787,12 @@
  extern void _bfd_elf_init_2_index_sections
@@ -14,8 +14,8 @@
  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' /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 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;
@@ -25,8 +25,8 @@
  	    }
  
  	  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' /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
+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;
@@ -189,7 +189,7 @@
  	      name = ".gnu.version_r";
  	      goto get_vma;
 +	    case DT_SUSE_VTRELOC:
-+	      name = ".suse.vtreloc";
++	      name = ".suse.vtrelocs";
 +	      goto get_vma;
  	    case DT_VERSYM:
  	      name = ".gnu.version";
@@ -203,8 +203,8 @@
    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' /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 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. */
@@ -217,8 +217,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 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' /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 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
@@ -234,8 +234,8 @@
  
  /* 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' /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 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,
@@ -245,8 +245,8 @@
    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' /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 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,
@@ -275,8 +275,8 @@
  	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' /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 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
@@ -309,3 +309,1440 @@
    ${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;
++}
+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
++++ 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;
+ 	    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 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
+@@ -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;
++
++  abfd = elf_hash_table (info)->dynobj;
++  bed = get_elf_backend_data (abfd);
++  flags = bed->dynamic_sec_flags;
++
++  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;
++
++  return TRUE;
++}
++
+ /* 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;
++
+     dynamic = FALSE;
++
++    vtrel_sec = bfd_get_section_by_name (abfd, ".vtrelocs");
++    if (vtrel_sec)
++      {
++        fprintf (stderr, "Has vtrelocs ! %d\n", (int)vtrel_sec->size);
++        if (!info->vtreloc)
++          {
++            info->vtreloc = 1;
++            if (!_bfd_elf_create_vtreloc_sections (info))
++              goto error_return;
++          }
++        vtrel_sec->flags |= SEC_EXCLUDE;
++      }
++  }
+   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
+@@ -5652,6 +5707,13 @@
+ 	    return FALSE;
+ 	}
+ 
++      s = bfd_get_section_by_name (output_bfd, ".suse.vtrelocs");
++      if (s != NULL)
++	{
++          if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_VTRELOC, 0))
++	    return FALSE;
++	}
++
+       dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
+       /* If .dynstr is excluded from the link, we don't want any of
+ 	 these tags.  Strictly, we should be checking each section
+@@ -7159,6 +7221,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 +7966,8 @@
+   bfd_vma r_type_mask;
+   int r_sym_shift;
+ 
++  fprintf (stderr, "elf_link_adjust_relocs ... %p\n", rel_hash);
++
+   if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
+     {
+       swap_in = bed->s->swap_reloc_in;
+@@ -10038,6 +10104,7 @@
+       finfo.dynsym_sec = NULL;
+       finfo.hash_sec = NULL;
+       finfo.symver_sec = NULL;
++      finfo.vtreloc_sec = NULL;
+     }
+   else
+     {
+@@ -10045,6 +10112,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 +10172,10 @@
+   max_sym_count = 0;
+   max_sym_shndx_count = 0;
+   merged = FALSE;
++
++  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 +10804,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 +10945,11 @@
+ 	    case DT_VERNEED:
+ 	      name = ".gnu.version_r";
+ 	      goto get_vma;
++	    case DT_SUSE_VTRELOC:
++	      name = ".suse.vtrelocs";
++	      o = bfd_get_section_by_name (abfd, name);
++              fprintf (stderr, "got section vma at 0x%x\n", o->vma);
++	      goto get_vma;
+ 	    case DT_VERSYM:
+ 	      name = ".gnu.version";
+ 	    get_vma:
+@@ -11129,6 +11210,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 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
++++ 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. */
+   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 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
++++ binutils-2.17.50/include/elf/common.h	2008-01-09 17:04:17.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 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
++++ binutils-2.17.50/ld/ldmain.c	2008-01-09 17:04:17.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 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
++++ binutils-2.17.50/ld/lexsup.c	2008-01-09 17:04:17.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 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
++++ binutils-2.17.50/ld/scripttempl/elf.sc	2008-01-09 17:04:17.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
++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/gcc-vt-copy.diff
==============================================================================
--- trunk/patches/test/gcc-vt-copy.diff	(original)
+++ trunk/patches/test/gcc-vt-copy.diff	Thu Jan 10 17:50:19 2008
@@ -696,114 +696,6 @@
    /* We give C linkage to static constructors and destructors.  */
    push_lang_context (lang_name_c);
  
-diff -u -r -x testsuite -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' gcc-4.2.1-20070724/gcc/crtstuff.c gcc-4.2.1-20070724/gcc/crtstuff.c
---- gcc-4.2.1-20070724/gcc/crtstuff.c	2006-12-11 12:18:13.000000000 +0000
-+++ gcc-4.2.1-20070724/gcc/crtstuff.c	2008-01-09 16:01:54.000000000 +0000
-@@ -1,3 +1,9 @@
-+#undef MEEKS
-+#ifdef MEEKS
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <sys/mman.h>
-+#endif
- /* 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,
-@@ -154,6 +160,17 @@
- 
- #endif /* OBJECT_FORMAT_ELF */
- 
-+
-+#ifdef MEEKS
-+typedef struct {
-+    void         *src_pos;
-+    void         *dest_pos;
-+    unsigned long bitmap;
-+} VtRelEntry;
-+
-+VtRelEntry *__vtrelocs __attribute__ ((weak)) __attribute__ ((__visibility__ ("hidden"))) = 0;
-+#endif
-+
- #ifdef CRT_BEGIN
- 
- /* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
-@@ -516,6 +533,64 @@
- static void __attribute__((used))
- __do_global_ctors_aux (void)
- {
-+#ifdef MEEKS
-+#warning "Foo"
-+  {
-+    fprintf (stderr, "Check weak %p, %p!\n",
-+             __vtrelocs, &__vtrelocs);
-+    if (__vtrelocs && getenv("DO_VTLINK"))
-+      {
-+        VtRelEntry *p;
-+        unsigned long pagesize;
-+        unsigned long last_addr = 0;
-+        int debug_output = 0;
-+        
-+        debug_output = getenv ("DO_VTLINK_DEBUG") != NULL;
-+
-+        pagesize = sysconf (_SC_PAGESIZE);
-+        for (p = &__vtrelocs; p && p->src_pos; p++)
-+          {
-+            fprintf (stderr, "Copy: %p -> %p, (0x%x)\n",
-+                     p->src_pos, p->dest_pos, p->bitmap);
-+            unsigned long mask;
-+            void **src = p->src_pos;
-+            void **dest = p->dest_pos;
-+
-+            { /* ug ! */
-+              long addr = (long)dest;
-+              addr -= addr % pagesize;
-+              if (last_addr != addr)
-+                mprotect (addr, pagesize + 256, PROT_READ|PROT_WRITE|PROT_EXEC);
-+              last_addr = addr;
-+            }
-+
-+            for (mask = p->bitmap; mask; mask >>= 1)
-+            {
-+#ifdef DEBUG_ONLY
-+                fprintf (stderr, "%s copy [&%p -> &%p]\n",
-+                         mask & 1 ? "do" : "no", src, dest);
-+#else
-+                if (mask & 1)
-+                  {
-+                    if (debug_output || !(*src == *dest || *dest == 0xdeadbeef))
-+                      {
-+                        fprintf (stderr, "do copy %10p to %10p %s [&%p -> &%p]\n",
-+                                 *src, *dest,
-+                                 *src == *dest || *dest == 0xdeadbeef ? "match" : "Bug !",
-+                                 src, dest);
-+                      }
-+                    *dest = *src;
-+                  }
-+                else if (debug_output)
-+                   fprintf (stderr, "no copy %10p to %10p %s\n",
-+                            *src, *dest, *src == *dest && (int)*src > 0x100 ? "Bug !" : "skip");
-+#endif
-+                dest++; src++;
-+            }
-+          }
-+      }
-+  }
-+#endif
-   func_ptr *p;
-   for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
-     (*p) ();
-diff -u -r -x testsuite -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' gcc-4.2.1-20070724/gcc/gcc.c gcc-4.2.1-20070724/gcc/gcc.c
---- gcc-4.2.1-20070724/gcc/gcc.c	2007-03-13 10:38:40.000000000 +0000
-+++ gcc-4.2.1-20070724/gcc/gcc.c	2008-01-09 15:26:55.000000000 +0000
-@@ -4594,6 +4594,8 @@
-   const char *string;
-   int value;
- 
-+//  fprintf (stderr, "do_spec_1 '%s'\n", spec);
-+
-   while ((c = *p++))
-     /* If substituting a switch, treat all chars like letters.
-        Otherwise, NL, SPC, TAB and % are special.  */
 diff -u -r -x testsuite -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' gcc-4.2.1-20070724/gcc/tree.h gcc-4.2.1-20070724/gcc/tree.h
 --- gcc-4.2.1-20070724/gcc/tree.h	2008-01-09 12:33:14.000000000 +0000
 +++ gcc-4.2.1-20070724/gcc/tree.h	2008-01-09 15:27:54.000000000 +0000
@@ -825,18 +717,3 @@
  /* In a VAR_DECL, nonzero if the decl is a register variable with
     an explicit asm specification.  */
  #define DECL_HARD_REGISTER(NODE)  (VAR_DECL_CHECK (NODE)->decl_with_vis.hard_register)
-diff -u -r -x testsuite -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' gcc-4.2.1-20070724/gcc/varasm.c gcc-4.2.1-20070724/gcc/varasm.c
---- gcc-4.2.1-20070724/gcc/varasm.c	2008-01-09 12:33:13.000000000 +0000
-+++ gcc-4.2.1-20070724/gcc/varasm.c	2008-01-09 15:26:55.000000000 +0000
-@@ -1795,6 +1795,11 @@
-   if (flag_syntax_only)
-     return;
- 
-+  if (DECL_VTRELOC_INIT (decl))
-+  {
-+      /* FIXME: in fact not needed: remove me ... */
-+  }
-+
-   app_disable ();
- 
-   if (! dont_output_data

Modified: trunk/patches/test/glibc-vt-reloc.diff
==============================================================================
--- trunk/patches/test/glibc-vt-reloc.diff	(original)
+++ trunk/patches/test/glibc-vt-reloc.diff	Thu Jan 10 17:50:19 2008
@@ -1,6 +1,6 @@
-diff -u -r -x cc-nptl -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
+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-09 12:30:34.000000000 +0000
++++ glibc-2.6.1/elf/dl-reloc.c	2008-01-10 17:49:56.000000000 +0000
 @@ -27,6 +27,9 @@
  #include <sys/types.h>
  #include "dynamic-link.h"
@@ -11,7 +11,7 @@
  /* Statistics function.  */
  #ifdef SHARED
  # define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
-@@ -133,6 +136,25 @@
+@@ -133,6 +136,85 @@
  	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
  }
  
@@ -19,25 +19,85 @@
 +static void
 +_dl_perform_vtrelocs (struct link_map *map, struct r_scope_elem *scope[])
 +{
-+  u_int32_t *ptr;
++  ElfW(VtReloc) *rel;
++  int debug_output = GLRO(dl_debug_mask) & DL_DEBUG_RELOC;
++  int i;
 +
-+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
-+    _dl_debug_printf ("new vtcopy-reloc processing\n");
++  if (debug_output)
++    _dl_debug_printf ("new vtcopy-reloc processing on '%s'\n", map->l_name);
 +
-+  ptr = map->l_info[SUSEIDX(DT_SUSE_VTRELOC)];
-+  if (ptr == NULL) {
-+      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
-+          _dl_debug_printf ("no vtreloc section in '%s'\n", map->l_name);
++  {
++      ElfW(Dyn) *item;
++      _dl_debug_printf ("fidx 0x%x\n", SUSEIDX(DT_SUSE_VTRELOC));
++      _dl_debug_printf ("in size 0x%x\n", sizeof (map->l_info) / sizeof(map->l_info[0]));
++      item = map->l_info[DT_STRTAB]; /* SUSEIDX(DT_SUSE_VTRELOC)]; */
++      _dl_debug_printf ("bits: 0x%x\n", item->d_tag);
++      _dl_debug_printf ("bits2: 0x%x\n", item->d_un.d_val);
++      _dl_debug_printf ("bits3: 0x%x\n", item->d_un.d_ptr);
++      item = map->l_info[SUSEIDX(DT_SUSE_VTRELOC)];
++      _dl_debug_printf ("vtreloc item: 0x%x\n", item);
++      if (!item)
++          return;
++  }
++
++#define TSTFOO_PTR(map, i) (map)->i->d_un.d_ptr
++  rel = (ElfW(VtReloc) *)(TSTFOO_PTR (map, l_info[SUSEIDX(DT_SUSE_VTRELOC)]));
++  _dl_debug_printf ("got d_ptr\n");
++  if (rel == NULL)
++    {
++      if (debug_output)
++        _dl_debug_printf ("no vtreloc section in '%s'\n", map->l_name);
 +      return;
++    }
++  {
++      ElfW(Addr) p = map->l_info[DT_PLTGOT];
++      _dl_debug_printf ("pltgot at 0x%x (0x%x)\n", p, p - map->l_addr);
++  }
++  {
++      ElfW(Addr) p = map->l_info[DT_HASH];
++      _dl_debug_printf ("hash at 0x%x (0x%x)\n", p, p - map->l_addr);
 +  }
-+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
-+      _dl_debug_printf ("vtreloc section found in '%s' at %p (%p)\n",
-+                        map->l_name, ptr, (ptr - map->l_addr));
++  _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);
++  for (i = 0; i < 64; i++)
++      _dl_debug_printf ("0x%x: 0x%x\n", (int)&((unsigned char *)rel)[i],
++                        ((unsigned char *)rel)[i]);
++  while (rel->r_src != 0)
++    {
++      ElfW(Addr) **src, **dest;
++      ElfW(Word) mask;
++
++      src = (void *)rel->r_src;
++      dest = (void *)rel->r_dest;
++      _dl_debug_printf ("copy from 0x%x to 0x%x mask 0x%x\n", src, dest, rel->r_mask);
++
++      for (mask = rel->r_mask; mask; mask >>= 1)
++        {
++          _dl_debug_printf ("%s copy [&0x%x -> &0x%x]\n",
++                            mask & 1 ? "do" : "no", src, dest);
++          if (mask & 1)
++            {
++              if (debug_output || !(*src == *dest || *dest == (ElfW(Addr) *)0xdeadbeef))
++                {
++                    _dl_debug_printf ("do copy 0x%x to 0x%x %s [&0x%x -> &0x%x]\n",
++                                      *src, *dest,
++                                      *src == *dest || *dest == (ElfW(Addr) *)0xdeadbeef ? "match" : "Bug",
++                                      src, dest);
++                }
++              *dest = *src;
++            }
++          else if (debug_output)
++            _dl_debug_printf ("no copy 0x%x to 0x%x %s\n",
++                              *src, *dest, *src == *dest && (int)*src > 0x100 ? "Bug" : "skip");
++          dest++; src++;
++        }
++    }
 +}
  
  void
  _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
-@@ -293,6 +315,8 @@
+@@ -293,6 +375,8 @@
  #endif
    }
  
@@ -46,9 +106,9 @@
    /* Mark the object so we know this work has been done.  */
    l->l_relocated = 1;
  
-diff -u -r -x cc-nptl -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
+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
-+++ glibc-2.6.1/elf/dynamic-link.h	2008-01-09 12:19:55.000000000 +0000
++++ glibc-2.6.1/elf/dynamic-link.h	2008-01-10 17:45:16.000000000 +0000
 @@ -65,6 +65,10 @@
  #ifndef VERSYMIDX
  # define VERSYMIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
@@ -60,17 +120,28 @@
  
  
  /* Read the dynamic section at DYN and fill in INFO with indices DT_*.  */
-@@ -104,6 +108,9 @@
-       else if ((Elf32_Word) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
- 	info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
- 	     + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
-+      else if (dyn->d_tag >= DT_SUSE_LO &&
-+	       dyn->d_tag < DT_SUSE_LO + DT_SUSENUM)
-+        info[SUSEIDX(dyn->d_tag)] = dyn;
-       ++dyn;
-     }
+@@ -86,8 +90,20 @@
+ 
+   info = l->l_info;
  
-@@ -143,6 +150,7 @@
++  _dl_debug_printf ("Name '%s'\n", l->l_name ? l->l_name : "<noname>");
++  info[SUSEIDX(DT_SUSE_VTRELOC)] = 0;
++
+   while (dyn->d_tag != DT_NULL)
+     {
++      if (dyn->d_tag >= DT_SUSE_LO &&
++	       dyn->d_tag < DT_SUSE_LO + DT_SUSENUM)
++      {
++          _dl_debug_printf ("assign at fidx 0x%x (0x%x)\n", SUSEIDX(dyn->d_tag), dyn);
++               info[SUSEIDX(dyn->d_tag)] = dyn;
++      } else
++          _dl_debug_printf ("tag 0x%x not >= 0x%x and < 0x%x\n",
++                            dyn->d_tag, DT_SUSE_LO, DT_SUSE_LO + DT_SUSENUM);
++
+       if (dyn->d_tag < DT_NUM)
+ 	info[dyn->d_tag] = dyn;
+       else if (dyn->d_tag >= DT_LOPROC &&
+@@ -143,6 +159,7 @@
  # endif
        ADJUST_DYN_INFO (DT_JMPREL);
        ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
@@ -78,16 +149,39 @@
        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 cc-nptl -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
+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
-+++ glibc-2.6.1/elf/elf.h	2008-01-09 12:28:45.000000000 +0000
-@@ -734,6 +734,14 @@
++++ glibc-2.6.1/elf/elf.h	2008-01-09 16:43:02.000000000 +0000
+@@ -518,6 +518,22 @@
+   Elf64_Sxword	r_addend;		/* Addend */
+ } Elf64_Rela;
+ 
++/* VTable relocation entry */
++
++typedef struct
++{
++  Elf32_Addr r_src;  /* source address */
++  Elf32_Addr r_dest; /* destination address */
++  Elf32_Word r_mask; /* copy bit-mask */
++} Elf32_VtReloc;
++
++typedef struct
++{
++  Elf64_Addr r_src;  /* source address */
++  Elf64_Addr r_dest; /* destination address */
++  Elf64_Word r_mask; /* copy bit-mask */
++} Elf64_VtReloc;
++
+ /* How to extract and insert information held in the r_info field.  */
+ 
+ #define ELF32_R_SYM(val)		((val) >> 8)
+@@ -734,6 +750,14 @@
  #define DT_VERSIONTAGIDX(tag)	(DT_VERNEEDNUM - (tag))	/* Reverse order! */
  #define DT_VERSIONTAGNUM 16
  
 +/* 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_LO (0x6cbdd030 + 2)
 +#define DT_SUSE_VTRELOC   DT_SUSE_LO
 +#define DT_SUSE_HI 0x6cbdd040
 +#define DT_SUSE_TAGIDX(tag) (tag - DT_SUSE_LO)
@@ -96,9 +190,9 @@
  /* 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 cc-nptl -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
+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
-+++ glibc-2.6.1/include/link.h	2008-01-09 12:30:17.000000000 +0000
++++ 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]