aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog52
-rw-r--r--bfd/elf-bfd.h23
-rw-r--r--bfd/elf-m10300.c2
-rw-r--r--bfd/elf32-arm.c28
-rw-r--r--bfd/elf32-cris.c19
-rw-r--r--bfd/elf32-hppa.c18
-rw-r--r--bfd/elf32-i370.c15
-rw-r--r--bfd/elf32-i386.c2
-rw-r--r--bfd/elf32-m32r.c2
-rw-r--r--bfd/elf32-m68k.c19
-rw-r--r--bfd/elf32-mips.c1
-rw-r--r--bfd/elf32-ppc.c10
-rw-r--r--bfd/elf32-s390.c9
-rw-r--r--bfd/elf32-sh.c2
-rw-r--r--bfd/elf32-sparc.c1
-rw-r--r--bfd/elf32-vax.c15
-rw-r--r--bfd/elf32-xstormy16.c2
-rw-r--r--bfd/elf32-xtensa.c2
-rw-r--r--bfd/elf64-alpha.c2
-rw-r--r--bfd/elf64-hppa.c2
-rw-r--r--bfd/elf64-mips.c1
-rw-r--r--bfd/elf64-mmix.c2
-rw-r--r--bfd/elf64-ppc.c12
-rw-r--r--bfd/elf64-s390.c10
-rw-r--r--bfd/elf64-sh64.c2
-rw-r--r--bfd/elf64-sparc.c2
-rw-r--r--bfd/elf64-x86-64.c13
-rw-r--r--bfd/elflink.c86
-rw-r--r--bfd/elfn32-mips.c1
-rw-r--r--bfd/elfxx-ia64.c2
-rw-r--r--bfd/elfxx-mips.c5
-rw-r--r--bfd/elfxx-sparc.c17
-rw-r--r--bfd/elfxx-target.h5
-rw-r--r--bfd/linker.c23
34 files changed, 369 insertions, 38 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index eba1f15..03cff6c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,55 @@
+2006-10-17 Alan Modra <amodra@bigpond.net.au>
+
+ * elf-bfd.h (struct elf_link_hash_table): Reorder. Add
+ text_index_section and data_index_section.
+ (struct elf_backend_data): Add elf_backend_init_index_section.
+ (_bfd_elf_init_1_index_section): Declare.
+ (_bfd_elf_init_2_index_sections): Declare.
+ * elfxx-target.h (elf_backend_init_index_section): Define.
+ (elfNN_bed): Init new field.
+ * elflink.c (_bfd_elf_link_omit_section_dynsym): Keep first tls
+ section and text_index_section plus data_index_section.
+ (_bfd_elf_link_renumber_dynsyms): Clear dynindx on omitted sections.
+ (_bfd_elf_init_1_index_section): New function.
+ (_bfd_elf_init_2_index_sections): New function.
+ (bfd_elf_size_dynsym_hash_dynstr): Call elf_backend_init_index_section.
+ (elf_link_input_bfd): When emitting relocs, use text_index_section
+ and data_index_section for removed sections.
+ * elf-m10300.c (elf_backend_omit_section_dynsym): Define.
+ * elf32-i386.c: Likewise.
+ * elf32-m32r.c: Likewise.
+ * elf32-sh.c: Likewise.
+ * elf32-xstormy16.c: Likewise.
+ * elf32-xtensa.c: Likewise.
+ * elf64-alpha.c: Likewise.
+ * elf64-hppa.c: Likewise.
+ * elf64-mmix.c: Likewise.
+ * elf64-sh64.c: Likewise.
+ * elfxx-ia64.c: Likewise.
+ * elf32-arm.c (elf32_arm_final_link_relocate): Use text_index_section
+ and data_index_section sym for relocs against sections with no dynamic
+ section sym.
+ (elf_backend_init_index_section): Define.
+ * elf32-cris.c: Similarly.
+ * elf32-hppa.c: Similarly.
+ * elf32-i370.c: Similarly.
+ * elf32-m68k.c: Similarly.
+ * elf32-mips.c: Similarly.
+ * elf32-ppc.c: Similarly.
+ * elf32-s390.c: Similarly.
+ * elf32-sparc.c: Similarly.
+ * elf32-vax.c: Similarly.
+ * elf64-mips.c: Similarly.
+ * elf64-ppc.c: Similarly.
+ * elf64-s390.c: Similarly.
+ * elf64-sparc.c: Similarly.
+ * elf64-x86-64.c: Similarly.
+ * elfn32-mips.c: Similarly.
+ * elfxx-mips.c: Similarly.
+ * elfxx-sparc.c: Similarly.
+ * linker.c (fix_syms): Base symbols in removed sections on
+ previous section in preference to using absolute section.
+
2006-10-16 Andreas Schwab <schwab@suse.de>
* elfxx-ia64.c (addend_compare): Properly compute return value.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 1e541da..bb86c4e 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -345,6 +345,10 @@ struct elf_link_hash_table
when linking against or generating a shared object. */
bfd_boolean dynamic_sections_created;
+ /* True if this target has relocatable executables, so needs dynamic
+ section symbols. */
+ bfd_boolean is_relocatable_executable;
+
/* The BFD used to hold special sections created by the linker.
This will be the first BFD found which requires these sections to
be created. */
@@ -378,6 +382,12 @@ struct elf_link_hash_table
included in the link. */
struct bfd_link_needed_list *needed;
+ /* Sections in the output bfd that provides a section symbol
+ to be used by relocations emitted against local symbols.
+ Most targets will not use data_index_section. */
+ asection *text_index_section;
+ asection *data_index_section;
+
/* The _GLOBAL_OFFSET_TABLE_ symbol. */
struct elf_link_hash_entry *hgot;
@@ -406,10 +416,6 @@ struct elf_link_hash_table
/* A linked list of BFD's loaded in the link. */
struct elf_link_loaded_list *loaded;
-
- /* True if this target has relocatable executables, so needs dynamic
- section symbols. */
- bfd_boolean is_relocatable_executable;
};
/* Look up an entry in an ELF linker hash table. */
@@ -766,6 +772,11 @@ struct elf_backend_data
bfd_boolean (*elf_backend_size_dynamic_sections)
(bfd *output_bfd, struct bfd_link_info *info);
+ /* Set TEXT_INDEX_SECTION and DATA_INDEX_SECTION, the output sections
+ we keep to use as a base for relocs and symbols. */
+ void (*elf_backend_init_index_section)
+ (bfd *output_bfd, struct bfd_link_info *info);
+
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
@@ -1697,6 +1708,10 @@ extern bfd_boolean _bfd_elf_create_got_section
(bfd *, struct bfd_link_info *);
extern struct elf_link_hash_entry *_bfd_elf_define_linkage_sym
(bfd *, struct bfd_link_info *, asection *, const char *);
+extern void _bfd_elf_init_1_index_section
+ (bfd *, struct bfd_link_info *);
+extern void _bfd_elf_init_2_index_sections
+ (bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_elfcore_make_pseudosection
(bfd *, char *, size_t, ufile_ptr);
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 423ec52..7a72925 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -4756,6 +4756,8 @@ _bfd_mn10300_elf_reloc_type_class (const Elf_Internal_Rela *rela)
_bfd_mn10300_elf_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
_bfd_mn10300_elf_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_symbol \
_bfd_mn10300_elf_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index bdbdd6a..f4342b6 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3731,6 +3731,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value |= 1;
if (globals->symbian_p)
{
+ asection *osec;
+
/* On Symbian OS, the data segment and text segement
can be relocated independently. Therefore, we
must indicate the segment to which this
@@ -3738,11 +3740,27 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
use any symbol in the right segment; we just use
the section symbol as it is convenient. (We
cannot use the symbol given by "h" directly as it
- will not appear in the dynamic symbol table.) */
+ will not appear in the dynamic symbol table.)
+
+ Note that the dynamic linker ignores the section
+ symbol value, so we don't subtract osec->vma
+ from the emitted reloc addend. */
if (sym_sec)
- symbol = elf_section_data (sym_sec->output_section)->dynindx;
+ osec = sym_sec->output_section;
else
- symbol = elf_section_data (input_section->output_section)->dynindx;
+ osec = input_section->output_section;
+ symbol = elf_section_data (osec)->dynindx;
+ if (symbol == 0)
+ {
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ if ((osec->flags & SEC_READONLY) == 0
+ && htab->data_index_section != NULL)
+ osec = htab->data_index_section;
+ else
+ osec = htab->text_index_section;
+ symbol = elf_section_data (osec)->dynindx;
+ }
BFD_ASSERT (symbol != 0);
}
else
@@ -8551,7 +8569,8 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
/* UnixWare sets the entsize of .plt to 4, although that doesn't
really seem like the right value. */
- elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+ if (splt->output_section->owner == output_bfd)
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
if (htab->vxworks_p && !info->shared && htab->splt->size > 0)
{
@@ -9494,6 +9513,7 @@ const struct elf_size_info elf32_arm_size_info = {
#define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections
#define elf_backend_link_output_symbol_hook elf32_arm_output_symbol_hook
#define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_2_index_sections
#define elf_backend_post_process_headers elf32_arm_post_process_headers
#define elf_backend_reloc_type_class elf32_arm_reloc_type_class
#define elf_backend_object_p elf32_arm_object_p
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c
index 66c8219..199ee1b 100644
--- a/bfd/elf32-cris.c
+++ b/bfd/elf32-cris.c
@@ -1430,11 +1430,12 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
+ outrel.r_addend = relocation + rel->r_addend;
+
if (r_type == R_CRIS_32)
{
relocate = TRUE;
outrel.r_info = ELF32_R_INFO (0, R_CRIS_RELATIVE);
- outrel.r_addend = relocation + rel->r_addend;
}
else
{
@@ -1451,13 +1452,24 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (indx > 0);
+ if (indx == 0)
+ {
+ struct elf_cris_link_hash_table *htab;
+ htab = elf_cris_hash_table (info);
+ osec = htab->root.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
}
}
@@ -3390,6 +3402,7 @@ elf_cris_reloc_type_class (rela)
elf_cris_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elf_cris_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_finish_dynamic_symbol \
elf_cris_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 0a8b3b1..db6e842 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -4024,17 +4024,22 @@ elf32_hppa_relocate_section (bfd *output_bfd,
&& sym_sec->output_section != NULL
&& ! bfd_is_abs_section (sym_sec))
{
- /* Skip this relocation if the output section has
- been discarded. */
- if (bfd_is_abs_section (sym_sec->output_section))
- break;
+ asection *osec;
+
+ osec = sym_sec->output_section;
+ indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ osec = htab->etab.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
- indx = elf_section_data (sym_sec->output_section)->dynindx;
/* We are turning this relocation into one
against a section symbol, so subtract out the
output section's address but not the offset
of the input section in the output section. */
- outrel.r_addend -= sym_sec->output_section->vma;
+ outrel.r_addend -= osec->vma;
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
@@ -4642,6 +4647,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
#define elf_backend_finish_dynamic_symbol elf32_hppa_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections elf32_hppa_finish_dynamic_sections
#define elf_backend_size_dynamic_sections elf32_hppa_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_gc_mark_hook elf32_hppa_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_hppa_gc_sweep_hook
#define elf_backend_grok_prstatus elf32_hppa_grok_prstatus
diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c
index 3c7c372..4930581 100644
--- a/bfd/elf32-i370.c
+++ b/bfd/elf32-i370.c
@@ -1290,9 +1290,21 @@ i370_elf_relocate_section (bfd *output_bfd,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT(indx > 0);
+ if (indx == 0)
+ {
+ struct elf_link_hash_table *htab;
+ htab = elf_hash_table (info);
+ osec = htab->text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
#ifdef DEBUG
if (indx <= 0)
{
@@ -1427,6 +1439,7 @@ i370_elf_post_process_headers (bfd * abfd,
link glibc's ld.so without errors. */
#define elf_backend_create_dynamic_sections i370_elf_create_dynamic_sections
#define elf_backend_size_dynamic_sections i370_elf_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_finish_dynamic_sections i370_elf_finish_dynamic_sections
#define elf_backend_fake_sections i370_elf_fake_sections
#define elf_backend_section_from_shdr i370_elf_section_from_shdr
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 227bc9e..97054a5 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -3872,6 +3872,8 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
#define elf_backend_always_size_sections elf_i386_always_size_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#define elf_backend_hash_symbol elf_i386_hash_symbol
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c
index 7456c1c..30674f3 100644
--- a/bfd/elf32-m32r.c
+++ b/bfd/elf32-m32r.c
@@ -4141,6 +4141,8 @@ m32r_elf_reloc_type_class (const Elf_Internal_Rela *rela)
#define elf_backend_create_dynamic_sections m32r_elf_create_dynamic_sections
#define bfd_elf32_bfd_link_hash_table_create m32r_elf_link_hash_table_create
#define elf_backend_size_dynamic_sections m32r_elf_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_sections m32r_elf_finish_dynamic_sections
#define elf_backend_adjust_dynamic_symbol m32r_elf_adjust_dynamic_symbol
#define elf_backend_finish_dynamic_symbol m32r_elf_finish_dynamic_symbol
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 50b962d..81d219d 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -1833,11 +1833,12 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
else
{
/* This symbol is local, or marked to become local. */
+ outrel.r_addend = relocation + rel->r_addend;
+
if (r_type == R_68K_32)
{
relocate = TRUE;
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
- outrel.r_addend = relocation + rel->r_addend;
}
else
{
@@ -1854,13 +1855,24 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (indx > 0);
+ if (indx == 0)
+ {
+ struct elf_link_hash_table *htab;
+ htab = elf_hash_table (info);
+ osec = htab->text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
}
}
@@ -2418,6 +2430,7 @@ elf_m68k_plt_sym_val (bfd_vma i, const asection *plt,
elf_m68k_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elf_m68k_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section elf_m68k_relocate_section
#define elf_backend_finish_dynamic_symbol \
elf_m68k_finish_dynamic_symbol
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 1a293a0..c5e7dd4 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -1513,6 +1513,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
_bfd_mips_elf_always_size_sections
#define elf_backend_size_dynamic_sections \
_bfd_mips_elf_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section _bfd_mips_elf_relocate_section
#define elf_backend_finish_dynamic_symbol \
_bfd_mips_elf_finish_dynamic_symbol
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 7b3e722..59bac50 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6280,9 +6280,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (indx > 0);
+ if (indx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
#ifdef DEBUG
- if (indx <= 0)
+ if (indx == 0)
printf ("indx=%ld section=%s flags=%08x name=%s\n",
indx, osec->name, osec->flags,
h->root.root.string);
@@ -7472,6 +7477,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
#define elf_backend_get_sec_type_attr ppc_elf_get_sec_type_attr
#define elf_backend_plt_sym_val ppc_elf_plt_sym_val
#define elf_backend_action_discarded ppc_elf_action_discarded
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#include "elf32-target.h"
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 287e683..83bf5e1 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -2630,14 +2630,18 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
osec = sec->output_section;
sindx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (sindx > 0);
+ if (sindx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ sindx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (sindx != 0);
/* We are turning this relocation into one
against a section symbol, so subtract out
the output section's address but not the
offset of the input section in the output
section. */
-
outrel.r_addend -= osec->vma;
}
outrel.r_info = ELF32_R_INFO (sindx, r_type);
@@ -3542,6 +3546,7 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_relocate_section elf_s390_relocate_section
#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_grok_prstatus elf_s390_grok_prstatus
#define elf_backend_plt_sym_val elf_s390_plt_sym_val
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index 02093cf..85f3d8f 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -6028,6 +6028,8 @@ sh_elf_plt_sym_val (bfd_vma i, const asection *plt,
sh_elf_always_size_sections
#define elf_backend_size_dynamic_sections \
sh_elf_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_symbol \
sh_elf_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 3f0c7d6..5f13b96 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -207,6 +207,7 @@ elf32_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
#define elf_backend_gc_mark_hook _bfd_sparc_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook _bfd_sparc_elf_gc_sweep_hook
#define elf_backend_plt_sym_val _bfd_sparc_elf_plt_sym_val
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c
index fe8ea03..2572b68 100644
--- a/bfd/elf32-vax.c
+++ b/bfd/elf32-vax.c
@@ -1680,9 +1680,21 @@ elf_vax_relocate_section (bfd *output_bfd,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (indx > 0);
+ if (indx == 0)
+ {
+ struct elf_link_hash_table *htab;
+ htab = elf_hash_table (info);
+ osec = htab->text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
@@ -2062,6 +2074,7 @@ elf_vax_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
elf_vax_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elf_vax_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section elf_vax_relocate_section
#define elf_backend_finish_dynamic_symbol \
elf_vax_finish_dynamic_symbol
diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c
index 818b62d..c5c88c7 100644
--- a/bfd/elf32-xstormy16.c
+++ b/bfd/elf32-xstormy16.c
@@ -999,6 +999,8 @@ xstormy16_elf_gc_mark_hook (asection *sec,
#define elf_backend_check_relocs xstormy16_elf_check_relocs
#define elf_backend_always_size_sections \
xstormy16_elf_always_size_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_sections \
xstormy16_elf_finish_dynamic_sections
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 2a6c695..34f7f47 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -9844,6 +9844,8 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] =
#define elf_backend_reloc_type_class elf_xtensa_reloc_type_class
#define elf_backend_relocate_section elf_xtensa_relocate_section
#define elf_backend_size_dynamic_sections elf_xtensa_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_special_sections elf_xtensa_special_sections
#define elf_backend_action_discarded elf_xtensa_action_discarded
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index f37a317..1f7e546 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -5275,6 +5275,8 @@ static const struct elf_size_info alpha_elf_size_info =
elf64_alpha_always_size_sections
#define elf_backend_size_dynamic_sections \
elf64_alpha_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_relocate_section \
elf64_alpha_relocate_section
#define elf_backend_finish_dynamic_symbol \
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 4ff7e6a..4b5e95d 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -2820,6 +2820,8 @@ const struct elf_size_info hppa64_elf_size_info =
elf64_hppa_create_dynamic_sections
#define elf_backend_post_process_headers elf64_hppa_post_process_headers
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_adjust_dynamic_symbol \
elf64_hppa_adjust_dynamic_symbol
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index 09d13e8..408c352 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -3034,6 +3034,7 @@ const struct elf_size_info mips_elf64_size_info =
_bfd_mips_elf_always_size_sections
#define elf_backend_size_dynamic_sections \
_bfd_mips_elf_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section _bfd_mips_elf_relocate_section
#define elf_backend_finish_dynamic_symbol \
_bfd_mips_elf_finish_dynamic_symbol
diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c
index 63176eb..e18f4a1 100644
--- a/bfd/elf64-mmix.c
+++ b/bfd/elf64-mmix.c
@@ -2916,6 +2916,8 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
#define elf_backend_check_relocs mmix_elf_check_relocs
#define elf_backend_symbol_processing mmix_elf_symbol_processing
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define bfd_elf64_bfd_is_local_label_name \
mmix_elf_is_local_label_name
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index d87a1b2..fcbc71e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -97,6 +97,7 @@ static bfd_vma opd_entry_value
#define elf_backend_hide_symbol ppc64_elf_hide_symbol
#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust
#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_2_index_sections
#define elf_backend_action_discarded ppc64_elf_action_discarded
#define elf_backend_relocate_section ppc64_elf_relocate_section
#define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol
@@ -10840,6 +10841,17 @@ ppc64_elf_relocate_section (bfd *output_bfd,
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ if ((osec->flags & SEC_READONLY) == 0
+ && htab->elf.data_index_section != NULL)
+ osec = htab->elf.data_index_section;
+ else
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
+
/* We are turning this relocation into one
against a section symbol, so subtract out
the output section's address but not the
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 59151d8..1d86820 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -2611,14 +2611,19 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
osec = sec->output_section;
sindx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (sindx > 0);
+
+ if (sindx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ sindx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (sindx != 0);
/* We are turning this relocation into one
against a section symbol, so subtract out
the output section's address but not the
offset of the input section in the output
section. */
-
outrel.r_addend -= osec->vma;
}
outrel.r_info = ELF64_R_INFO (sindx, r_type);
@@ -3449,6 +3454,7 @@ const struct elf_size_info s390_elf64_size_info =
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_relocate_section elf_s390_relocate_section
#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_plt_sym_val elf_s390_plt_sym_val
diff --git a/bfd/elf64-sh64.c b/bfd/elf64-sh64.c
index e55c19a..5ebea96 100644
--- a/bfd/elf64-sh64.c
+++ b/bfd/elf64-sh64.c
@@ -4094,6 +4094,8 @@ static const struct bfd_elf_special_section sh64_elf64_special_sections[]=
sh64_elf64_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
sh64_elf64_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_finish_dynamic_symbol \
sh64_elf64_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index 5c928e2..1185553 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -889,6 +889,8 @@ const struct elf_size_info elf64_sparc_size_info =
_bfd_sparc_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook \
_bfd_sparc_elf_gc_sweep_hook
+#define elf_backend_init_index_section \
+ _bfd_elf_init_1_index_section
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 23dee16..2556fdc 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2457,9 +2457,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
sindx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (sindx > 0);
+ if (sindx == 0)
+ {
+ asection *oi = htab->elf.text_index_section;
+ sindx = elf_section_data (oi)->dynindx;
+ }
+ BFD_ASSERT (sindx != 0);
}
outrel.r_info = ELF64_R_INFO (sindx, r_type);
@@ -3657,6 +3667,7 @@ static const struct bfd_elf_special_section
#define elf_backend_relocate_section elf64_x86_64_relocate_section
#define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections
#define elf_backend_always_size_sections elf64_x86_64_always_size_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_plt_sym_val elf64_x86_64_plt_sym_val
#define elf_backend_object_p elf64_x86_64_elf_object_p
#define bfd_elf64_mkobject elf64_x86_64_mkobject
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1df583f..63cac8e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -712,6 +712,8 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info,
asection *p)
{
+ struct elf_link_hash_table *htab;
+
switch (elf_section_data (p)->this_hdr.sh_type)
{
case SHT_PROGBITS:
@@ -719,15 +721,21 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
/* If sh_type is yet undecided, assume it could be
SHT_PROGBITS/SHT_NOBITS. */
case SHT_NULL:
+ htab = elf_hash_table (info);
+ if (p == htab->tls_sec)
+ return FALSE;
+
+ if (htab->text_index_section != NULL)
+ return p != htab->text_index_section && p != htab->data_index_section;
+
if (strcmp (p->name, ".got") == 0
|| strcmp (p->name, ".got.plt") == 0
|| strcmp (p->name, ".plt") == 0)
{
asection *ip;
- bfd *dynobj = elf_hash_table (info)->dynobj;
- if (dynobj != NULL
- && (ip = bfd_get_section_by_name (dynobj, p->name)) != NULL
+ if (htab->dynobj != NULL
+ && (ip = bfd_get_section_by_name (htab->dynobj, p->name)) != NULL
&& (ip->flags & SEC_LINKER_CREATED)
&& ip->output_section == p)
return TRUE;
@@ -763,6 +771,8 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
&& (p->flags & SEC_ALLOC) != 0
&& !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
elf_section_data (p)->dynindx = ++dynsymcount;
+ else
+ elf_section_data (p)->dynindx = 0;
}
*section_sym_count = dynsymcount;
@@ -5932,16 +5942,65 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
return TRUE;
}
+/* Find the first non-excluded output section. We'll use its
+ section symbol for some emitted relocs. */
+void
+_bfd_elf_init_1_index_section (bfd *output_bfd, struct bfd_link_info *info)
+{
+ asection *s;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
+ && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ {
+ elf_hash_table (info)->text_index_section = s;
+ break;
+ }
+}
+
+/* Find two non-excluded output sections, one for code, one for data.
+ We'll use their section symbols for some emitted relocs. */
+void
+_bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
+{
+ asection *s;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
+ == (SEC_ALLOC | SEC_READONLY))
+ && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ {
+ elf_hash_table (info)->text_index_section = s;
+ break;
+ }
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
+ && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+ {
+ elf_hash_table (info)->data_index_section = s;
+ break;
+ }
+
+ if (elf_hash_table (info)->text_index_section == NULL)
+ elf_hash_table (info)->text_index_section
+ = elf_hash_table (info)->data_index_section;
+}
+
bfd_boolean
bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
{
+ const struct elf_backend_data *bed;
+
if (!is_elf_hash_table (info->hash))
return TRUE;
+ bed = get_elf_backend_data (output_bfd);
+ (*bed->elf_backend_init_index_section) (output_bfd, info);
+
if (elf_hash_table (info)->dynamic_sections_created)
{
bfd *dynobj;
- const struct elf_backend_data *bed;
asection *s;
bfd_size_type dynsymcount;
unsigned long section_sym_count;
@@ -5980,7 +6039,6 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
section as we went along in elf_link_add_object_symbols. */
s = bfd_get_section_by_name (dynobj, ".dynsym");
BFD_ASSERT (s != NULL);
- bed = get_elf_backend_data (output_bfd);
s->size = dynsymcount * bed->s->sizeof_sym;
if (dynsymcount != 0)
@@ -7769,6 +7827,24 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
if (!bfd_is_abs_section (osec))
{
r_symndx = osec->target_index;
+ if (r_symndx == 0)
+ {
+ struct elf_link_hash_table *htab;
+ asection *oi;
+
+ htab = elf_hash_table (finfo->info);
+ oi = htab->text_index_section;
+ if ((osec->flags & SEC_READONLY) == 0
+ && htab->data_index_section != NULL)
+ oi = htab->data_index_section;
+
+ if (oi != NULL)
+ {
+ irela->r_addend += osec->vma - oi->vma;
+ r_symndx = oi->target_index;
+ }
+ }
+
BFD_ASSERT (r_symndx != 0);
}
}
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index 1e42faa..21cf4af 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -2301,6 +2301,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
_bfd_mips_elf_always_size_sections
#define elf_backend_size_dynamic_sections \
_bfd_mips_elf_size_dynamic_sections
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section _bfd_mips_elf_relocate_section
#define elf_backend_finish_dynamic_symbol \
_bfd_mips_elf_finish_dynamic_symbol
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c
index 89271ea..dbea35b 100644
--- a/bfd/elfxx-ia64.c
+++ b/bfd/elfxx-ia64.c
@@ -5762,6 +5762,8 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
elfNN_ia64_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elfNN_ia64_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_relocate_section \
elfNN_ia64_relocate_section
#define elf_backend_finish_dynamic_symbol \
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 83d6258..66cdf14 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -4801,6 +4801,11 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
{
indx = elf_section_data (sec->output_section)->dynindx;
if (indx == 0)
+ {
+ asection *osec = htab->root.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ if (indx == 0)
abort ();
}
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index ccbd272..77ffbfe 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2864,6 +2864,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
{
long indx;
+ outrel.r_addend = relocation + rel->r_addend;
+
if (is_plt)
sec = htab->splt;
@@ -2878,9 +2880,20 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
{
asection *osec;
+ /* We are turning this relocation into one
+ against a section symbol. It would be
+ proper to subtract the symbol's value,
+ osec->vma, from the emitted reloc addend,
+ but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+
/* FIXME: we really should be able to link non-pic
shared libraries. */
if (indx == 0)
@@ -2894,8 +2907,8 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
}
}
- outrel.r_info = SPARC_ELF_R_INFO (htab, rel, indx, r_type);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_info = SPARC_ELF_R_INFO (htab, rel, indx,
+ r_type);
}
}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 537cc3b..9e8ceca 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -381,6 +381,10 @@
#ifndef elf_backend_size_dynamic_sections
#define elf_backend_size_dynamic_sections 0
#endif
+#ifndef elf_backend_init_index_section
+#define elf_backend_init_index_section \
+ ((void (*) (bfd *, struct bfd_link_info *)) bfd_void)
+#endif
#ifndef elf_backend_relocate_section
#define elf_backend_relocate_section 0
#endif
@@ -603,6 +607,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_adjust_dynamic_symbol,
elf_backend_always_size_sections,
elf_backend_size_dynamic_sections,
+ elf_backend_init_index_section,
elf_backend_relocate_section,
elf_backend_finish_dynamic_symbol,
elf_backend_finish_dynamic_sections,
diff --git a/bfd/linker.c b/bfd/linker.c
index ea14d76..257a585 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -3073,7 +3073,7 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec)
bfd_section_already_linked_table_insert (already_linked_list, sec);
}
-/* Convert symbols in excluded output sections to absolute. */
+/* Convert symbols in excluded output sections to use a kept section. */
static bfd_boolean
fix_syms (struct bfd_link_hash_entry *h, void *data)
@@ -3092,8 +3092,27 @@ fix_syms (struct bfd_link_hash_entry *h, void *data)
&& (s->output_section->flags & SEC_EXCLUDE) != 0
&& bfd_section_removed_from_list (obfd, s->output_section))
{
+ asection *op;
+ for (op = s->output_section->prev; op != NULL; op = op->prev)
+ if ((op->flags & SEC_EXCLUDE) == 0
+ && !bfd_section_removed_from_list (obfd, op))
+ break;
+ if (op == NULL)
+ {
+ if (s->output_section->prev != NULL)
+ op = s->output_section->prev->next;
+ else
+ op = s->output_section->owner->sections;
+ for (; op != NULL; op = op->next)
+ if ((op->flags & SEC_EXCLUDE) == 0
+ && !bfd_section_removed_from_list (obfd, op))
+ break;
+ if (op == NULL)
+ op = bfd_abs_section_ptr;
+ }
h->u.def.value += s->output_offset + s->output_section->vma;
- h->u.def.section = bfd_abs_section_ptr;
+ h->u.def.value -= op->vma;
+ h->u.def.section = op;
}
}