relocs into shared libs.
* elf32-cris.c (cris_elf_relocate_section): Likewise.
* elf32-i370.c (i370_elf_relocate_section): Likewise.
* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
* elf32-mips.c (mips_elf_calculate_relocation): Likewise.
* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
* elf32-sh.c (sh_elf_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
* elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
* elf64-s390.c (elf_s390_relocate_section): Likewise.
* elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
* elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
* elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise.
* elf.c (bfd_section_from_r_symndx): New function.
* elf-bfd.h (LOCAL_SYM_CACHE_SIZE): Define.
(struct sym_sec_cache): New.
(bfd_section_from_r_symndx): Declare.
(struct bfd_elf_section_data): Change local_dynrel type to PTR.
* elflink.h (elf_link_input_bfd): Don't test for removed linkonce
relocs when relocatable. Don't zero entire reloc, just zero the
addend and sym.
* elf32-i386.c (struct elf_i386_link_hash_table): Add sym_sec.
(elf_i386_link_hash_table_create): Init it.
(elf_i386_check_relocs): Track dynamic relocs needed for local
syms on a per-section basis as we do for globals.
(elf_i386_gc_sweep_hook): Update for local_dynrel change.
Remove dead code.
(allocate_dynrelocs): Warning fix.
(elf_i386_size_dynamic_sections): Don't allocate relocs when
section has been discarded.
(elf_i386_relocate_section): Don't copy STN_UNDEF relocs
into shared libs.
* elf32-hppa.c: Likewise.
* elf32-s390.c: Likewise.
* elf64-ppc.c: Likewise.
* elf64-s390.c: Likewise.
+2001-11-10 Alan Modra <amodra@bigpond.net.au>
+
+ * elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF
+ relocs into shared libs.
+ * elf32-cris.c (cris_elf_relocate_section): Likewise.
+ * elf32-i370.c (i370_elf_relocate_section): Likewise.
+ * elf32-m68k.c (elf_m68k_relocate_section): Likewise.
+ * elf32-mips.c (mips_elf_calculate_relocation): Likewise.
+ * elf32-ppc.c (ppc_elf_relocate_section): Likewise.
+ * elf32-sh.c (sh_elf_relocate_section): Likewise.
+ * elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
+ * elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
+ * elf64-s390.c (elf_s390_relocate_section): Likewise.
+ * elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
+ * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
+ * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise.
+
+ * elf.c (bfd_section_from_r_symndx): New function.
+ * elf-bfd.h (LOCAL_SYM_CACHE_SIZE): Define.
+ (struct sym_sec_cache): New.
+ (bfd_section_from_r_symndx): Declare.
+ (struct bfd_elf_section_data): Change local_dynrel type to PTR.
+ * elflink.h (elf_link_input_bfd): Don't test for removed linkonce
+ relocs when relocatable. Don't zero entire reloc, just zero the
+ addend and sym.
+ * elf32-hppa.c (struct elf32_hppa_link_hash_table): Add sym_sec.
+ (elf32_hppa_link_hash_table_create): Init it.
+ (elf32_hppa_check_relocs): Track dynamic relocs needed for local
+ syms on a per-section basis as we do for globals.
+ (elf32_hppa_gc_sweep_hook): Update for local_dynrel change.
+ (allocate_dynrelocs): Warning fix.
+ (elf32_hppa_size_dynamic_sections): Don't allocate relocs when
+ section has been discarded.
+ (elf32_hppa_relocate_section): Don't copy STN_UNDEF relocs
+ into shared libs.
+ * elf32-i386.c (struct elf_i386_link_hash_table): Add sym_sec.
+ (elf_i386_link_hash_table_create): Init it.
+ (elf_i386_check_relocs): Track dynamic relocs needed for local
+ syms on a per-section basis as we do for globals.
+ (elf_i386_gc_sweep_hook): Update for local_dynrel change.
+ Remove dead code.
+ (allocate_dynrelocs): Warning fix.
+ (elf_i386_size_dynamic_sections): Don't allocate relocs when
+ section has been discarded.
+ (elf_i386_relocate_section): Don't copy STN_UNDEF relocs
+ into shared libs.
+ * elf32-s390.c (struct elf_s390_link_hash_table): Add sym_sec.
+ (elf_s390_link_hash_table_create): Init it.
+ (elf_s390_check_relocs): Track dynamic relocs needed for local
+ syms on a per-section basis as we do for globals.
+ (elf_s390_gc_sweep_hook): Update for local_dynrel change.
+ Remove dead code.
+ (allocate_dynrelocs): Warning fix.
+ (elf_s390_size_dynamic_sections): Don't allocate relocs when
+ section has been discarded.
+ (elf_s390_relocate_section): Don't copy STN_UNDEF relocs
+ into shared libs.
+ * elf64-ppc.c (struct ppc_link_hash_table): Add sym_sec.
+ (ppc64_link_hash_table_create): Init it.
+ (ppc64_elf_check_relocs): Track dynamic relocs needed for local
+ syms on a per-section basis as we do for globals.
+ (ppc64_elf_gc_sweep_hook): Update for local_dynrel change.
+ (allocate_dynrelocs): Call the correct record_dynamic_dymbol
+ function. Warning fix.
+ (ppc64_elf_size_dynamic_sections): Don't allocate relocs when
+ section has been discarded.
+ (ppc64_elf_relocate_section): Don't copy STN_UNDEF relocs
+ into shared libs.
+ * elf64-s390.c (struct elf_s390_link_hash_table): Add sym_sec.
+ (elf_s390_link_hash_table_create): Init it.
+ (elf_s390_check_relocs): Track dynamic relocs needed for local
+ syms on a per-section basis as we do for globals.
+ (elf_s390_gc_sweep_hook): Update for local_dynrel change.
+ Remove dead code.
+ (allocate_dynrelocs): Warning fix.
+ (elf_s390_size_dynamic_sections): Don't allocate relocs when
+ section has been discarded.
+ (elf_s390_relocate_section): Don't copy STN_UNDEF relocs
+ into shared libs.
+
2001-11-08 Martin Schwidefsky <schwidefsky@de.ibm.com>
* elf32-s390: Major rework that introduces all recent changes to
(elf_s390_copy_indirect_symbol): New function.
(elf_s390_create_dynamic_sections): New function.
(readonly_dynrelocs): New function.
- * elf64-s390x: Likewise.
+ * elf64-s390.c: Likewise.
2001-11-07 Jakub Jelinek <jakub@redhat.com>
/* Returns true if the hash table is a struct elf_link_hash_table. */
#define is_elf_hash_table(p) \
((p)->hash->type == bfd_link_elf_hash_table)
+
+/* Used by bfd_section_from_r_symndx to cache a small number of local
+ symbol to section mappings. */
+#define LOCAL_SYM_CACHE_SIZE 32
+struct sym_sec_cache
+{
+ bfd *abfd;
+ unsigned long indx[LOCAL_SYM_CACHE_SIZE];
+ asection *sec[LOCAL_SYM_CACHE_SIZE];
+};
\f
/* Constant information held for an ELF backend. */
/* The number of relocations currently assigned to REL_HDR2. */
unsigned int rel_count2;
- /* The number of dynamic relocs copied for local symbols. */
- unsigned int local_dynrel;
+ /* A pointer to a linked list tracking dynamic relocs copied for
+ local symbols. */
+ PTR local_dynrel;
/* A pointer to the bfd section used for dynamic relocs. */
asection *sreloc;
extern int _bfd_elf_symbol_from_bfd_symbol
PARAMS ((bfd *, asymbol **));
+extern asection *bfd_section_from_r_symndx
+ PARAMS ((bfd *, struct sym_sec_cache *, asection *, unsigned long));
extern asection *bfd_section_from_elf_index
PARAMS ((bfd *, unsigned int));
extern boolean _bfd_elf_create_dynamic_sections
return true;
}
+/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
+ Return SEC for sections that have no elf section, and NULL on error. */
+
+asection *
+bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
+ bfd *abfd;
+ struct sym_sec_cache *cache;
+ asection *sec;
+ unsigned long r_symndx;
+{
+ unsigned char esym_shndx[2];
+ unsigned int isym_shndx;
+ Elf_Internal_Shdr *symtab_hdr;
+ file_ptr pos;
+ bfd_size_type amt;
+ unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
+
+ if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
+ return cache->sec[ent];
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ pos = symtab_hdr->sh_offset;
+ if (get_elf_backend_data (abfd)->s->sizeof_sym
+ == sizeof (Elf64_External_Sym))
+ {
+ pos += r_symndx * sizeof (Elf64_External_Sym);
+ pos += offsetof (Elf64_External_Sym, st_shndx);
+ }
+ else
+ {
+ pos += r_symndx * sizeof (Elf32_External_Sym);
+ pos += offsetof (Elf32_External_Sym, st_shndx);
+ }
+ amt = sizeof (esym_shndx);
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0
+ || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+ return NULL;
+ isym_shndx = H_GET_16 (abfd, esym_shndx);
+
+ if (cache->abfd != abfd)
+ {
+ memset (cache->indx, -1, sizeof (cache->indx));
+ cache->abfd = abfd;
+ }
+ cache->indx[ent] = r_symndx;
+ cache->sec[ent] = sec;
+ if (isym_shndx > 0 && isym_shndx < SHN_LORESERVE)
+ {
+ asection *s;
+ s = bfd_section_from_elf_index (abfd, isym_shndx);
+ if (s != NULL)
+ cache->sec[ent] = s;
+ }
+ return cache->sec[ent];
+}
+
/* Given an ELF section number, retrieve the corresponding BFD
section. */
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
if (info->shared
+ && r_symndx != 0
&& (r_type != R_ARM_PC24
|| (h != NULL
&& h->dynindx != -1
case R_CRIS_16:
case R_CRIS_32:
if (info->shared
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_CRIS_8_PCREL
&& r_type != R_CRIS_16_PCREL
/* Set if we need a .plt stub to support lazy dynamic linking. */
unsigned int need_plt_stub:1;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Various hash macros and functions. */
ret->has_12bit_branch = 0;
ret->has_17bit_branch = 0;
ret->need_plt_stub = 0;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
|| (h->elf.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf32_hppa_dyn_reloc_entry *p;
+ struct elf32_hppa_dyn_reloc_entry **head;
+
/* Create a reloc section in dynobj and make room for
this reloc. */
if (sreloc == NULL)
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf32_hppa_dyn_reloc_entry *p;
+ head = &h->dyn_relocs;
+ }
+ else
+ {
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
- p = h->dyn_relocs;
- if (p == NULL || p->sec != sec)
- {
- p = ((struct elf32_hppa_dyn_reloc_entry *)
- bfd_alloc (htab->elf.dynobj,
- (bfd_size_type) sizeof *p));
- if (p == NULL)
- return false;
- p->next = h->dyn_relocs;
- h->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
+ head = ((struct elf32_hppa_dyn_reloc_entry **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ p = ((struct elf32_hppa_dyn_reloc_entry *)
+ bfd_alloc (htab->elf.dynobj,
+ (bfd_size_type) sizeof *p));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
#if RELATIVE_DYNRELOCS
- p->relative_count = 0;
+ p->relative_count = 0;
#endif
- }
+ }
- p->count += 1;
+ p->count += 1;
#if RELATIVE_DYNRELOCS
- if (!IS_ABSOLUTE_RELOC (rtype))
- p->relative_count += 1;
+ if (!IS_ABSOLUTE_RELOC (rtype))
+ p->relative_count += 1;
#endif
- }
- else
- {
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
- }
}
}
}
struct elf32_hppa_link_hash_table *htab;
bfd *dynobj;
- elf_section_data (sec)->local_dynrel = 0;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
eh->dyn_relocs = NULL;
return true;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf32_hppa_dyn_reloc_entry *p;
- if (count != 0)
+ for (p = ((struct elf32_hppa_dyn_reloc_entry *)
+ elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srel = elf_section_data (s)->sreloc;
- srel->_raw_size += count * sizeof (Elf32_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srel = elf_section_data (p->sec)->sreloc;
+ srel->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ }
}
}
case R_PARISC_DPREL14R:
case R_PARISC_DPREL21L:
case R_PARISC_DIR32:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
/* The reloc types handled here and this conditional
expression must match the code in ..check_relocs and
- ..discard_relocs. ie. We need exactly the same condition
+ allocate_dynrelocs. ie. We need exactly the same condition
as in ..check_relocs, with some extra conditions (dynindx
test in this case) to cater for relocs removed by
- ..discard_relocs. If you squint, the non-shared test
+ allocate_dynrelocs. If you squint, the non-shared test
here does indeed match the one in ..check_relocs, the
difference being that here we test DEF_DYNAMIC as well as
!DEF_REGULAR. All common syms end up with !DEF_REGULAR,
Conversely, DEF_DYNAMIC can't be used in check_relocs as
there all files have not been loaded. */
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& (IS_ABSOLUTE_RELOC (r_type)
|| (h != NULL
&& h->elf.dynindx != -1
|| (h->elf.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->elf.dynindx != -1
&& (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
object. */
case (int)R_I370_ADDR31:
case (int)R_I370_ADDR16:
- if (info->shared)
+ if (info->shared
+ && r_symndx != 0)
{
Elf_Internal_Rela outrel;
boolean skip;
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Get the i386 ELF linker hash table from a link_info structure. */
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf_i386_dyn_relocs *p;
+ struct elf_i386_dyn_relocs **head;
+
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
this reloc. */
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf_i386_link_hash_entry *eh;
- struct elf_i386_dyn_relocs *p;
-
- eh = (struct elf_i386_link_hash_entry *) h;
- p = eh->dyn_relocs;
-
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof *p;
- p = ((struct elf_i386_dyn_relocs *)
- bfd_alloc (htab->elf.dynobj, amt));
- if (p == NULL)
- return false;
- p->next = eh->dyn_relocs;
- eh->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
- p->pc_count += 1;
+ head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
}
else
{
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
+
+ head = ((struct elf_i386_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ bfd_size_type amt = sizeof *p;
+ p = ((struct elf_i386_dyn_relocs *)
+ bfd_alloc (htab->elf.dynobj, amt));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
}
+
+ p->count += 1;
+ if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
+ p->pc_count += 1;
}
break;
const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
- bfd *dynobj;
- elf_section_data (sec)->local_dynrel = 0;
-
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return true;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
eh->dyn_relocs = NULL;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf_i386_dyn_relocs *p;
- if (count != 0)
+ for (p = *((struct elf_i386_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srel = elf_section_data (s)->sreloc;
- srel->_raw_size += count * sizeof (Elf32_External_Rel);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srel = elf_section_data (p->sec)->sreloc;
+ srel->_raw_size += p->count * sizeof (Elf32_External_Rel);
+ }
}
}
case R_386_32:
case R_386_PC32:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
&& h->dynindx != -1
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
if (! relocate)
continue;
}
-
break;
default:
case R_68K_16:
case R_68K_32:
if (info->shared
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_68K_PC8
&& r_type != R_68K_PC16
& ELF_LINK_HASH_DEF_DYNAMIC) != 0)
&& ((h->root.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0)
{
/* If we're creating a shared library, or this relocation is
case (int) R_PPC_ADDR14:
case (int) R_PPC_UADDR32:
case (int) R_PPC_UADDR16:
- if (info->shared)
+ if (info->shared && r_symndx != 0)
{
Elf_Internal_Rela outrel;
boolean skip;
bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
- switch (code)
+ switch (code)
{
case BFD_RELOC_NONE:
return &elf_howto_table[(int) R_390_NONE];
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Get the s390 ELF linker hash table from a link_info structure. */
if (entry == NULL)
return entry;
}
-
+
/* Call the allocation method of the superclass. */
entry = _bfd_elf_link_hash_newfunc (entry, table, string);
if (entry != NULL)
{
struct elf_s390_link_hash_entry *eh;
-
+
eh = (struct elf_s390_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
}
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
+
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
symbol. */
if ((info->shared
&& (sec->flags & SEC_ALLOC) != 0
- && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
+ && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
&& ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
&& ELF32_R_TYPE (rel->r_info) != R_390_PC32)
|| (h != NULL
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf_s390_dyn_relocs *p;
+ struct elf_s390_dyn_relocs **head;
+
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
this reloc. */
{
const char *name;
bfd *dynobj;
-
+
name = (bfd_elf_string_from_elf_section
(abfd,
elf_elfheader (abfd)->e_shstrndx,
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf_s390_link_hash_entry *eh;
- struct elf_s390_dyn_relocs *p;
-
- eh = (struct elf_s390_link_hash_entry *) h;
- p = eh->dyn_relocs;
-
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof *p;
- p = ((struct elf_s390_dyn_relocs *)
- bfd_alloc (htab->elf.dynobj, amt));
- if (p == NULL)
- return false;
- p->next = eh->dyn_relocs;
- eh->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
- || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
- || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
- p->pc_count += 1;
+ head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs;
}
else
{
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
+
+ head = ((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ bfd_size_type amt = sizeof *p;
+ p = ((struct elf_s390_dyn_relocs *)
+ bfd_alloc (htab->elf.dynobj, amt));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
}
+
+ p->count += 1;
+ if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
+ || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
+ || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
+ p->pc_count += 1;
}
break;
-
+
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_390_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_390_GNU_VTENTRY:
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return false;
break;
-
+
default:
break;
}
const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
- bfd *dynobj;
-
- elf_section_data (sec)->local_dynrel = 0;
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return true;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
}
/* If we didn't find any dynamic relocs in read-only sections, then
- we'll be keeping the dynamic relocs and avoiding the copy reloc. */
+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
if (p == NULL)
{
h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
h->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
}
-
+
/* Make room for this entry. */
s->_raw_size += PLT_ENTRY_SIZE;
-
+
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
htab->sgotplt->_raw_size += GOT_ENTRY_SIZE;
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
- }
+ }
else
{
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- }
-
+ }
+
if (h->got.refcount > 0)
{
asection *s;
eh->dyn_relocs = NULL;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf_s390_dyn_relocs *p;
- if (count != 0)
+ for (p = *((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srela = elf_section_data (s)->sreloc;
- srela->_raw_size += count * sizeof (Elf32_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srela = elf_section_data (p->sec)->sreloc;
+ srela->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ }
}
}
{
if (s->_raw_size != 0 && s != htab->srelplt)
relocs = true;
-
+
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
s->reloc_count = 0;
if (s->contents == NULL)
return false;
}
-
+
if (htab->elf.dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
-
+
if (! info->shared)
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return false;
}
-
+
if (htab->splt->_raw_size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_JMPREL, 0))
return false;
}
-
+
if (relocs)
{
if (!add_dynamic_entry (DT_RELA, 0)
/* If any dynamic relocs apply to a read-only section,
then we need a DT_TEXTREL entry. */
elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info);
-
+
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
}
}
#undef add_dynamic_entry
-
+
return true;
}
bfd_vma relocation;
boolean unresolved_reloc;
bfd_reloc_status_type r;
-
+
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == (int) R_390_GNU_VTINHERIT
|| r_type == (int) R_390_GNU_VTENTRY)
return false;
}
howto = elf_howto_table + r_type;
-
+
r_symndx = ELF32_R_SYM (rel->r_info);
-
+
if (info->relocateable)
{
/* This is a relocateable link. We don't have to change
rel->r_addend += sec->output_offset + sym->st_value;
}
}
-
+
continue;
}
-
+
/* This is a final link. */
h = NULL;
sym = NULL;
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)
{
relocation = 0;
}
}
-
+
switch (r_type)
{
case R_390_GOT12:
offset table. */
if (htab->sgot == NULL)
abort ();
-
+
if (h != NULL)
{
boolean dyn;
-
+
off = h->got.offset;
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
case R_390_PC16:
case R_390_PC16DBL:
case R_390_PC32:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_390_PC16
&& r_type != R_390_PC16DBL
&& r_type != R_390_PC32)
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
boolean skip, relocate;
asection *sreloc;
Elf32_External_Rela *loc;
-
+
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
-
+
skip = false;
-
+
if (elf_section_data (input_section)->stab_info == NULL)
outrel.r_offset = rel->r_offset;
else
skip = true;
outrel.r_offset = off;
}
-
+
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
-
+
if (skip)
{
memset (&outrel, 0, sizeof outrel);
outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
outrel.r_addend = relocation + rel->r_addend;
}
-
+
sreloc = elf_section_data (input_section)->sreloc;
if (sreloc == NULL)
abort ();
-
+
loc = (Elf32_External_Rela *) sreloc->contents;
loc += sreloc->reloc_count++;
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
-
+
/* If this reloc is against an external symbol, we do
not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes
if (! relocate)
continue;
}
-
break;
-
+
default:
break;
}
-
+
if (unresolved_reloc
&& !(info->shared
&& (input_section->flags & SEC_DEBUGGING) != 0
bfd_get_section_name (input_bfd, input_section),
(long) rel->r_offset,
h->root.root.string);
-
+
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
relocation, rel->r_addend);
-
+
if (r != bfd_reloc_ok)
{
const char *name;
-
+
if (h != NULL)
name = h->root.root.string;
else
if (*name == '\0')
name = bfd_section_name (input_bfd, sec);
}
-
+
if (r == bfd_reloc_overflow)
{
-
+
if (! ((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
}
}
}
-
+
return true;
}
Elf_Internal_Sym *sym;
{
struct elf_s390_link_hash_table *htab;
-
+
htab = elf_s390_hash_table (info);
-
+
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma plt_index;
Elf_Internal_Rela rela;
Elf32_External_Rela *loc;
bfd_vma relative_offset;
-
+
/* This symbol has an entry in the procedure linkage table. Set
it up. */
-
+
if (h->dynindx == -1
|| htab->splt == NULL
|| htab->sgotplt == NULL
rela.r_addend = 0;
loc = (Elf32_External_Rela *) htab->srelplt->contents + plt_index;
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
-
+
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value alone. This is a clue
for the dynamic linker, to make function pointer
comparisons work between an application and shared
- library. */
+ library. */
sym->st_shndx = SHN_UNDEF;
}
}
-
+
if (h->got.offset != (bfd_vma) -1)
{
Elf_Internal_Rela rela;
{
Elf_Internal_Dyn dyn;
asection *s;
-
+
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
+
switch (dyn.d_tag)
{
default:
continue;
-
+
case DT_PLTGOT:
dyn.d_un.d_ptr = htab->sgot->output_section->vma;
break;
-
+
case DT_JMPREL:
dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
break;
case R_SH_DIR32:
case R_SH_REL32:
if (info->shared
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0
&& (r_type != R_SH_REL32
|| (h != NULL
case R_SPARC_LO10:
case R_SPARC_UA16:
case R_SPARC_UA32:
- if (info->shared && (input_section->flags & SEC_ALLOC))
+ if (info->shared
+ && r_symndx != 0
+ && (input_section->flags & SEC_ALLOC))
{
Elf_Internal_Rela outrel;
boolean skip;
outrel.r_addend = addend;
addend = 0, relocation = 0;
}
- else if (info->shared && (input_section->flags & SEC_ALLOC))
+ else if (info->shared
+ && r_symndx != 0
+ && (input_section->flags & SEC_ALLOC))
{
outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
outrel.r_addend = relocation + addend;
asection *sdynbss;
asection *srelbss;
asection *sglink;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Get the ppc64 ELF linker hash table from a link_info structure. */
htab->sdynbss = NULL;
htab->srelbss = NULL;
htab->sglink = NULL;
+ htab->sym_sec.abfd = NULL;
return &htab->elf.root;
}
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct ppc_dyn_relocs *p;
+ struct ppc_dyn_relocs **head;
+
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
this reloc. */
relocations we need for this symbol. */
if (h != NULL)
{
- struct ppc_link_hash_entry *eh;
- struct ppc_dyn_relocs *p;
-
- eh = (struct ppc_link_hash_entry *) h;
- p = eh->dyn_relocs;
-
- if (p == NULL || p->sec != sec)
- {
- p = ((struct ppc_dyn_relocs *)
- bfd_alloc (htab->elf.dynobj,
- (bfd_size_type) sizeof *p));
- if (p == NULL)
- return false;
- p->next = eh->dyn_relocs;
- eh->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- if (!IS_ABSOLUTE_RELOC (r_type))
- p->pc_count += 1;
+ head = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
}
else
{
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
+
+ head = ((struct ppc_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
}
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ p = ((struct ppc_dyn_relocs *)
+ bfd_alloc (htab->elf.dynobj,
+ (bfd_size_type) sizeof *p));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
+ }
+
+ p->count += 1;
+ if (!IS_ABSOLUTE_RELOC (r_type))
+ p->pc_count += 1;
}
break;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
+ elf_section_data (sec)->local_dynrel = NULL;
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf64_link_record_dynamic_symbol (info, h))
return false;
}
eh->dyn_relocs = NULL;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct ppc_dyn_relocs *p;
- if (count != 0)
+ for (p = *((struct ppc_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srel = elf_section_data (s)->sreloc;
- srel->_raw_size += count * sizeof (Elf64_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srel = elf_section_data (p->sec)->sreloc;
+ srel->_raw_size += p->count * sizeof (Elf64_External_Rela);
+ }
}
}
case R_PPC64_UADDR32:
case R_PPC64_UADDR64:
case R_PPC64_TOC:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& (IS_ABSOLUTE_RELOC (r_type)
|| (h != NULL
&& h->dynindx != -1
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Get the s390 ELF linker hash table from a link_info structure. */
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
if (local_got_refcounts == NULL)
{
bfd_size_type size;
-
+
size = symtab_hdr->sh_info;
size *= sizeof (bfd_signed_vma);
local_got_refcounts = ((bfd_signed_vma *)
return false;
}
break;
-
+
case R_390_PLT16DBL:
case R_390_PLT32:
case R_390_PLT32DBL:
never referenced by a dynamic object, in which case we
don't need to generate a procedure linkage table entry
after all. */
-
+
/* If this is a local symbol, we resolve it directly without
creating a procedure linkage table entry. */
if (h == NULL)
continue;
-
+
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
h->plt.refcount += 1;
break;
-
+
case R_390_8:
case R_390_16:
case R_390_32:
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
+
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
}
-
+
/* If we are creating a shared library, and this is a reloc
against a global symbol, or a non PC relative reloc
against a local symbol, then we need to copy the reloc
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf_s390_dyn_relocs *p;
+ struct elf_s390_dyn_relocs **head;
+
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
this reloc. */
{
const char *name;
bfd *dynobj;
-
+
name = (bfd_elf_string_from_elf_section
(abfd,
elf_elfheader (abfd)->e_shstrndx,
elf_section_data (sec)->rel_hdr.sh_name));
if (name == NULL)
return false;
-
+
if (strncmp (name, ".rela", 5) != 0
|| strcmp (bfd_get_section_name (abfd, sec),
name + 5) != 0)
(_("%s: bad relocation section name `%s\'"),
bfd_archive_filename (abfd), name);
}
-
+
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
if (sreloc == NULL)
{
flagword flags;
-
+
sreloc = bfd_make_section (dynobj, name);
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
}
elf_section_data (sec)->sreloc = sreloc;
}
-
+
/* If this is a global symbol, we count the number of
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf_s390_link_hash_entry *eh;
- struct elf_s390_dyn_relocs *p;
-
- eh = (struct elf_s390_link_hash_entry *) h;
- p = eh->dyn_relocs;
-
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof *p;
- p = ((struct elf_s390_dyn_relocs *)
- bfd_alloc (htab->elf.dynobj, amt));
- if (p == NULL)
- return false;
- p->next = eh->dyn_relocs;
- eh->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- if (ELF64_R_TYPE (rel->r_info) == R_390_PC16
- || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
- || ELF64_R_TYPE (rel->r_info) == R_390_PC32
- || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL
- || ELF64_R_TYPE (rel->r_info) == R_390_PC64)
- p->pc_count += 1;
+ head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs;
}
else
{
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
+
+ head = ((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ bfd_size_type amt = sizeof *p;
+ p = ((struct elf_s390_dyn_relocs *)
+ bfd_alloc (htab->elf.dynobj, amt));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
+ p->pc_count = 0;
}
+
+ p->count += 1;
+ if (ELF64_R_TYPE (rel->r_info) == R_390_PC16
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC32
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL
+ || ELF64_R_TYPE (rel->r_info) == R_390_PC64)
+ p->pc_count += 1;
}
break;
-
+
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_390_GNU_VTINHERIT:
if (!_bfd_elf64_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_390_GNU_VTENTRY:
if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return false;
break;
-
+
default:
break;
}
const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
- bfd *dynobj;
- elf_section_data (sec)->local_dynrel = 0;
-
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- return true;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
h->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
}
-
+
/* Make room for this entry. */
s->_raw_size += PLT_ENTRY_SIZE;
-
+
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
htab->sgotplt->_raw_size += GOT_ENTRY_SIZE;
eh->dyn_relocs = NULL;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf_s390_dyn_relocs *p;
- if (count != 0)
+ for (p = *((struct elf_s390_dyn_relocs **)
+ &elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srela = elf_section_data (s)->sreloc;
- srela->_raw_size += count * sizeof (Elf64_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srela = elf_section_data (p->sec)->sreloc;
+ srela->_raw_size += p->count * sizeof (Elf64_External_Rela);
+ }
}
}
{
if (s->_raw_size != 0 && s != htab->srelplt)
relocs = true;
-
+
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
s->reloc_count = 0;
|| !add_dynamic_entry (DT_RELASZ, 0)
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
return false;
-
+
/* If any dynamic relocs apply to a read-only section,
then we need a DT_TEXTREL entry. */
elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info);
-
+
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
case R_390_PC32:
case R_390_PC32DBL:
case R_390_PC64:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_390_PC16
&& r_type != R_390_PC16DBL
&& r_type != R_390_PC32
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
if (r != bfd_reloc_ok)
{
const char *name;
-
+
if (h != NULL)
name = h->root.root.string;
else
if (*name == '\0')
name = bfd_section_name (input_bfd, sec);
}
-
+
if (r == bfd_reloc_overflow)
{
-
+
if (! ((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
{
Elf_Internal_Dyn dyn;
asection *s;
-
+
bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
-
+
switch (dyn.d_tag)
{
default:
continue;
-
+
case DT_PLTGOT:
dyn.d_un.d_ptr = htab->sgot->output_section->vma;
break;
-
+
case DT_JMPREL:
dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
break;
-
+
case DT_PLTRELSZ:
s = htab->srelplt->output_section;
if (s->_cooked_size != 0)
else
dyn.d_un.d_val = s->_raw_size;
break;
-
+
case DT_RELASZ:
/* The procedure linkage table relocs (DT_JMPREL) should
not be included in the overall relocs (DT_RELA).
/* When generating a shared object, these relocations are copied
into the output file to be resolved at run time. */
- if (info->shared && (input_section->flags & SEC_ALLOC))
+ if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
{
switch (r_type)
{
case R_X86_64_64:
/* FIXME: The ABI says the linker should make sure the value is
the same when it's zeroextended to 64 bit. */
- if (info->shared && (input_section->flags & SEC_ALLOC) != 0)
+ if (info->shared
+ && r_symndx != 0
+ && (input_section->flags & SEC_ALLOC) != 0)
{
Elf_Internal_Rela outrel;
boolean skip, relocate;
&& o->reloc_count > 0)
return false;
- {
- Elf_Internal_Rela *rel, *relend;
- /* Run through the relocs looking for any against symbols
- from discarded sections and section symbols from
- removed link-once sections. Complain about relocs
- against discarded sections. Zero relocs against removed
- link-once sections. We should really complain if
- anything in the final link tries to use it, but
- DWARF-based exception handling might have an entry in
- .eh_frame to describe a routine in the linkonce section,
- and it turns out to be hard to remove the .eh_frame
- entry too. FIXME. */
- rel = internal_relocs;
- relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
- for ( ; rel < relend; rel++)
- {
- unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+ /* Run through the relocs looking for any against symbols
+ from discarded sections and section symbols from
+ removed link-once sections. Complain about relocs
+ against discarded sections. Zero relocs against removed
+ link-once sections. We should really complain if
+ anything in the final link tries to use it, but
+ DWARF-based exception handling might have an entry in
+ .eh_frame to describe a routine in the linkonce section,
+ and it turns out to be hard to remove the .eh_frame
+ entry too. FIXME. */
+ if (!finfo->info->relocateable)
+ {
+ Elf_Internal_Rela *rel, *relend;
- if (r_symndx >= locsymcount
- || (elf_bad_symtab (input_bfd)
- && finfo->sections[r_symndx] == NULL))
- {
- struct elf_link_hash_entry *h;
-
- h = sym_hashes[r_symndx - extsymoff];
- 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;
-
- /* Complain if the definition comes from a
- discarded section. */
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && ! bfd_is_abs_section (h->root.u.def.section)
- && bfd_is_abs_section (h->root.u.def.section
- ->output_section))
- {
+ rel = internal_relocs;
+ relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ for ( ; rel < relend; rel++)
+ {
+ unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
+ {
+ struct elf_link_hash_entry *h;
+
+ h = sym_hashes[r_symndx - extsymoff];
+ 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;
+
+ /* Complain if the definition comes from a
+ discarded section. */
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h->root.u.def.section)
+ && bfd_is_abs_section (h->root.u.def.section
+ ->output_section))
+ {
#if BFD_VERSION_DATE < 20031005
- if ((o->flags & SEC_DEBUGGING) != 0)
- {
+ if ((o->flags & SEC_DEBUGGING) != 0)
+ {
#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section; zeroing"),
- NULL, input_bfd, o, rel->r_offset);
+ (*finfo->info->callbacks->warning)
+ (finfo->info,
+ _("warning: relocation against removed section; zeroing"),
+ NULL, input_bfd, o, rel->r_offset);
#endif
memset (rel, 0, sizeof (*rel));
- }
- else
+ }
+ else
#endif
- {
- if (! ((*finfo->info->callbacks->undefined_symbol)
- (finfo->info, h->root.root.string,
- input_bfd, o, rel->r_offset,
- true)))
- return false;
- }
- }
- }
- else
- {
- isym = finfo->internal_syms + r_symndx;
- if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
- {
- asection *sec = finfo->sections[r_symndx];
+ {
+ if (! ((*finfo->info->callbacks->undefined_symbol)
+ (finfo->info, h->root.root.string,
+ input_bfd, o, rel->r_offset,
+ true)))
+ return false;
+ }
+ }
+ }
+ else
+ {
+ isym = finfo->internal_syms + r_symndx;
+ if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ {
+ asection *sec = finfo->sections[r_symndx];
- if (sec != NULL
- && ! bfd_is_abs_section (sec)
- && bfd_is_abs_section (sec->output_section))
- {
+ if (sec != NULL
+ && ! bfd_is_abs_section (sec)
+ && bfd_is_abs_section (sec->output_section))
+ {
#if BFD_VERSION_DATE < 20031005
- if ((o->flags & SEC_DEBUGGING) != 0
- || (sec->flags & SEC_LINK_ONCE) != 0)
- {
+ if ((o->flags & SEC_DEBUGGING) != 0
+ || (sec->flags & SEC_LINK_ONCE) != 0)
+ {
#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section"),
- NULL, input_bfd, o, rel->r_offset);
+ (*finfo->info->callbacks->warning)
+ (finfo->info,
+ _("warning: relocation against removed section"),
+ NULL, input_bfd, o, rel->r_offset);
#endif
- memset (rel, 0, sizeof (*rel));
- }
- else
+ rel->r_info
+ = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
+ rel->r_addend = 0;
+ }
+ else
#endif
- {
- boolean ok;
- const char *msg
- = _("local symbols in discarded section %s");
- bfd_size_type amt
- = strlen (sec->name) + strlen (msg) - 1;
- char *buf = (char *) bfd_malloc (amt);
-
- if (buf != NULL)
- sprintf (buf, msg, sec->name);
- else
- buf = (char *) sec->name;
- ok = (*finfo->info->callbacks
- ->undefined_symbol) (finfo->info, buf,
- input_bfd, o,
- rel->r_offset,
- true);
- if (buf != sec->name)
- free (buf);
- if (!ok)
- return false;
- }
- }
- }
- }
- }
- }
+ {
+ boolean ok;
+ const char *msg
+ = _("local symbols in discarded section %s");
+ bfd_size_type amt
+ = strlen (sec->name) + strlen (msg) - 1;
+ char *buf = (char *) bfd_malloc (amt);
+
+ if (buf != NULL)
+ sprintf (buf, msg, sec->name);
+ else
+ buf = (char *) sec->name;
+ ok = (*finfo->info->callbacks
+ ->undefined_symbol) (finfo->info, buf,
+ input_bfd, o,
+ rel->r_offset,
+ true);
+ if (buf != sec->name)
+ free (buf);
+ if (!ok)
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
/* Relocate the section by invoking a back end routine.
/* Don't emit relocs for __GLOB_DATA_PTR on AIX. */
&& (!h || strcmp (h->root.root.string,
"__GLOB_DATA_PTR") != 0)))
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0)
{
unsigned int dyn_r_type;
case R_IA64_PCREL64MSB:
case R_IA64_PCREL64LSB:
/* Install a dynamic relocation for this reloc. */
- if (dynamic_symbol_p
- || elfNN_ia64_aix_vec (info->hash->creator))
+ if ((dynamic_symbol_p
+ || elfNN_ia64_aix_vec (info->hash->creator))
+ && r_symndx != 0)
{
BFD_ASSERT (srel != NULL);