aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf-m10300.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1998-06-30 10:02:22 +0000
committerRichard Henderson <rth@redhat.com>1998-06-30 10:02:22 +0000
commit303b4cc64fa823bde77776b05503b39dc513e644 (patch)
treebba8b7aa0ced2c0a7a22ddee4cc5b89832d72ebb /bfd/elf-m10300.c
parentd40d5880c209617e3e4c951ed70b083c76b4cc37 (diff)
downloadgdb-303b4cc64fa823bde77776b05503b39dc513e644.zip
gdb-303b4cc64fa823bde77776b05503b39dc513e644.tar.gz
gdb-303b4cc64fa823bde77776b05503b39dc513e644.tar.bz2
ELF Section-level Garbage Collection.
Diffstat (limited to 'bfd/elf-m10300.c')
-rw-r--r--bfd/elf-m10300.c165
1 files changed, 161 insertions, 4 deletions
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index a2f60ba..1cb8e74 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -92,6 +92,12 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
static void mn10300_info_to_howto
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+static boolean mn10300_elf_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static asection *mn10300_elf_gc_mark_hook
+ PARAMS ((bfd *, struct bfd_link_info *info, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean mn10300_elf_relax_delete_bytes
PARAMS ((bfd *, asection *, bfd_vma, int));
static boolean mn10300_elf_symbol_address_p
@@ -115,6 +121,11 @@ enum reloc_type
R_MN10300_PCREL32,
R_MN10300_PCREL16,
R_MN10300_PCREL8,
+
+ /* These are GNU extensions to enable C++ vtable garbage collection. */
+ R_MN10300_GNU_VTINHERIT,
+ R_MN10300_GNU_VTENTRY,
+
R_MN10300_MAX
};
@@ -218,6 +229,36 @@ static reloc_howto_type elf_mn10300_howto_table[] =
0xff,
0xff,
true),
+
+ /* GNU extension to record C++ vtable hierarchy */
+ HOWTO (R_MN10300_GNU_VTINHERIT, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_MN10300_GNU_VTINHERIT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable member usage */
+ HOWTO (R_MN10300_GNU_VTENTRY, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_MN10300_GNU_VTENTRY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
};
struct mn10300_reloc_map
@@ -235,6 +276,8 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] =
{ BFD_RELOC_32_PCREL, R_MN10300_PCREL32, },
{ BFD_RELOC_16_PCREL, R_MN10300_PCREL16, },
{ BFD_RELOC_8_PCREL, R_MN10300_PCREL8, },
+ { BFD_RELOC_VTABLE_INHERIT, R_MN10300_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_MN10300_GNU_VTENTRY },
};
static reloc_howto_type *
@@ -270,6 +313,109 @@ mn10300_info_to_howto (abfd, cache_ptr, dst)
cache_ptr->howto = &elf_mn10300_howto_table[r_type];
}
+/* Look through the relocs for a section during the first phase.
+ Since we don't do .gots or .plts, we just need to consider the
+ virtual table relocs for gc. */
+
+static boolean
+mn10300_elf_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+
+ if (info->relocateable)
+ return true;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ if (!elf_bad_symtab (abfd))
+ sym_hashes_end -= symtab_hdr->sh_info;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_MN10300_GNU_VTINHERIT:
+ if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ return false;
+ break;
+
+ /* This relocation describes which C++ vtable entries are actually
+ used. Record for later use during GC. */
+ case R_MN10300_GNU_VTENTRY:
+ if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Return the section that should be marked against GC for a given
+ relocation. */
+
+static asection *
+mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ Elf_Internal_Rela *rel;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ if (h != NULL)
+ {
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MN10300_GNU_VTINHERIT:
+ case R_MN10300_GNU_VTENTRY:
+ break;
+
+ default:
+ switch (h->root.type)
+ {
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ return h->root.u.def.section;
+
+ case bfd_link_hash_common:
+ return h->root.u.c.p->section;
+ }
+ }
+ }
+ else
+ {
+ if (!(elf_bad_symtab (abfd)
+ && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+ && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+ && sym->st_shndx != SHN_COMMON))
+ {
+ return bfd_section_from_elf_index (abfd, sym->st_shndx);
+ }
+ }
+
+ return NULL;
+}
+
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
@@ -292,7 +438,6 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
switch (r_type)
{
-
case R_MN10300_NONE:
return bfd_reloc_ok;
@@ -352,6 +497,10 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
bfd_put_32 (input_bfd, value, hit_data);
return bfd_reloc_ok;
+ case R_MN10300_GNU_VTINHERIT:
+ case R_MN10300_GNU_VTENTRY:
+ return bfd_reloc_ok;
+
default:
return bfd_reloc_notsupported;
}
@@ -396,6 +545,11 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
r_type = ELF32_R_TYPE (rel->r_info);
howto = elf_mn10300_howto_table + r_type;
+ /* Just skip the vtable gc relocs. */
+ if (r_type == R_MN10300_GNU_VTINHERIT
+ || r_type == R_MN10300_GNU_VTENTRY)
+ continue;
+
if (info->relocateable)
{
/* This is a relocateable link. We don't have to change
@@ -2556,9 +2710,12 @@ _bfd_mn10300_elf_object_p (abfd)
#define ELF_MACHINE_CODE EM_CYGNUS_MN10300
#define ELF_MAXPAGESIZE 0x1000
-#define elf_info_to_howto mn10300_info_to_howto
-#define elf_info_to_howto_rel 0
-#define elf_backend_relocate_section mn10300_elf_relocate_section
+#define elf_info_to_howto mn10300_info_to_howto
+#define elf_info_to_howto_rel 0
+#define elf_backend_can_gc_sections 1
+#define elf_backend_check_relocs mn10300_elf_check_relocs
+#define elf_backend_gc_mark_hook mn10300_elf_gc_mark_hook
+#define elf_backend_relocate_section mn10300_elf_relocate_section
#define bfd_elf32_bfd_relax_section mn10300_elf_relax_section
#define bfd_elf32_bfd_get_relocated_section_contents \
mn10300_elf_get_relocated_section_contents