examining to gc_mark_hook, rather than the bfd.
(elf_gc_sections): Adjust.
* elf-bfd.h (struct elf_backend_data <gc_mark_hook>): Likewise.
* elf-m10300.c (mn10300_elf_gc_mark_hook): Likewise.
* elf32-arm.h (elf32_arm_gc_mark_hook): Likewise.
* elf32-avr.c (elf32_avr_gc_mark_hook): Likewise.
* elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
* elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
* elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
* elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
* elf32-i386.c (elf_i386_gc_mark_hook): Likewise.
* elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
* elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
* elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
* elf32-openrisc.c (openrisc_elf_gc_mark_hook): Likewise.
* elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
* elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
* elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
* elf32-sparc.c (elf32_sparc_gc_mark_hook): Likewise.
* elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
* elf32-vax.c (elf_vax_gc_mark_hook): Likewise.
* elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
* elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
* elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
* elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
* elf64-sh64.c (sh_elf64_gc_mark_hook): Likewise.
* elfxx-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
* elfxx-mips.h (_bfd_mips_elf_gc_mark_hook): Likewise.
* elf64-x86-64.c (elf64_x86_64_gc_mark_hook): Likewise.
* elf32-frv.c (elf32_frv_gc_mark_hook): Likewise. Also remove
redundant local sym tests.
* elf64-ppc.c (struct ppc_link_hash_entry): Add is_entry.
(link_hash_newfunc): Init is_entry.
(ppc64_elf_copy_indirect_symbol): Copy is_entry.
(ppc64_elf_link_hash_table_create): Init all_local_syms.
(create_linkage_sections): Use bfd_make_section_anyway rather than
bfd_make_section.
(ppc64_elf_mark_entry_syms): New function.
(ppc64_elf_check_relocs): Don't bother testing elf_bad_symtab. Set
up opd entry to function section map.
(ppc64_elf_gc_mark_hook): Special case opd section relocs, and
relocs that reference the opd section.
(edit_opd): New function.
(ppc64_elf_size_dynamic_sections): Call get_local_syms and edit_opd.
(ppc64_elf_setup_section_lists): Don't calculate htab->bfd_count here.
(get_local_syms): Do so here. Exit if we already have local syms.
Remove bogus comment imported from elf32-hppa.c. Don't attempt to
read local syms on non-ELF input.
(ppc64_elf_size_stubs): Call _bfd_elf64_link_read_relocs rather
than duplicating it's function here. Adjust free of internal
relocs to suit.
(ppc64_elf_relocate_section): Adjust local syms in opd section.
* elf64-ppc.h (ppc64_elf_mark_entry_syms): Declare.
* elf32-hppa.c (elf32_hppa_size_stubs): Call
_bfd_elf32_link_read_relocs rather than duplicating it's function
here. Adjust free of internal relocs to suit.
+2002-07-01 Alan Modra <amodra@bigpond.net.au>
+
+ * elflink.h (elf_gc_mark): Pass in the section whose relocs we are
+ examining to gc_mark_hook, rather than the bfd.
+ (elf_gc_sections): Adjust.
+ * elf-bfd.h (struct elf_backend_data <gc_mark_hook>): Likewise.
+ * elf-m10300.c (mn10300_elf_gc_mark_hook): Likewise.
+ * elf32-arm.h (elf32_arm_gc_mark_hook): Likewise.
+ * elf32-avr.c (elf32_avr_gc_mark_hook): Likewise.
+ * elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
+ * elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
+ * elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
+ * elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
+ * elf32-i386.c (elf_i386_gc_mark_hook): Likewise.
+ * elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
+ * elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
+ * elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
+ * elf32-openrisc.c (openrisc_elf_gc_mark_hook): Likewise.
+ * elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
+ * elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
+ * elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
+ * elf32-sparc.c (elf32_sparc_gc_mark_hook): Likewise.
+ * elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
+ * elf32-vax.c (elf_vax_gc_mark_hook): Likewise.
+ * elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
+ * elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
+ * elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
+ * elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
+ * elf64-sh64.c (sh_elf64_gc_mark_hook): Likewise.
+ * elfxx-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
+ * elfxx-mips.h (_bfd_mips_elf_gc_mark_hook): Likewise.
+ * elf64-x86-64.c (elf64_x86_64_gc_mark_hook): Likewise.
+ * elf32-frv.c (elf32_frv_gc_mark_hook): Likewise. Also remove
+ redundant local sym tests.
+ * elf64-ppc.c (struct ppc_link_hash_entry): Add is_entry.
+ (link_hash_newfunc): Init is_entry.
+ (ppc64_elf_copy_indirect_symbol): Copy is_entry.
+ (ppc64_elf_link_hash_table_create): Init all_local_syms.
+ (create_linkage_sections): Use bfd_make_section_anyway rather than
+ bfd_make_section.
+ (ppc64_elf_mark_entry_syms): New function.
+ (ppc64_elf_check_relocs): Don't bother testing elf_bad_symtab. Set
+ up opd entry to function section map.
+ (ppc64_elf_gc_mark_hook): Special case opd section relocs, and
+ relocs that reference the opd section.
+ (edit_opd): New function.
+ (ppc64_elf_size_dynamic_sections): Call get_local_syms and edit_opd.
+ (ppc64_elf_setup_section_lists): Don't calculate htab->bfd_count here.
+ (get_local_syms): Do so here. Exit if we already have local syms.
+ Remove bogus comment imported from elf32-hppa.c. Don't attempt to
+ read local syms on non-ELF input.
+ (ppc64_elf_size_stubs): Call _bfd_elf64_link_read_relocs rather
+ than duplicating it's function here. Adjust free of internal
+ relocs to suit.
+ (ppc64_elf_relocate_section): Adjust local syms in opd section.
+ * elf64-ppc.h (ppc64_elf_mark_entry_syms): Declare.
+ * elf32-hppa.c (elf32_hppa_size_stubs): Call
+ _bfd_elf32_link_read_relocs rather than duplicating it's function
+ here. Adjust free of internal relocs to suit.
+
2002-07-01 Andreas Jaeger <aj@suse.de>
* elf64-x86-64.c (elf64_x86_64_check_relocs): Certain relocations
PARAMS ((bfd *));
/* This function is called during section gc to discover the section a
- particular relocation refers to. It need not be defined for hosts
- that have no queer relocation types. */
+ particular relocation refers to. */
asection * (*gc_mark_hook)
- PARAMS ((bfd *abfd, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *sec, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *h, Elf_Internal_Sym *));
/* This function, if defined, is called during the sweep phase of gc
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 *,
+ PARAMS ((asection *, 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));
relocation. */
static asection *
-mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+mn10300_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static asection * elf32_arm_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_arm_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
}
static asection *
-elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf32_arm_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* AVR-specific support for 32-bit ELF
- Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru>
This file is part of BFD, the Binary File Descriptor library.
static void avr_info_to_howto_rela
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
static asection *elf32_avr_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_avr_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
}
static asection *
-elf32_avr_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
const Elf_Internal_Rela *));
static asection * cris_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean cris_elf_object_p PARAMS ((bfd *));
relocation. */
static asection *
-cris_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd * abfd;
+cris_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection * sec;
struct bfd_link_info * info ATTRIBUTE_UNUSED;
Elf_Internal_Rela * rel;
struct elf_link_hash_entry * h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
static void d10v_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
static asection * elf32_d10v_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_d10v_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
}
static asection *
-elf32_d10v_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+elf32_d10v_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ Elf_Internal_Rela *rel;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
{
if (h != NULL)
{
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection * fr30_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean fr30_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-fr30_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd * abfd;
+fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection * sec;
struct bfd_link_info * info ATTRIBUTE_UNUSED;
Elf_Internal_Rela * rel;
struct elf_link_hash_entry * h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
static boolean elf32_frv_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
static asection * elf32_frv_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_frv_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
static int elf32_frv_machine PARAMS ((bfd *));
relocation. */
static asection *
-elf32_frv_gc_mark_hook (abfd, info, rel, h, sym)
- bfd * abfd;
+elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
+ asection * sec;
struct bfd_link_info * info ATTRIBUTE_UNUSED;
Elf_Internal_Rela * rel;
struct elf_link_hash_entry * h;
}
}
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 bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
asection *, const Elf_Internal_Rela *));
static asection *elf32_hppa_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_hppa_gc_sweep_hook
for a given relocation. */
static asection *
-elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf32_hppa_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
section != NULL;
section = section->next)
{
- Elf_Internal_Shdr *input_rel_hdr;
- Elf32_External_Rela *external_relocs, *erelaend, *erela;
Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
- bfd_size_type amt;
/* If there aren't any relocs, then there's nothing more
to do. */
|| section->output_section->owner != output_bfd)
continue;
- /* Allocate space for the external relocations. */
- amt = section->reloc_count;
- amt *= sizeof (Elf32_External_Rela);
- external_relocs = (Elf32_External_Rela *) bfd_malloc (amt);
- if (external_relocs == NULL)
- {
- goto error_ret_free_local;
- }
-
- /* Likewise for the internal relocations. */
- amt = section->reloc_count;
- amt *= sizeof (Elf_Internal_Rela);
- internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+ /* Get the relocs. */
+ internal_relocs
+ = _bfd_elf32_link_read_relocs (input_bfd, section, NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
if (internal_relocs == NULL)
- {
- free (external_relocs);
- goto error_ret_free_local;
- }
-
- /* Read in the external relocs. */
- input_rel_hdr = &elf_section_data (section)->rel_hdr;
- if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) external_relocs,
- input_rel_hdr->sh_size,
- input_bfd) != input_rel_hdr->sh_size)
- {
- free (external_relocs);
- error_ret_free_internal:
- free (internal_relocs);
- goto error_ret_free_local;
- }
-
- /* Swap in the relocs. */
- erela = external_relocs;
- erelaend = erela + section->reloc_count;
- irela = internal_relocs;
- for (; erela < erelaend; erela++, irela++)
- bfd_elf32_swap_reloca_in (input_bfd, erela, irela);
-
- /* We're done with the external relocs, free them. */
- free (external_relocs);
+ goto error_ret_free_local;
/* Now examine each relocation. */
irela = internal_relocs;
if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
{
bfd_set_error (bfd_error_bad_value);
- goto error_ret_free_internal;
+ error_ret_free_internal:
+ if (elf_section_data (section)->relocs == NULL)
+ free (internal_relocs);
+ goto error_ret_free_local;
}
/* Only look for stubs on call instructions. */
if (stub_entry == NULL)
{
free (stub_name);
- goto error_ret_free_local;
+ goto error_ret_free_internal;
}
stub_entry->target_value = sym_value;
}
/* We're done with the internal relocs, free them. */
- free (internal_relocs);
+ if (elf_section_data (section)->relocs == NULL)
+ free (internal_relocs);
}
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection *elf_i386_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf_i386_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-elf_i386_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf_i386_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* M32R-specific support for 32-bit ELF.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
const Elf_Internal_Rela *));
asection * m32r_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
#define NOP_INSN 0x7000
}
asection *
-m32r_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+m32r_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ Elf_Internal_Rela *rel;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
{
if (h != NULL)
{
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection *elf_m68k_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf_m68k_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-elf_m68k_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf_m68k_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static asection * mcore_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean mcore_elf_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd * abfd;
+mcore_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection * sec;
struct bfd_link_info * info ATTRIBUTE_UNUSED;
Elf_Internal_Rela * rel;
struct elf_link_hash_entry * h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection * openrisc_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean openrisc_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+openrisc_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
asection *,
const Elf_Internal_Rela *));
-static asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,
+static asection * ppc_elf_gc_mark_hook PARAMS ((asection *sec,
struct bfd_link_info *info,
Elf_Internal_Rela *rel,
struct elf_link_hash_entry *h,
relocation. */
static asection *
-ppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+ppc_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection *elf_s390_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf_s390_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf_s390_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
static boolean sh_elf_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static asection * sh_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean sh_elf_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
}
static asection *
-sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+sh_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* SPARC-specific support for 32-bit ELF
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
static enum elf_reloc_type_class elf32_sparc_reloc_type_class
PARAMS ((const Elf_Internal_Rela *));
static asection * elf32_sparc_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf32_sparc_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
}
static asection *
-elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf32_sparc_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
{
-
if (h != NULL)
{
switch (ELF32_R_TYPE (rel->r_info))
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection * v850_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *,
+ PARAMS ((asection *, struct bfd_link_info *,
Elf_Internal_Rela *, struct elf_link_hash_entry *,
Elf_Internal_Sym *));
}
static asection *
-v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+v850_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection *elf_vax_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf_vax_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-elf_vax_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf_vax_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection * xstormy16_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static reloc_howto_type xstormy16_elf_howto_table [] =
relocation. */
static asection *
-xstormy16_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd * abfd;
+xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection * sec;
struct bfd_link_info * info ATTRIBUTE_UNUSED;
Elf_Internal_Rela * rel;
struct elf_link_hash_entry * h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static asection * mmix_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean mmix_elf_gc_sweep_hook
relocation. */
static asection *
-mmix_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
/* Since .opd is an array of descriptors and each entry will end up
with identical R_PPC64_RELATIVE relocs, there is really no need to
propagate .opd relocs; The dynamic linker should be taught to
- relocate .opd without reloc entries. FIXME: .opd should be trimmed
- of unused values. */
+ relocate .opd without reloc entries. */
#ifndef NO_OPD_RELOCS
#define NO_OPD_RELOCS 0
#endif
/* Flag function code and descriptor symbols. */
unsigned int is_func:1;
unsigned int is_func_descriptor:1;
+ unsigned int is_entry:1;
};
/* ppc64 ELF linker hash table. */
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection * ppc64_elf_gc_mark_hook
- PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Rela *rel,
- struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean ppc64_elf_gc_sweep_hook
- PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
- const Elf_Internal_Rela *relocs));
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
static boolean func_desc_adjust
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean ppc64_elf_func_desc_adjust
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
static void ppc64_elf_hide_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
+static boolean edit_opd
+ PARAMS ((bfd *, struct bfd_link_info *));
static boolean allocate_dynrelocs
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean readonly_dynrelocs
eh->oh = NULL;
eh->is_func = 0;
eh->is_func_descriptor = 0;
+ eh->is_entry = 0;
}
return entry;
htab->add_stub_section = NULL;
htab->layout_sections_again = NULL;
htab->stub_group = NULL;
+ htab->all_local_syms = NULL;
htab->sgot = NULL;
htab->srelgot = NULL;
htab->splt = NULL;
{
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- htab->srelbrlt = bfd_make_section (dynobj, ".rela.branch_lt");
+ htab->srelbrlt = bfd_make_section_anyway (dynobj, ".rela.branch_lt");
if (!htab->srelbrlt
|| ! bfd_set_section_flags (dynobj, htab->srelbrlt, flags)
|| ! bfd_set_section_alignment (dynobj, htab->srelbrlt, 3))
edir->is_func |= eind->is_func;
edir->is_func_descriptor |= eind->is_func_descriptor;
+ edir->is_entry |= eind->is_entry;
_bfd_elf_link_hash_copy_indirect (dir, ind);
}
+/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and
+ symbols undefined on the command-line. */
+
+boolean
+ppc64_elf_mark_entry_syms (info)
+ struct bfd_link_info *info;
+{
+ struct ppc_link_hash_table *htab;
+ struct bfd_sym_chain *sym;
+
+ htab = ppc_hash_table (info);
+ for (sym = info->gc_sym_list; sym; sym = sym->next)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = elf_link_hash_lookup (&htab->elf, sym->name, false, false, false);
+ if (h != NULL)
+ ((struct ppc_link_hash_entry *) h)->is_entry = 1;
+ }
+ return true;
+}
+
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure
linkage table, and dynamic reloc sections. */
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
asection *sreloc;
- boolean is_opd;
+ asection **opd_sym_map;
if (info->relocateable)
return true;
sym_hashes = elf_sym_hashes (abfd);
sym_hashes_end = (sym_hashes
- + symtab_hdr->sh_size / sizeof (Elf64_External_Sym));
- if (!elf_bad_symtab (abfd))
- sym_hashes_end -= symtab_hdr->sh_info;
+ + symtab_hdr->sh_size / sizeof (Elf64_External_Sym)
+ - symtab_hdr->sh_info);
sreloc = NULL;
- is_opd = strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0;
+ opd_sym_map = NULL;
+ if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0)
+ {
+ /* Garbage collection needs some extra help with .opd sections.
+ We don't want to necessarily keep everything referenced by
+ relocs in .opd, as that would keep all functions. Instead,
+ if we reference an .opd symbol (a function descriptor), we
+ want to keep the function code symbol's section. This is
+ easy for global symbols, but for local syms we need to keep
+ information about the associated function section. Later, if
+ edit_opd deletes entries, we'll use this array to adjust
+ local syms in .opd. */
+ union opd_info {
+ asection *func_section;
+ long entry_adjust;
+ };
+ bfd_size_type amt;
+
+ amt = sec->_raw_size * sizeof (union opd_info) / 24;
+ opd_sym_map = (asection **) bfd_zalloc (abfd, amt);
+ if (opd_sym_map == NULL)
+ return false;
+ elf_section_data (sec)->tdata = opd_sym_map;
+ }
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
break;
case R_PPC64_ADDR64:
- if (is_opd
+ if (opd_sym_map != NULL
&& h != NULL
&& h->root.root.string[0] == '.'
&& h->root.root.string[1] != 0)
((struct ppc_link_hash_entry *) h)->oh = fdh;
}
}
+ if (opd_sym_map != NULL
+ && h == NULL
+ && rel + 1 < rel_end
+ && ((enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info)
+ == R_PPC64_TOC))
+ {
+ asection *s;
+
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec,
+ r_symndx);
+ if (s == NULL)
+ return false;
+ else if (s != sec)
+ opd_sym_map[rel->r_offset / 24] = s;
+ }
/* Fall through. */
case R_PPC64_REL64:
case R_PPC64_UADDR64:
case R_PPC64_TOC:
/* Don't propagate .opd relocs. */
- if (NO_OPD_RELOCS && is_opd)
+ if (NO_OPD_RELOCS && opd_sym_map != NULL)
break;
/* If we are creating a shared library, and this is a reloc
relocation. */
static asection *
-ppc64_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+ppc64_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
{
+ asection *rsec = NULL;
+
if (h != NULL)
{
enum elf_ppc_reloc_type r_type;
+ struct ppc_link_hash_entry *fdh;
r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info);
switch (r_type)
{
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
- return h->root.u.def.section;
+ fdh = (struct ppc_link_hash_entry *) h;
+
+ /* Function descriptor syms cause the associated
+ function code sym section to be marked. */
+ if (fdh->is_func_descriptor)
+ rsec = fdh->oh->root.u.def.section;
+
+ /* Function entry syms return NULL if they are in .opd
+ and are not ._start (or others undefined on the ld
+ command line). Thus we avoid marking all function
+ sections, as all functions are referenced in .opd. */
+ else if ((fdh->oh != NULL
+ && ((struct ppc_link_hash_entry *) fdh->oh)->is_entry)
+ || elf_section_data (sec)->tdata == NULL)
+ rsec = h->root.u.def.section;
+ break;
case bfd_link_hash_common:
- return h->root.u.c.p->section;
+ rsec = h->root.u.c.p->section;
+ break;
default:
break;
}
else
{
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
+ asection **opd_sym_section;
+
+ rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+ opd_sym_section = (asection **) elf_section_data (rsec)->tdata;
+ if (opd_sym_section != NULL)
+ rsec = opd_sym_section[sym->st_value / 24];
+ else if (elf_section_data (sec)->tdata != NULL)
+ rsec = NULL;
}
- return NULL;
+ return rsec;
}
/* Update the .got, .plt. and dynamic reloc reference counts for the
}
}
+static boolean
+edit_opd (obfd, info)
+ bfd *obfd;
+ struct bfd_link_info *info;
+{
+ bfd *ibfd;
+ unsigned int bfd_indx;
+ struct ppc_link_hash_table *htab = ppc_hash_table (info);
+
+ for (bfd_indx = 0, ibfd = info->input_bfds;
+ ibfd != NULL;
+ ibfd = ibfd->link_next, bfd_indx++)
+ {
+ asection *sec;
+ Elf_Internal_Rela *relstart, *rel, *relend;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma offset;
+ long *adjust;
+ boolean need_edit;
+
+ sec = bfd_get_section_by_name (ibfd, ".opd");
+ if (sec == NULL)
+ continue;
+
+ adjust = (long *) elf_section_data (sec)->tdata;
+ BFD_ASSERT (adjust != NULL);
+ memset (adjust, 0, (size_t) sec->_raw_size * sizeof (long) / 24);
+
+ if (sec->output_section == bfd_abs_section_ptr)
+ continue;
+
+ /* Look through the section relocs. */
+ if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0)
+ continue;
+
+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (ibfd);
+
+ /* Read the relocations. */
+ relstart = _bfd_elf64_link_read_relocs (obfd, sec, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
+ if (relstart == NULL)
+ return false;
+
+ /* First run through the relocs to check they are sane, and to
+ determine whether we need to edit this opd section. */
+ need_edit = false;
+ offset = 0;
+ relend = relstart + sec->reloc_count;
+ for (rel = relstart; rel < relend; rel++)
+ {
+ enum elf_ppc_reloc_type r_type;
+ unsigned long r_symndx;
+ asection *sym_sec;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+
+ /* .opd contains a regular array of 24 byte entries. We're
+ only interested in the reloc pointing to a function entry
+ point. */
+ r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info);
+ if (r_type == R_PPC64_TOC)
+ continue;
+
+ if (r_type != R_PPC64_ADDR64)
+ {
+ (*_bfd_error_handler)
+ (_("%s: unexpected reloc type %u in .opd section"),
+ bfd_archive_filename (ibfd), r_type);
+ need_edit = false;
+ break;
+ }
+
+ if (rel + 1 >= relend)
+ continue;
+ r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info);
+ if (r_type != R_PPC64_TOC)
+ continue;
+
+ if (rel->r_offset != offset)
+ {
+ /* If someone messes with .opd alignment then after a
+ "ld -r" we might have padding in the middle of .opd.
+ Also, there's nothing to prevent someone putting
+ something silly in .opd with the assembler. No .opd
+ optimization for them! */
+ (*_bfd_error_handler)
+ (_("%s: .opd is not a regular array of opd entries"),
+ bfd_archive_filename (ibfd));
+ need_edit = false;
+ break;
+ }
+
+ r_symndx = ELF64_R_SYM (rel->r_info);
+ sym_sec = NULL;
+ h = NULL;
+ sym = NULL;
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ sym_sec = h->root.u.def.section;
+ }
+ else
+ {
+ sym = htab->all_local_syms[bfd_indx] + r_symndx;
+ if ((sym->st_shndx != SHN_UNDEF
+ && sym->st_shndx < SHN_LORESERVE)
+ || sym->st_shndx > SHN_HIRESERVE)
+ sym_sec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
+ }
+
+ if (sym_sec == NULL || sym_sec->owner == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: undefined sym `%s' in .opd section"),
+ bfd_archive_filename (ibfd),
+ h != NULL ? h->root.root.string : "<local symbol>");
+ need_edit = false;
+ break;
+ }
+
+ if (sym_sec->output_section == bfd_abs_section_ptr)
+ {
+ /* OK, we've found a function that's excluded from the
+ link. */
+ need_edit = true;
+ }
+
+ offset += 24;
+ }
+
+ if (need_edit)
+ {
+ Elf_Internal_Rela *write_rel;
+ bfd_byte *rptr, *wptr;
+ boolean skip;
+
+ /* This seems a waste of time as input .opd sections are all
+ zeros as generated by gcc, but I suppose there's no reason
+ this will always be so. We might start putting something in
+ the third word of .opd entries. */
+ if ((sec->flags & SEC_IN_MEMORY) == 0)
+ {
+ bfd_byte *loc = bfd_alloc (ibfd, sec->_raw_size);
+ if (loc == NULL)
+ return false;
+ if (! bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0,
+ sec->_raw_size))
+ return false;
+ sec->contents = loc;
+ sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
+ }
+
+ elf_section_data (sec)->relocs = relstart;
+
+ wptr = sec->contents;
+ rptr = sec->contents;
+ write_rel = relstart;
+ skip = false;
+ offset = 0;
+ for (rel = relstart; rel < relend; rel++)
+ {
+ if (rel->r_offset == offset)
+ {
+ unsigned long r_symndx;
+ asection *sym_sec;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+
+ r_symndx = ELF64_R_SYM (rel->r_info);
+ sym_sec = NULL;
+ h = NULL;
+ sym = NULL;
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ sym_sec = h->root.u.def.section;
+ }
+ else
+ {
+ sym = htab->all_local_syms[bfd_indx] + r_symndx;
+ if ((sym->st_shndx != SHN_UNDEF
+ && sym->st_shndx < SHN_LORESERVE)
+ || sym->st_shndx > SHN_HIRESERVE)
+ sym_sec = bfd_section_from_elf_index (ibfd,
+ sym->st_shndx);
+ }
+
+ skip = sym_sec->output_section == bfd_abs_section_ptr;
+ if (!skip)
+ {
+ /* We'll be keeping this opd entry. */
+
+ if (h != NULL)
+ {
+ /* Redefine the function descriptor symbol
+ to this location in the opd section.
+ We've checked above that opd relocs are
+ ordered. */
+ struct elf_link_hash_entry *fdh;
+ struct ppc_link_hash_entry *fh;
+
+ fh = (struct ppc_link_hash_entry *) h;
+ BFD_ASSERT (fh->is_func);
+ fdh = fh->oh;
+ fdh->root.u.def.value = wptr - sec->contents;
+ }
+ else
+ {
+ /* Local syms are a bit tricky. Other parts
+ of the linker re-read them so it's not
+ possible to tweak local sym values. In
+ any case, we'd need to look through the
+ local syms for the function descriptor
+ sym which we don't have at the moment.
+ So keep an array of adjustments. */
+ adjust[(rel->r_offset + wptr - rptr) / 24]
+ = wptr - rptr;
+ }
+
+ if (wptr != rptr)
+ memcpy (wptr, rptr, 24);
+ wptr += 24;
+ }
+ rptr += 24;
+ offset += 24;
+ }
+
+ /* We need to adjust any reloc offsets to point to the
+ new opd entries. While we're at it, we may as well
+ remove redundant relocs. */
+ if (!skip)
+ {
+ rel->r_offset += wptr - rptr;
+ if (write_rel != rel)
+ memcpy (write_rel, rel, sizeof (*rel));
+ ++write_rel;
+ }
+ }
+
+ sec->_cooked_size = wptr - sec->contents;
+ sec->reloc_count = write_rel - relstart;
+ }
+ else if (elf_section_data (sec)->relocs == NULL)
+ free (relstart);
+ }
+
+ return true;
+}
+
/* This is the condition under which ppc64_elf_finish_dynamic_symbol
will be called from elflink.h. If elflink.h doesn't call our
finish_dynamic_symbol routine, we'll need to do something about
}
}
+ if (!get_local_syms (info->input_bfds, htab))
+ return false;
+
+ if (!edit_opd (output_bfd, info))
+ return false;
+
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
struct bfd_link_info *info;
{
bfd *input_bfd;
- unsigned int bfd_count;
int top_id, top_index;
asection *section;
asection **input_list, **list;
|| htab->sbrlt == NULL)
return 0;
- /* Count the number of input BFDs and find the top input section id. */
- for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
+ /* Find the top input section id. */
+ for (input_bfd = info->input_bfds, top_id = 0;
input_bfd != NULL;
input_bfd = input_bfd->link_next)
{
- bfd_count += 1;
for (section = input_bfd->sections;
section != NULL;
section = section->next)
top_id = section->id;
}
}
- htab->bfd_count = bfd_count;
amt = sizeof (struct map_stub) * (top_id + 1);
htab->stub_group = (struct map_stub *) bfd_zmalloc (amt);
struct ppc_link_hash_table *htab;
{
unsigned int bfd_indx;
+ bfd *ibfd;
Elf_Internal_Sym *local_syms, **all_local_syms;
+ bfd_size_type amt;
+
+ if (htab->all_local_syms != NULL)
+ return true;
/* We want to read in symbol extension records only once. To do this
we need to read in the local symbols in parallel and save them for
later use; so hold pointers to the local symbols in an array. */
- bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
+ for (ibfd = input_bfd, bfd_indx = 0; ibfd != NULL; ibfd = ibfd->link_next)
+ bfd_indx += 1;
+ htab->bfd_count = bfd_indx;
+ amt = sizeof (Elf_Internal_Sym *) * bfd_indx;
all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt);
htab->all_local_syms = all_local_syms;
if (all_local_syms == NULL)
return false;
- /* Walk over all the input BFDs, swapping in local symbols.
- If we are creating a shared library, create hash entries for the
- export stubs. */
+ /* Walk over all the input BFDs, swapping in local symbols. */
for (bfd_indx = 0;
input_bfd != NULL;
input_bfd = input_bfd->link_next, bfd_indx++)
Elf_External_Sym_Shndx *shndx_buf, *shndx;
bfd_size_type sec_size;
+ if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour)
+ continue;
+
/* We'll need the symbol table in a second. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
if (symtab_hdr->sh_info == 0)
section != NULL;
section = section->next)
{
- Elf_Internal_Shdr *input_rel_hdr;
- Elf64_External_Rela *external_relocs, *erelaend, *erela;
Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
- bfd_size_type amt;
/* If there aren't any relocs, then there's nothing more
to do. */
|| section->output_section->owner != output_bfd)
continue;
- /* Allocate space for the external relocations. */
- amt = section->reloc_count;
- amt *= sizeof (Elf64_External_Rela);
- external_relocs = (Elf64_External_Rela *) bfd_malloc (amt);
- if (external_relocs == NULL)
- {
- goto error_ret_free_local;
- }
-
- /* Likewise for the internal relocations. */
- amt = section->reloc_count;
- amt *= sizeof (Elf_Internal_Rela);
- internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+ /* Get the relocs. */
+ internal_relocs
+ = _bfd_elf64_link_read_relocs (input_bfd, section, NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
if (internal_relocs == NULL)
- {
- free (external_relocs);
- goto error_ret_free_local;
- }
-
- /* Read in the external relocs. */
- input_rel_hdr = &elf_section_data (section)->rel_hdr;
- if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) external_relocs,
- input_rel_hdr->sh_size,
- input_bfd) != input_rel_hdr->sh_size)
- {
- free (external_relocs);
- error_ret_free_internal:
- free (internal_relocs);
- goto error_ret_free_local;
- }
-
- /* Swap in the relocs. */
- erela = external_relocs;
- erelaend = erela + section->reloc_count;
- irela = internal_relocs;
- for (; erela < erelaend; erela++, irela++)
- bfd_elf64_swap_reloca_in (input_bfd, erela, irela);
-
- /* We're done with the external relocs, free them. */
- free (external_relocs);
+ goto error_ret_free_local;
/* Now examine each relocation. */
irela = internal_relocs;
if (r_type >= (unsigned int) R_PPC_max)
{
bfd_set_error (bfd_error_bad_value);
- goto error_ret_free_internal;
+ error_ret_free_internal:
+ if (elf_section_data (section)->relocs == NULL)
+ free (internal_relocs);
+ goto error_ret_free_local;
}
/* Only look for stubs on branch instructions. */
if (stub_entry == NULL)
{
free (stub_name);
- goto error_ret_free_local;
+ goto error_ret_free_internal;
}
stub_entry->target_value = sym_value;
}
/* We're done with the internal relocs, free them. */
- free (internal_relocs);
+ if (elf_section_data (section)->relocs == NULL)
+ free (internal_relocs);
}
}
TOCstart = elf_gp (output_bfd);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
- is_opd = strcmp (bfd_get_section_name (abfd, input_section), ".opd") == 0;
+ is_opd = elf_section_data (input_section)->tdata != NULL;
rel = relocs;
relend = relocs + input_section->reloc_count;
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
/* rel may have changed, update our copy of addend. */
addend = rel->r_addend;
+
+ if (elf_section_data (sec) != NULL)
+ {
+ long *opd_sym_adjust;
+
+ opd_sym_adjust = (long *) elf_section_data (sec)->tdata;
+ if (opd_sym_adjust != NULL && sym->st_value % 24 == 0)
+ relocation += opd_sym_adjust[sym->st_value / 24];
+ }
}
else
{
shared lib. (I believe this is a generic
bug in binutils handling of weak syms.)
In these cases we won't use the opd
- entry in this lib; We ought to edit the
- opd section to remove unused entries. */
+ entry in this lib. */
unresolved_reloc = false;
}
outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+boolean ppc64_elf_mark_entry_syms
+ PARAMS ((struct bfd_link_info *));
bfd_vma ppc64_elf_toc
PARAMS ((bfd *));
int ppc64_elf_setup_section_lists
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static asection *elf_s390_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf_s390_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-elf_s390_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf_s390_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
static boolean sh_elf64_set_mach_from_flags PARAMS ((bfd *));
static boolean sh_elf64_set_private_flags PARAMS ((bfd *, flagword));
static asection *sh_elf64_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean sh_elf64_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,
relocation. */
static asection *
-sh_elf64_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+sh_elf64_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ Elf_Internal_Rela *rel;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
{
if (h != NULL)
{
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
const Elf_Internal_Rela *));
static asection *elf64_x86_64_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
static boolean elf64_x86_64_gc_sweep_hook
relocation. */
static asection *
-elf64_x86_64_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+elf64_x86_64_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
static boolean elf_gc_mark
PARAMS ((struct bfd_link_info *info, asection *sec,
asection * (*gc_mark_hook)
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *))));
static boolean elf_gc_sweep
struct bfd_link_info *info;
asection *sec;
asection * (*gc_mark_hook)
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
{
boolean ret;
(const PTR) locshndx,
&s);
if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
- rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
+ rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
else
{
h = sym_hashes[r_symndx - extsymoff];
- rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
+ rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
}
}
else if (r_symndx >= nlocsyms)
{
h = sym_hashes[r_symndx - extsymoff];
- rsec = (*gc_mark_hook) (sec->owner, info, rel, h, NULL);
+ rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
}
else
{
(const PTR) (locsyms + r_symndx),
(const PTR) locshndx,
&s);
- rsec = (*gc_mark_hook) (sec->owner, info, rel, NULL, &s);
+ rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s);
}
if (rsec && !rsec->gc_mark)
boolean ok = true;
bfd *sub;
asection * (*gc_mark_hook)
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *h, Elf_Internal_Sym *));
if (!get_elf_backend_data (abfd)->can_gc_sections
relocation. */
asection *
-_bfd_mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
- bfd *abfd;
+_bfd_mips_elf_gc_mark_hook (sec, info, rel, h, sym)
+ asection *sec;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
if (h != NULL)
{
- switch (ELF_R_TYPE (abfd, rel->r_info))
+ switch (ELF_R_TYPE (sec->owner, rel->r_info))
{
case R_MIPS_GNU_VTINHERIT:
case R_MIPS_GNU_VTENTRY:
}
}
else
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
return NULL;
}
extern boolean _bfd_mips_elf_modify_segment_map
PARAMS ((bfd *));
extern asection * _bfd_mips_elf_gc_mark_hook
- PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+ PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
extern boolean _bfd_mips_elf_gc_sweep_hook
PARAMS ((bfd *, struct bfd_link_info *, asection *,