ooo-build r11382 - trunk/patches/test
- From: michael svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r11382 - trunk/patches/test
- Date: Wed, 23 Jan 2008 17:05:29 +0000 (GMT)
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]