ooo-build r11382 - trunk/patches/test



Author: michael
Date: Wed Jan 23 17:05:29 2008
New Revision: 11382
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11382&view=rev

Log:
Latest / greatest vtrelocs work ...


Added:
   trunk/patches/test/suse-vtrelocs-binutils.diff
   trunk/patches/test/suse-vtrelocs-gcc.diff
   trunk/patches/test/suse-vtrelocs-glibc.diff
Modified:
   trunk/patches/test/binutils-vt-copy-3.diff

Modified: trunk/patches/test/binutils-vt-copy-3.diff
==============================================================================
--- trunk/patches/test/binutils-vt-copy-3.diff	(original)
+++ trunk/patches/test/binutils-vt-copy-3.diff	Wed Jan 23 17:05:29 2008
@@ -1,739 +1,19 @@
-diff -u -r -x '*~' -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 *);
- 
-+/* 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 '*~' -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-16 17:29:43.000000000 +0000
-@@ -0,0 +1,600 @@
-+#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 !\n");
-+      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)
-+{
-+  if (getenv ("NOACCUM"))
-+    return;
-+
-+  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.  */
-+	  /* FIXME: we really don't want to keep these around, quick hack
-+	 *** due to having relocs pointing to these sections */
-+	  /*	  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);
-+          }
-+
-+	  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");
-+/*  FIXME - foo !
-+	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;
-+
-+  if (getenv ("NOACCUM"))
-+    return;
-+
-+  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 '*~' -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
++++ binutils-2.17.50/bfd/elf.c	2008-01-23 16:48:45.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;
++	    case DT_SUSE_VTRELOC: name = "SUSE_VTRELOC"; break;
  	    }
  
  	  fprintf (f, "  %-11s ", name);
+
 diff -u -r -x '*~' -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-15 15:50:27.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,25 @@
-   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;
-+          }
-+/*        FIXME: quick hack here ...
-+	  vtrel_sec->flags |= SEC_EXCLUDE; */
-+      }
-+  }
-   else
-     {
-       dynamic = TRUE;
-@@ -3603,6 +3650,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 +5026,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 +5426,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 +5708,13 @@
++++ binutils-2.17.50/bfd/elflink.c	2008-01-23 16:50:07.000000000 +0000
+@@ -5652,6 +5652,13 @@
  	    return FALSE;
  	}
  
@@ -747,100 +27,20 @@
        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 +7222,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 +7967,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 +10105,7 @@
-       finfo.dynsym_sec = NULL;
-       finfo.hash_sec = NULL;
-       finfo.symver_sec = NULL;
-+      finfo.vtreloc_sec = NULL;
-     }
-   else
-     {
-@@ -10045,6 +10113,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 +10173,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 +10805,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 +10946,11 @@
+@@ -10869,6 +10876,10 @@
  	    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 +11211,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 '*~' -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. */
-   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 '*~' -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
++++ binutils-2.17.50/include/elf/common.h	2008-01-23 16:40:38.000000000 +0000
 @@ -624,6 +624,13 @@
  #define DT_USED		0x7ffffffe
  #define DT_FILTER	0x7fffffff
@@ -855,50 +55,10 @@
  
  /* Values used in DT_FEATURE .dynamic entry.  */
  #define DTF_1_PARINIT	0x00000001
-diff -u -r -x '*~' -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,
- 	    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 '*~' -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,
-   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 '*~' -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-17 11:53:01.000000000 +0000
++++ binutils-2.17.50/ld/scripttempl/elf.sc	2008-01-23 16:48:46.000000000 +0000
 @@ -285,6 +285,7 @@
  eval $COMBRELOCCAT <<EOF
    .rel.init     ${RELOCATING-0} : { *(.rel.init) }
@@ -907,24 +67,14 @@
    .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,14 @@
+@@ -410,6 +411,13 @@
    ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}}
    .jcr          ${RELOCATING-0} : { KEEP (*(.jcr)) }
  
 +  /* Virtual table copy relocation tables */
-+  __vtrelocs = .;
-+  .suse.vtrelocs  :
++  .suse.vtrelocs :
 +  {
-+    KEEP (*(.vtrelocs.*))
++    KEEP (*(SORT(.vtrelocs.*)))
 +    QUAD(0)
 +  }
 +

Added: trunk/patches/test/suse-vtrelocs-binutils.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/suse-vtrelocs-binutils.diff	Wed Jan 23 17:05:29 2008
@@ -0,0 +1,83 @@
+diff -u -r -x '*~' -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-23 16:48:45.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 '*~' -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-23 16:50:07.000000000 +0000
+@@ -5652,6 +5652,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
+@@ -10869,6 +10876,10 @@
+ 	    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);
++	      goto get_vma;
+ 	    case DT_VERSYM:
+ 	      name = ".gnu.version";
+ 	    get_vma:
+diff -u -r -x '*~' -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-23 16:40:38.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 '*~' -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-23 16:48:46.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) }
+@@ -410,6 +411,13 @@
+   ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}}
+   .jcr          ${RELOCATING-0} : { KEEP (*(.jcr)) }
+ 
++  /* Virtual table copy relocation tables */
++  .suse.vtrelocs :
++  {
++    KEEP (*(SORT(.vtrelocs.*)))
++    QUAD(0)
++  }
++
+   ${RELOCATING+${DATARELRO}}
+   ${OTHER_RELRO_SECTIONS}
+   ${TEXT_DYNAMIC-${DYNAMIC}}

Added: trunk/patches/test/suse-vtrelocs-gcc.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/suse-vtrelocs-gcc.diff	Wed Jan 23 17:05:29 2008
@@ -0,0 +1,820 @@
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/collect2.c gcc-4.2.1-simple/gcc/collect2.c
+--- pristine-gcc-4.2.1-simple/gcc/collect2.c	2006-12-11 12:18:13.000000000 +0000
++++ gcc-4.2.1-simple/gcc/collect2.c	2008-01-21 19:50:44.000000000 +0000
+@@ -175,7 +175,7 @@
+ static int aixrtl_flag;			/* true if -brtl */
+ #endif
+ 
+-int debug;				/* true if -debug */
++int debug = 1;				/* true if -debug */
+ 
+ static int shared_obj;			/* true if -shared */
+ 
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/cp/class.c gcc-4.2.1-simple/gcc/cp/class.c
+--- pristine-gcc-4.2.1-simple/gcc/cp/class.c	2007-07-05 10:02:39.000000000 +0100
++++ gcc-4.2.1-simple/gcc/cp/class.c	2008-01-23 15:48:56.000000000 +0000
+@@ -181,8 +181,7 @@
+ static tree end_of_class (tree, int);
+ static bool layout_empty_base (tree, tree, splay_tree);
+ static void accumulate_vtbl_inits (tree, tree, tree, tree, tree);
+-static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
+-					       tree);
++static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree);
+ static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
+ static void build_vcall_and_vbase_vtbl_entries (tree, vtbl_init_data *);
+ static void clone_constructors_and_destructors (tree);
+@@ -6355,6 +6354,49 @@
+   return decl;
+ }
+ 
++/* Returns the VAR_DECL for the vtable copy relocation entries associated
++   with BINFO. */
++
++tree get_vtreloc_decl (tree t, tree inits)
++{
++  tree name, d;
++
++  name = mangle_vtreloc_for_type (t);
++  d = IDENTIFIER_GLOBAL_VALUE (name);
++
++  if (!d)
++    {
++      int nslots = list_length (inits);
++      tree atype = build_cplus_array_type (vtbl_slot_copy_type_node,
++					   build_index_type (size_int (nslots - 1)));
++      layout_type (atype);
++      TYPE_ALIGN (atype) = BITS_PER_UNIT * 4;
++
++      d = build_lang_decl (VAR_DECL, name, atype);
++      DECL_ALIGN(d) = 1;
++      DECL_USER_ALIGN(d) = 1;
++      DECL_SECTION_NAME(d) = mangle_vtreloc_section_for_type (t);
++      SET_DECL_ASSEMBLER_NAME (d, name);
++      /* Remember the type it is for.  */
++      TREE_TYPE (name) = t;
++      DECL_ARTIFICIAL (d) = 1;
++      DECL_IGNORED_P (d) = 1;
++      TREE_READONLY (d) = 1;
++      TREE_STATIC (d) = 1;
++      TREE_PUBLIC (d) = 0;
++      DECL_COMDAT (d) = 1;
++      /* Mark the variable as undefined -- but remember that we can
++	 define it later if we need to do so.  */
++      DECL_EXTERNAL (d) = 0;
++      DECL_NOT_REALLY_EXTERN (d) = 1;
++      set_linkage_according_to_type (t, d);
++      pushdecl_top_level_and_finish (d, NULL_TREE);
++
++      vtable_copy_slots = tree_cons (t, inits, vtable_copy_slots);
++    }
++
++  return d;
++}
+ 
+ /* Returns the binfo for the primary base of BINFO.  If the resulting
+    BINFO is a virtual base, and it is inherited elsewhere in the
+@@ -6438,7 +6480,7 @@
+   if (indented)
+     fprintf (stream, "\n");
+ 
+-  if (!(flags & TDF_SLIM))
++  if (1) /* !(flags & TDF_SLIM)) */
+     {
+       int indented = 0;
+ 
+@@ -6637,12 +6679,69 @@
+   dump_thunk (stderr, 0, fn);
+ }
+ 
++/* List of vtable copy slot data, keyed by type */
++/*
++ * toplevel: purpose - type
++ *           value   - [slot relocs]
++ * slot relocs: purpose - original binfo
++ *              value   - init structures: [src, dest, bitmap]
++ */
++tree vtable_copy_slots;
++
++
++static tree
++build_addr_offset (tree decl, int offset)
++{
++  tree index, addr;
++
++  index = build_int_cst (NULL_TREE, offset);
++  addr = build1 (ADDR_EXPR, ptr_type_node, build_array_ref (decl, index));
++
++  return addr;
++}
++
++/* Ideal .rodata output format: */
++/* dest_symbol, |dest_offset|src_bitmap_blocks, src_symbol, <bitmap> */
++/* Pragmatic 1st cut output format: */
++/* dest_addr, src_addr, <bitmap> */
++static tree
++build_vtable_copy_slot (tree dest_binfo, int dest_offset,
++                        tree src_binfo,  int src_offset,
++                        int bitmap, tree chain)
++{
++    tree src_decl, dest_decl;
++    tree elem = NULL_TREE, init;
++
++    /* Either a padding entry or nothing to do */
++    if (!dest_binfo || !bitmap)
++      return chain;
++
++    /*    fprintf (stderr, "Copy %s + %d => ",
++             type_as_string (src_binfo, TFF_PLAIN_IDENTIFIER),
++             src_offset);
++	     fprintf (stderr, " %s + %d mask 0x%x\n",
++             type_as_string (dest_binfo, TFF_PLAIN_IDENTIFIER),
++             dest_offset, bitmap); */
++
++    elem = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, bitmap), elem);
++
++    dest_decl = get_vtbl_decl_for_binfo (dest_binfo);
++    elem = tree_cons (NULL_TREE, build_addr_offset (dest_decl, dest_offset), elem);
++
++    src_decl = get_vtable_decl (BINFO_TYPE (src_binfo), 1);
++    elem = tree_cons (NULL_TREE, build_addr_offset (src_decl, src_offset), elem);
++
++    init = build_constructor_from_list (vtbl_slot_copy_type_node, elem);
++
++    return tree_cons (NULL_TREE, init, chain);
++}
++
+ /* Virtual function table initialization.  */
+ 
+ /* Create all the necessary vtables for T and its base classes.  */
+ 
+-static void
+-finish_vtbls (tree t)
++static tree
++vtbl_get_inits (tree t)
+ {
+   tree list;
+   tree vbase;
+@@ -6662,8 +6761,407 @@
+       accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
+     }
+ 
++  return TREE_VALUE (list);
++}
++
++/* List of un-altered vtable inits */
++/*
++ * list of: purpose - type
++ *          value   - [constructor_list]
++ */
++tree vtable_copy_types;
++
++/* FIXME: rather a lame search */
++static VEC(constructor_elt,gc) *
++get_vtinit_for_binfo (tree binfo, int list_only)
++{
++  tree k;
++  for (k = vtable_copy_types; k; k = TREE_CHAIN(k))
++    {
++      if (TREE_PURPOSE(k) == binfo)
++	return CONSTRUCTOR_ELTS (TREE_VALUE(k));
++    }
++  if (list_only)
++    return NULL;
++
++  k = get_vtbl_decl_for_binfo (binfo);
++  if (k) 
++    return CONSTRUCTOR_ELTS (DECL_INITIAL (k));
++  else
++    return NULL;
++}
++
++static void
++set_vtinit_for_binfo (tree binfo, VEC(constructor_elt,gc) *vtinits)
++{
++  vtable_copy_types = tree_cons (binfo, build_constructor (NULL_TREE, vtinits),
++				 vtable_copy_types);
++}
++
++static void
++debug_vtable (tree t, tree binfo)
++{
++  tree value;
++  unsigned HOST_WIDE_INT ix;
++  VEC(constructor_elt,gc) *vtable;
++
++  if (!getenv ("MOREDEBUG"))
++    return;
++
++  fprintf (stderr, "VTable for '%s'\n",
++	   type_as_string (t, TFF_PLAIN_IDENTIFIER));
++
++  vtable = get_vtinit_for_binfo (binfo, 0);
++  if (!vtable) 
++    {
++      fprintf (stderr, "<none>\n");
++      return;
++    }
++
++  FOR_EACH_CONSTRUCTOR_VALUE (vtable, ix, value) 
++    {
++      fprintf (stderr, "\t%-4ld  %s\n", (long)ix,
++	       expr_as_string (value, TFF_PLAIN_IDENTIFIER));
++    }
++}
++
++/* to track a segment of vtable initializer */
++typedef struct vt_fragment_d GTY(()) {
++  tree binfo;
++
++  /* ptr into the vec decl */
++  unsigned int offset;
++  unsigned int size;
++  VEC(constructor_elt,gc) *vec;
++} vt_fragment;
++
++typedef struct vt_copy_record_d GTY(()) {
++  vt_fragment *src;
++  vt_fragment *dest;
++  unsigned int bitmap;
++  unsigned int offset;
++} vt_copy_record;
++
++DEF_VEC_O(vt_fragment);
++DEF_VEC_O(vt_copy_record);
++DEF_VEC_ALLOC_O(vt_fragment, heap);
++DEF_VEC_ALLOC_O(vt_copy_record, heap);
++
++static void
++vtdecompose_frags (tree t_binfo, VEC(vt_fragment,heap) **frags)
++{
++  unsigned int seek_fn = 1, i;
++  vt_fragment *frag = NULL;
++  VEC(constructor_elt,gc) *vtable;
++
++  vtable = get_vtinit_for_binfo (t_binfo, 0);
++  if (!vtable)
++    return;
++
++  for (i = 0; i < VEC_length(constructor_elt,vtable); i++)
++    {
++      tree fn = VEC_index (constructor_elt, vtable, i)->value;
++      int is_fn = TREE_CODE (fn) == ADDR_EXPR
++	&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL;
++
++      if (is_fn && seek_fn)
++	{
++	  frag = VEC_safe_push (vt_fragment, heap, *frags, NULL);
++	  frag->binfo = t_binfo;
++	  frag->offset = i;
++	  frag->size = VEC_length (constructor_elt, vtable) - i;
++	  frag->vec = vtable;
++	  seek_fn = 0;
++	}
++      if (!is_fn && !seek_fn)
++	{
++	  frag->size = i - frag->offset;
++	  seek_fn = 1;
++	}
++    }
++}
++
++static void
++debug_fragments (VEC(vt_fragment,heap) *frags)
++{
++  unsigned int i;
++  for (i = 0; i < VEC_length(vt_fragment,frags); i++)
++    {
++      vt_fragment *frag = VEC_index (vt_fragment, frags, i);
++      fprintf (stderr, "fragment %d: '%s' offset %d, size %d\n",
++	       i, type_as_string (BINFO_TYPE (frag->binfo), TFF_PLAIN_IDENTIFIER),
++	       frag->offset, frag->size);
++    }
++}
++
++static void
++push_vtfrag (VEC(vt_copy_record,heap) **vt_copies,
++	     vt_fragment *src, vt_fragment *dest,
++	     unsigned int bitmap, unsigned int offset)
++{
++  vt_copy_record *rec;
++
++  /* FIXME: we need to be able to compare these */
++  /* that is not easy, sadly - so punt for now (?), and hope we don't get too
++   * many duplicate / overlapping hits */
++  rec = VEC_safe_push (vt_copy_record, heap, *vt_copies, NULL);
++  rec->src = src;
++  rec->dest = dest;
++  rec->bitmap = bitmap;
++  rec->offset = offset;
++  if (getenv ("MOREDEBUG"))
++    fprintf (stderr, "Push frag 0x%x %d\n", bitmap, offset);
++}
++
++static void
++debug_vt_copies (VEC(vt_copy_record,heap) *vt_copies)
++{
++  unsigned int i;
++
++  if (!getenv ("MOREDEBUG"))
++    return;
++
++  fprintf (stderr, "vtcopies: %d records\n", VEC_length(vt_copy_record, vt_copies));
++  for (i = 0; i < VEC_length(vt_copy_record, vt_copies); i++)
++    {
++      vt_copy_record *cpy = VEC_index (vt_copy_record, vt_copies, i);
++      fprintf (stderr, "\tcopy from %s+%d to %s+%d mask 0x%x\n",
++	       type_as_string (BINFO_TYPE (cpy->src->binfo), TFF_PLAIN_IDENTIFIER),
++	       cpy->src->offset + cpy->offset,
++	       type_as_string (BINFO_TYPE (cpy->dest->binfo), TFF_PLAIN_IDENTIFIER),
++	       cpy->dest->offset + cpy->offset,
++	       cpy->bitmap);
++    }
++}
++
++/*
++ * Compare all src & dest fragments for the best match ...
++ */
++static tree
++compare_build_vtrelocs (tree t, VEC(constructor_elt,gc) *vinits,
++			VEC(vt_fragment,heap) *dest_frags,
++			VEC(vt_fragment,heap) *src_frags)
++{
++  unsigned int i;
++  tree cgraph_clobber = NULL_TREE;
++  VEC(vt_copy_record,heap) *vt_copies;
++  int verbose_debug = getenv ("MOREDEBUG") != NULL;
++
++  vt_copies = VEC_alloc(vt_copy_record, heap, VEC_length(vt_fragment, dest_frags));
++
++  for (i = 0; i < VEC_length(vt_fragment, dest_frags); i++)
++    {
++      unsigned int j;
++      vt_fragment *dest = VEC_index (vt_fragment, dest_frags, i);
++      
++      for (j = 0; j < VEC_length(vt_fragment, src_frags); j++)
++	{
++	  unsigned int cmp;
++	  unsigned int k, bits_set;
++	  unsigned int bitmap;
++	  int elide_leading_zeros = 1;
++	  vt_fragment *src = VEC_index (vt_fragment, src_frags, j);
++
++	  /* new virtual methods arrive only in the 1st dest fragment */
++	  if (i > 0 && dest->size != src->size)
++	    continue;
++
++	  cmp = src->size;
++	  if (cmp > dest->size)
++	    cmp = dest->size;
++
++	  /* FIXME: bin elide_leading_zeros until we have better
++	   * comparison logic ? */
++	  for (bitmap = bits_set = k = 0; k < cmp; k++)
++	    {
++	      tree src_fn = VEC_index (constructor_elt, src->vec, src->offset + k)->value;
++	      tree dest_fn = VEC_index (constructor_elt, dest->vec, dest->offset + k)->value;
++	      src_fn = TREE_OPERAND (src_fn, 0);
++	      dest_fn = TREE_OPERAND (dest_fn, 0);
++
++	      if (src_fn == dest_fn && src_fn != abort_fndecl)
++		{
++		  bitmap |= (1 << bits_set);
++		  elide_leading_zeros = 0;
++		}
++
++	      if (verbose_debug)
++		fprintf (stderr, "compare: %s %s %s (0x%x) [%s]\n",
++			 expr_as_string (src_fn, TFF_PLAIN_IDENTIFIER),
++			 src_fn == dest_fn ? "==" : "!=",
++			 expr_as_string (dest_fn, TFF_PLAIN_IDENTIFIER),
++			 bitmap,
++			 src_fn == abort_fndecl ? "pure-virt" : "non-pure virt");
++	      
++	      if (!elide_leading_zeros)
++		bits_set++;
++
++	      if (bits_set == (sizeof (long) * 8)) /* FIXME: arch size etc. urgh ... */
++		{
++		  push_vtfrag (&vt_copies, src, dest, bitmap, k - bits_set + 1);
++		  bits_set = bitmap = 0;
++		  elide_leading_zeros = 1;
++		}
++	    }
++	  if (bitmap != 0)
++	    push_vtfrag (&vt_copies, src, dest, bitmap, k - bits_set);
++	}
++    }
++
++  if (VEC_length(vt_copy_record, vt_copies) > 0)
++    {
++      VEC(constructor_elt,gc) *vtable;
++      unsigned int i;
++      tree vtreloc_inits = NULL_TREE;
++
++      debug_vt_copies (vt_copies);
++
++      /*
++       * Re-write the intializers to remove references in the vtable...
++       */
++      vtable = VEC_copy(constructor_elt,gc,vinits);
++
++      /* FIXME: copy & backup the original data before we mangle it
++	 for future reference [!] */
++      
++      if (verbose_debug)
++	fprintf (stderr, "re-writing vtable:\n");
++      for (i = 0; i < VEC_length(vt_copy_record, vt_copies); i++)
++	{
++	  unsigned int j, bitmap;
++	  vt_copy_record *vtc = VEC_index(vt_copy_record, vt_copies, i);
++
++	  /* re-write the existing vtable intializer */
++	  bitmap = vtc->bitmap;
++	  if (verbose_debug)
++	    fprintf (stderr, "\tclobber from off %d + %d, bitmap 0x%x\n",
++		     vtc->dest->offset, vtc->offset, bitmap);
++	  for (j = vtc->dest->offset + vtc->offset; bitmap; j++, (bitmap>>=1))
++	    {
++	      if (bitmap & 1)
++		{
++		  constructor_elt *elt = VEC_index (constructor_elt, vtable, j);
++		  if (verbose_debug)
++		    fprintf (stderr, "\tclobber '%s' (0x%x)\n",
++			     expr_as_string (elt->value, TFF_PLAIN_IDENTIFIER),
++			     bitmap);
++
++		  { /* Lengthy Assertion */
++		    constructor_elt *src_elt = VEC_index (constructor_elt, vtc->src->vec,
++							  vtc->src->offset + j - vtc->dest->offset);
++		    gcc_assert (TREE_CODE (elt->value) == INTEGER_CST /* FIXME: strange, but sometimes we overlap */
++				|| TREE_OPERAND (elt->value, 0) == TREE_OPERAND (src_elt->value, 0));
++		  }
++		  elt->value = fold_build1 (NOP_EXPR,
++					    vtable_entry_type,
++					    build_int_cst (build_pointer_type (void_type_node),
++							   0xdeadbeef));
++		}
++	    }
++
++	  /* build vtreloc decls */
++	  vtreloc_inits = build_vtable_copy_slot (vtc->dest->binfo, vtc->dest->offset + vtc->offset,
++						  vtc->src->binfo, vtc->src->offset + vtc->offset,
++						  vtc->bitmap, vtreloc_inits);
++	}
++
++      /* re-build as chain for constructor ... hmm */
++      for (i = 0; i < VEC_length(constructor_elt, vtable); i++)
++	{
++	  constructor_elt *elt = VEC_index (constructor_elt, vtable, i);
++	  cgraph_clobber = tree_cons (elt->index, elt->value, cgraph_clobber);
++	}
++
++      /* Append a reference to the parent vtable
++       * to encourage gcc to emit the VTReloc table */
++      cgraph_clobber = tree_cons (NULL_TREE,
++				  build_nop (vfunc_ptr_type_node,
++					     build_address (get_vtreloc_decl (t, vtreloc_inits))),
++				  cgraph_clobber);
++      cgraph_clobber = nreverse (cgraph_clobber);
++    }
++
++  vec_heap_free (vt_copies);
++  return cgraph_clobber;
++}
++
++static VEC(constructor_elt,gc) *
++build_init_vec (tree inits)
++{
++  tree t;
++  VEC(constructor_elt,gc) *v = NULL;
++
++  if (inits)
++    {
++      v = VEC_alloc (constructor_elt, gc, list_length (inits));
++      for (t = inits; t; t = TREE_CHAIN (t))
++	{
++	  constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
++	  elt->index = TREE_PURPOSE (t);
++	  elt->value = TREE_VALUE (t);
++	}
++    }
++
++  return v;
++}
++
++static void
++finish_vtbls (tree t)
++{
++  tree inits;
++  
++  inits = vtbl_get_inits (t);
++
++  if (inits && getenv ("VT_SHRINK"))
++  {
++    int i;
++    tree base_binfo;
++    VEC(vt_fragment,heap) *dest_frags;
++    VEC(vt_fragment,heap) *src_frags;
++    VEC(constructor_elt,gc) *vinits = NULL;
++
++    vinits = build_init_vec (inits);
++    if (!get_vtinit_for_binfo (TYPE_BINFO (t), 1))
++      set_vtinit_for_binfo (TYPE_BINFO (t), vinits);
++    else
++      fprintf (stderr, "Error: already set!\n");
++
++    debug_vtable (t, TYPE_BINFO (t));
++
++    if (getenv ("MOREDEBUG"))
++      fprintf (stderr, "Inherited from:\n");
++    for (i = 0; BINFO_BASE_ITERATE (TYPE_BINFO (t), i, base_binfo); i++)
++      {
++	tree btype = BINFO_TYPE (base_binfo);
++	debug_vtable (btype, TYPE_BINFO (btype));
++      }
++
++    src_frags = VEC_alloc(vt_fragment,heap,4);
++    dest_frags = VEC_alloc(vt_fragment,heap,4);
++    vtdecompose_frags (TYPE_BINFO (t), &dest_frags);
++    for (i = 0; BINFO_BASE_ITERATE (TYPE_BINFO (t), i, base_binfo); i++)
++      vtdecompose_frags (TYPE_BINFO (BINFO_TYPE (base_binfo)), &src_frags);
++
++    if (getenv ("MOREDEBUG"))
++      {
++	fprintf (stderr, "dest:\n");
++	debug_fragments (dest_frags);
++	fprintf (stderr, "src:\n");
++	debug_fragments (src_frags);
++      }
++
++    if (inits) {
++      tree new_inits = compare_build_vtrelocs (t, vinits, dest_frags, src_frags);
++      if (new_inits)
++	inits = new_inits;
++    }
++
++    vec_heap_free (dest_frags);
++    vec_heap_free (src_frags);
++  }
++
+   if (BINFO_VTABLE (TYPE_BINFO (t)))
+-    initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
++    initialize_vtable (TYPE_BINFO (t), inits);
+ }
+ 
+ /* Initialize the vtable for BINFO with the INITS.  */
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/cp/cp-tree.h gcc-4.2.1-simple/gcc/cp/cp-tree.h
+--- pristine-gcc-4.2.1-simple/gcc/cp/cp-tree.h	2007-07-24 09:14:47.000000000 +0100
++++ gcc-4.2.1-simple/gcc/cp/cp-tree.h	2008-01-22 14:27:55.000000000 +0000
+@@ -498,6 +498,7 @@
+     CPTI_UNKNOWN_TYPE,
+     CPTI_VTBL_TYPE,
+     CPTI_VTBL_PTR_TYPE,
++    CPTI_VTBL_SLOT_COPY_TYPE,
+     CPTI_STD,
+     CPTI_ABI,
+     CPTI_CONST_TYPE_INFO_TYPE,
+@@ -562,6 +563,7 @@
+ #define unknown_type_node		cp_global_trees[CPTI_UNKNOWN_TYPE]
+ #define vtbl_type_node			cp_global_trees[CPTI_VTBL_TYPE]
+ #define vtbl_ptr_type_node		cp_global_trees[CPTI_VTBL_PTR_TYPE]
++#define vtbl_slot_copy_type_node        cp_global_trees[CPTI_VTBL_SLOT_COPY_TYPE]
+ #define std_node			cp_global_trees[CPTI_STD]
+ #define abi_node			cp_global_trees[CPTI_ABI]
+ #define const_type_info_type_node	cp_global_trees[CPTI_CONST_TYPE_INFO_TYPE]
+@@ -3392,6 +3394,14 @@
+    TREE_PURPOSE slot.  */
+ extern GTY(()) tree static_aggregates;
+ 
++/* A list of inherited vtable slots which are copies of other slots
++   The source address is stored in the TREE_VALUE slot and the
++   destination is stored in the TREE_PURPOSE slot. */
++extern GTY(()) tree vtable_copy_slots;
++
++/* A type mapping of types to un-altered type tables */
++extern GTY(()) tree vtable_copy_types;
++
+ /* Functions called along with real static constructors and destructors.  */
+ 
+ extern GTY(()) tree static_ctors;
+@@ -3847,6 +3857,7 @@
+ extern void maybe_note_name_used_in_class	(tree, tree);
+ extern void note_name_declared_in_class		(tree, tree);
+ extern tree get_vtbl_decl_for_binfo		(tree);
++extern tree get_vtreloc_decl			(tree, tree);
+ extern void debug_class				(tree);
+ extern void debug_thunks			(tree);
+ extern tree cp_fold_obj_type_ref		(tree, tree);
+@@ -4533,6 +4544,9 @@
+ extern tree mangle_typeinfo_for_type		(tree);
+ extern tree mangle_typeinfo_string_for_type	(tree);
+ extern tree mangle_vtbl_for_type		(tree);
++extern tree mangle_vtbl_for_type_local          (tree);
++extern tree mangle_vtreloc_for_type		(tree);
++extern tree mangle_vtreloc_section_for_type     (tree);
+ extern tree mangle_vtt_for_type			(tree);
+ extern tree mangle_ctor_vtbl_for_type		(tree, tree);
+ extern tree mangle_thunk			(tree, int, tree, tree);
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/cp/decl.c gcc-4.2.1-simple/gcc/cp/decl.c
+--- pristine-gcc-4.2.1-simple/gcc/cp/decl.c	2007-07-24 09:14:45.000000000 +0100
++++ gcc-4.2.1-simple/gcc/cp/decl.c	2008-01-21 19:50:44.000000000 +0000
+@@ -124,6 +124,10 @@
+ 	tree vtbl_type_node;
+ 	tree vtbl_ptr_type_node;
+ 
++   Array slot copy type info:
++
++	tree vtbl_slot_copy_type_node;
++
+    Namespaces,
+ 
+ 	tree std_node;
+@@ -3117,6 +3121,13 @@
+     }
+ }
+ 
++static tree
++append_struct_field (const char *name, tree type, tree chain)
++{
++  return chainon (chain, build_decl (FIELD_DECL,
++                                     get_identifier (name), type));
++}
++
+ /* Create the predefined scalar types of C,
+    and some nodes representing standard constants (0, 1, (void *)0).
+    Initialize the global binding level.
+@@ -3243,6 +3254,19 @@
+   layout_type (vtbl_ptr_type_node);
+   record_builtin_type (RID_MAX, NULL, vtbl_ptr_type_node);
+ 
++  {
++    tree elem_fields = NULL;
++
++    vtbl_slot_copy_type_node = make_aggr_type (RECORD_TYPE);
++    elem_fields = append_struct_field ("vt_src_addr", ptr_type_node, elem_fields);
++    elem_fields = append_struct_field ("vt_dest_addr", ptr_type_node, elem_fields);
++    elem_fields = append_struct_field ("vt_copy_bitmap", size_type_node, elem_fields);
++    finish_builtin_struct (vtbl_slot_copy_type_node, "__vt_copy_slot_relocs",
++                           elem_fields, NULL_TREE);
++    layout_type (vtbl_slot_copy_type_node);
++    record_builtin_type (RID_MAX, NULL, vtbl_slot_copy_type_node);
++  }
++
+   push_namespace (get_identifier ("__cxxabiv1"));
+   abi_node = current_namespace;
+   pop_namespace ();
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/cp/decl2.c gcc-4.2.1-simple/gcc/cp/decl2.c
+--- pristine-gcc-4.2.1-simple/gcc/cp/decl2.c	2007-06-28 14:16:12.000000000 +0100
++++ gcc-4.2.1-simple/gcc/cp/decl2.c	2008-01-23 15:48:29.000000000 +0000
+@@ -2910,6 +2910,38 @@
+     finish_objects (function_key, priority, body);
+ }
+ 
++static void
++generate_vtable_copy_slots (void)
++{
++  tree k;
++
++  if (!getenv ("VT_SHRINK"))
++      return;
++
++  for (k = vtable_copy_slots; k; k = TREE_CHAIN(k))
++    {
++      tree t = TREE_PURPOSE(k);
++      tree inits = TREE_VALUE(k);
++      tree decl, ctor;
++
++      decl = get_vtreloc_decl (t, inits);
++      import_export_decl (decl);
++      if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
++	{
++	  DECL_EXTERNAL (decl) = 0;
++	  comdat_linkage (decl);
++	  DECL_COMDAT (decl) = 1;
++	  ctor = build_constructor_from_list (TREE_TYPE (decl), inits);
++	  initialize_artificial_var (decl, ctor);
++	  if (getenv ("MOREDEBUG"))
++	    fprintf (stderr, "Generate vtreloc variable '%s' comdat? %d\n",
++		     decl_as_string (decl, TFF_PLAIN_IDENTIFIER),
++		     DECL_COMDAT (decl));
++	}
++    }
++}
++
++
+ /* Generate constructor and destructor functions for the priority
+    indicated by N.  */
+ 
+@@ -3312,6 +3344,9 @@
+ 	}
+     }
+ 
++  /* Generate C++ vtable copy data */
++  generate_vtable_copy_slots ();
++
+   /* We give C linkage to static constructors and destructors.  */
+   push_lang_context (lang_name_c);
+ 
+diff -u -r -x '*~' -x '*.rej' -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-gcc-4.2.1-simple/gcc/cp/mangle.c gcc-4.2.1-simple/gcc/cp/mangle.c
+--- pristine-gcc-4.2.1-simple/gcc/cp/mangle.c	2006-12-11 12:16:19.000000000 +0000
++++ gcc-4.2.1-simple/gcc/cp/mangle.c	2008-01-23 15:10:38.000000000 +0000
+@@ -2670,6 +2670,99 @@
+   return mangle_special_for_type (type, "TV");
+ }
+ 
++tree
++mangle_vtbl_for_type_local (const tree type)
++{
++  const char *result;
++
++  /* We don't have an actual decl here for the special component, so
++     we can't just process the <encoded-name>.  Instead, fake it.  */
++  start_mangling (type, /*ident_p=*/true);
++
++  /* Start the mangling.  */
++  write_string ("_Z");
++  write_string ("VT");
++
++  /* Add the type.  */
++  write_type (type);
++  write_string ("_local");
++  result = finish_mangling (/*warn=*/false);
++
++  return get_identifier_nocopy (result);
++}
++
++/* FIXME: as should be obvious I have no idea what I'm doing here */
++static int calc_max_depth (const tree binfo)
++{
++  int i, max = 0;
++  tree base;
++
++  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base); ++i) {
++    int depth = calc_max_depth (base);
++    if (depth > max)
++      max = depth;
++  }
++  return max + 1;
++}
++
++static void write_order_complexity_for_type (const tree type)
++{
++  int max_depth = 0;
++  int virts;
++  tree binfo;
++  char buffer[128]; /* hack */
++
++  binfo = TYPE_BINFO (type);
++
++  max_depth = calc_max_depth (binfo);
++
++  /* FIXME: virtual bases ? 
++  {
++    tree vbase;
++    for (vbase = binfo; vbase; vbase = TREE_CHAIN (vbase))
++      virts++; 
++  }
++  */
++  virts = 0;
++
++  sprintf (buffer, "_%.8i_", max_depth + virts);
++  write_string (buffer);
++}
++
++/*
++ * In order to get initialization order right, use a metric of
++ * the maximum 'inheritedness' of a class, ie. a vtable that
++ * inherits from 5 others, should be initialized after those
++ * that inherit from 4 
++ */
++static const char *mangle_vtreloc (const tree type, const char *prefix)
++{
++  const char *name;
++
++  start_mangling (type, /*ident_p=*/true);
++  write_string (prefix);
++  write_order_complexity_for_type (type);
++  write_type (type);
++  name = finish_mangling (/*warn=*/false);
++
++  return name;
++}
++
++/* Create an identifier for the mangled name of the vt relocs for TYPE.  */
++
++tree mangle_vtreloc_for_type (const tree type)
++{
++  return get_identifier_nocopy (mangle_vtreloc (type, "_ZVTR"));
++}
++
++/* Create an identifier for the section name of the vt relocs for TYPE.  */
++
++tree mangle_vtreloc_section_for_type (const tree type)
++{
++  const char *name = mangle_vtreloc (type, ".vtrelocs._ZVTR");
++  return build_string (strlen (name), name);
++}
++
+ /* Returns an identifier for the mangled name of the VTT for TYPE.  */
+ 
+ tree

Added: trunk/patches/test/suse-vtrelocs-glibc.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/suse-vtrelocs-glibc.diff	Wed Jan 23 17:05:29 2008
@@ -0,0 +1,239 @@
+diff -u -r -x '*~' -x '*.rej' -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-glibc-2.6.1/elf/dl-init.c glibc-2.6.1/elf/dl-init.c
+--- pristine-glibc-2.6.1/elf/dl-init.c	2005-01-06 22:40:26.000000000 +0000
++++ glibc-2.6.1/elf/dl-init.c	2008-01-22 16:09:03.000000000 +0000
+@@ -30,6 +30,79 @@
+ extern int _dl_starting_up_internal attribute_hidden;
+ #endif
+ 
++#define SUSEIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + \
++			 DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM + DT_SUSE_TAGIDX (sym))
++
++/* process vtable / block copy relocations */
++
++static void
++_dl_perform_vtrelocs (struct link_map *map)
++{
++  ElfW(VtReloc) *rel;
++  int debug_output = GLRO(dl_debug_mask) & DL_DEBUG_RELOC;
++  int i;
++
++  if (debug_output)
++    _dl_debug_printf ("new vtcopy-reloc processing on '%s' offset 0x%x map 0x%x\n",
++                      map->l_name[0] ? map->l_name : rtld_progname,
++                      map->l_addr, map->l_map_start);
++
++  /* any vtrelocs ? */
++  if (map->l_info[SUSEIDX(DT_SUSE_VTRELOC)] == NULL)
++    {
++      if (debug_output)
++        _dl_debug_printf ("no vtreloc section in '%s'\n", map->l_name);
++      return;
++    }
++  rel = (ElfW(VtReloc) *)(D_PTR (map, l_info[SUSEIDX(DT_SUSE_VTRELOC)]));
++  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;
++      ElfW(Word) mask;
++
++      src = (void *)rel->r_src;
++      dest = (void *)rel->r_dest;
++      if (debug_output)
++        _dl_debug_printf ("copy from 0x%x to 0x%x mask 0x%x\n", src, dest, rel->r_mask);
++#ifdef DONT_TOUCH_EXTERNAL
++      if (dest < map->l_map_start || dest >= map->l_map_end)
++	{ /* weak symbol defined in another dso - thus already fixed up, and readonly */
++	  if (debug_output)
++	    _dl_debug_printf ("  skip, defined elsewhere\n");
++	}
++      else
++#endif
++	{
++	  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++;
++	    }
++	}
++      if (debug_output)
++	_dl_debug_printf ("move to next vtrel entry\n");
++      rel++;
++    }
++}
+ 
+ static void
+ call_init (struct link_map *l, int argc, char **argv, char **env)
+@@ -42,6 +115,8 @@
+      dependency.  */
+   l->l_init_called = 1;
+ 
++  _dl_perform_vtrelocs (l);
++
+   /* Check for object which constructors we do not run here.  */
+   if (__builtin_expect (l->l_name[0], 'a') == '\0'
+       && l->l_type == lt_executable)
+diff -u -r -x '*~' -x '*.rej' -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-glibc-2.6.1/elf/dl-load.c glibc-2.6.1/elf/dl-load.c
+--- pristine-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-11 15:23:16.000000000 +0000
+@@ -1200,9 +1200,13 @@
+ 
+ 	/* Remember which part of the address space this object uses.  */
+ 	l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
+-					      c->prot,
++					      c->prot | PROT_WRITE,
+ 					      MAP_COPY|MAP_FILE,
+ 					      fd, c->mapoff);
++        if (GLRO(dl_debug_mask) & DL_DEBUG_RELOC)
++            _dl_debug_printf ("map '%s' at 0x%x prot 0x%x\n", l->l_name,
++                              l->l_map_start, c->prot);
++
+ 	if (__builtin_expect ((void *) l->l_map_start == MAP_FAILED, 0))
+ 	  {
+ 	  map_error:
+diff -u -r -x '*~' -x '*.rej' -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-glibc-2.6.1/elf/dl-reloc.c glibc-2.6.1/elf/dl-reloc.c
+--- pristine-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-22 15:54:46.000000000 +0000
+@@ -133,7 +133,6 @@
+ 	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+ }
+ 
+-
+ void
+ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
+ 		     int lazy, int consider_profiling)
+@@ -174,11 +173,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.  */
+-  if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
++  if (1) //__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
+     {
+       /* Bletch.  We must make read-only segments writable
+ 	 long enough to relocate them.  */
+       const ElfW(Phdr) *ph;
++
++      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
++          _dl_debug_printf ("un-protecting foo\n");
++
+       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)
+ 	  {
+@@ -296,6 +299,7 @@
+   /* Mark the object so we know this work has been done.  */
+   l->l_relocated = 1;
+ 
++#if 0
+   /* Undo the segment protection changes.  */
+   while (__builtin_expect (textrels != NULL, 0))
+     {
+@@ -312,6 +316,7 @@
+      done, do it.  */
+   if (l->l_relro_size != 0)
+     _dl_protect_relro (l);
++#endif
+ }
+ 
+ 
+diff -u -r -x '*~' -x '*.rej' -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-glibc-2.6.1/elf/dynamic-link.h glibc-2.6.1/elf/dynamic-link.h
+--- pristine-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
+ # define VERSYMIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+ #endif
++#ifndef SUSEIDX
++# define SUSEIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + \
++        DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM + DT_SUSE_TAGIDX (sym))
++#endif
+ 
+ 
+ /* Read the dynamic section at DYN and fill in INFO with indices DT_*.  */
+@@ -88,6 +92,9 @@
+ 
+   while (dyn->d_tag != DT_NULL)
+     {
++      if (dyn->d_tag >= DT_SUSE_LO &&
++        dyn->d_tag < DT_SUSE_LO + DT_SUSENUM)
++          info[SUSEIDX(dyn->d_tag)] = dyn;
+       if (dyn->d_tag < DT_NUM)
+ 	info[dyn->d_tag] = dyn;
+       else if (dyn->d_tag >= DT_LOPROC &&
+@@ -143,6 +150,7 @@
+ # endif
+       ADJUST_DYN_INFO (DT_JMPREL);
+       ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
++      ADJUST_DYN_INFO (SUSEIDX(DT_SUSE_VTRELOC));
+       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 '*~' -x '*.rej' -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-glibc-2.6.1/elf/elf.h glibc-2.6.1/elf/elf.h
+--- pristine-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 */
+ } 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_VTRELOC   DT_SUSE_LO
++#define DT_SUSE_HI 0x6cbdd040
++#define DT_SUSE_TAGIDX(tag) (tag - DT_SUSE_LO)
++#define DT_SUSENUM 1
++
+ /* 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 '*~' -x '*.rej' -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-glibc-2.6.1/include/link.h glibc-2.6.1/include/link.h
+--- pristine-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>.  */
+ 
+     ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
+-		      + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
++		      + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM + DT_SUSENUM];
+     const ElfW(Phdr) *l_phdr;	/* Pointer to program header table in core.  */
+     ElfW(Addr) l_entry;		/* Entry point location.  */
+     ElfW(Half) l_phnum;		/* Number of program header entries.  */



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