aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog33
-rw-r--r--bfd/elf-bfd.h49
-rw-r--r--bfd/elf32-m68k.c91
-rw-r--r--bfd/elf32-mips.c73
-rw-r--r--bfd/elf32-ppc.c108
-rw-r--r--bfd/elf32-sparc.c91
-rw-r--r--bfd/elf64-alpha.c84
-rw-r--r--bfd/elf64-sparc.c92
-rw-r--r--bfd/elfcode.h2
-rw-r--r--bfd/elflink.c79
-rw-r--r--bfd/elflink.h239
11 files changed, 306 insertions, 635 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 78787ad..e3d3275 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,36 @@
+1999-07-13 Richard Henderson <rth@cygnus.com>
+
+ * elf.c (assign_file_positions_for_segments): Don't overwrite p_flags.
+
+ * elf-bfd.h (struct elf_link_local_dynamic_entry): New.
+ (struct elf_link_hash_table): Add dynlocal.
+ (_bfd_elf_link_lookup_local_dynindx): Prototype.
+ (_bfd_elf_link_adjust_dynindx): Delete.
+ (_bfd_elf_link_renumber_dynsyms): Prototype.
+ (_bfd_elf,link_record_local_dynamic_symbol): Prototype.
+ * elfcode.h (elf_link_record_local_dynamic_symbol): New alias.
+ * elflink.c (_bfd_elf_link_adjust_dynindx): Delete.
+ (_bfd_elf_link_lookup_local_dynindx): New function.
+ (elf_link_renumber_hash_table_dynsyms): New function.
+ (_bfd_elf_link_renumber_dynsyms): New function.
+ * elflink.h (elf_link_record_local_dynamic_symbol): New function.
+ (struct elf_assign_sym_version_info): Delete removed_dynamic.
+ (bfd_elf,size_dynamic_sections): Use _bfd_strip_section_from_output
+ instead of elf_link_remove_section_and_adjust_dynindices.
+ Remove removed_dynamic code. Use _bfd_elf_link_renumber_dynsyms.
+ (elf_link_assign_sym_version): Remove removed_dynamic code.
+ (elf_link_renumber_dynsyms): Delete.
+ (elf_bfd_final_link): Install section and local symbols into .dynsym.
+
+ * elf32-m68k.c (elf_m68k_adjust_dynindx): Delete.
+ (elf_m68k_size_dynamic_sections): Don't set section dynindicies.
+ (elf_m68k_finish_dynamic_sections): Don't write section dynsyms.
+ * elf32-mips.c: Similarly.
+ * elf32-ppc.c: Similarly.
+ * elf32-sparc.c: Similarly.
+ * elf64-alpha.c: Similarly.
+ * elf64-sparc.c: Similarly.
+
1999-07-13 Mark Mitchell <mark@codesourcery.com>
* elf32-mips.c (mips_elf_calculate_relocation): Do not complain
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index be6185b..6c20b06 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -86,6 +86,16 @@ struct elf_link_hash_entry
/* Symbol index as a dynamic symbol. Initialized to -1, and remains
-1 if this is not a dynamic symbol. */
+ /* ??? Note that this is consistently used as a synonym for tests
+ against whether we can perform various simplifying transformations
+ to the code. (E.g. changing a pc-relative jump to a PLT entry
+ into a pc-relative jump to the target function.) That test, which
+ is often relatively complex, and someplaces wrong or incomplete,
+ should really be replaced by a predicate in elflink.c.
+
+ End result: this field -1 does not indicate that the symbol is
+ not in the dynamic symbol table, but rather that the symbol is
+ not visible outside this DSO. */
long dynindx;
/* String table index in .dynstr if this is a dynamic symbol. */
@@ -181,6 +191,25 @@ struct elf_link_hash_entry
#define ELF_LINK_HASH_MARK 04000
};
+/* Records local symbols to be emitted in the dynamic symbol table. */
+
+struct elf_link_local_dynamic_entry
+{
+ struct elf_link_local_dynamic_entry *next;
+
+ /* The input bfd this symbol came from. */
+ bfd *input_bfd;
+
+ /* The index of the local symbol being copied. */
+ long input_indx;
+
+ /* The index in the outgoing dynamic symbol table. */
+ long dynindx;
+
+ /* A copy of the input symbol. */
+ Elf_Internal_Sym isym;
+};
+
/* ELF linker hash table. */
struct elf_link_hash_table
@@ -209,6 +238,8 @@ struct elf_link_hash_table
struct elf_link_hash_entry *hgot;
/* A pointer to information used to link stabs in sections. */
PTR stab_info;
+ /* A linked list of local symbols to be added to .dynsym. */
+ struct elf_link_local_dynamic_entry *dynlocal;
};
/* Look up an entry in an ELF linker hash table. */
@@ -956,6 +987,9 @@ struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
boolean
_bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *,
struct elf_link_hash_entry *));
+long
+_bfd_elf_link_lookup_local_dynindx PARAMS ((struct bfd_link_info *,
+ bfd *, long));
boolean
_bfd_elf_compute_section_file_positions PARAMS ((bfd *,
struct bfd_link_info *));
@@ -970,8 +1004,8 @@ boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *,
struct bfd_link_info *));
boolean _bfd_elf_create_got_section PARAMS ((bfd *,
struct bfd_link_info *));
-boolean _bfd_elf_link_adjust_dynindx PARAMS ((struct elf_link_hash_entry *,
- PTR));
+unsigned long _bfd_elf_link_renumber_dynsyms PARAMS ((bfd *,
+ struct bfd_link_info *));
elf_linker_section_t *_bfd_elf_create_linker_section
PARAMS ((bfd *abfd,
@@ -1113,8 +1147,15 @@ extern boolean bfd_elf64_link_create_dynamic_sections
extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs
PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
-#define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
-#define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+#define bfd_elf32_link_record_dynamic_symbol \
+ _bfd_elf_link_record_dynamic_symbol
+#define bfd_elf64_link_record_dynamic_symbol \
+ _bfd_elf_link_record_dynamic_symbol
+
+boolean _bfd_elf32_link_record_local_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, long));
+boolean _bfd_elf64_link_record_local_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, long));
extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *));
extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 36f6279..709057b 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -43,8 +43,6 @@ static boolean elf_m68k_gc_sweep_hook
const Elf_Internal_Rela *));
static boolean elf_m68k_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean elf_m68k_adjust_dynindx
- PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_m68k_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf_m68k_relocate_section
@@ -1312,51 +1310,6 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section for which we might need to copy
- relocs. These are local symbols, which means that they must come
- first in the dynamic symbol table. That means we must increment
- the dynamic symbol index of every other dynamic symbol. */
- if (info->shared)
- {
- int c;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) != 0
- || (s->flags & SEC_ALLOC) == 0)
- continue;
-
- elf_section_data (s)->dynindx = c + 1;
-
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
-
- ++c;
- }
-
- elf_link_hash_traverse (elf_hash_table (info),
- elf_m68k_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
- }
-
- return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-elf_m68k_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- int *cp = (int *) cparg;
-
- if (h->dynindx != -1)
- h->dynindx += *cp;
return true;
}
@@ -2213,50 +2166,6 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- if (info->shared)
- {
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
- int c;
-
- /* Set up the section symbols for the output sections. */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
-
- if (elf_section_data (s)->dynindx == 0)
- continue;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
-
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf32_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
-
- ++c;
- }
-
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
- }
-
return true;
}
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 03d7f3f..5f04726 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -7693,32 +7693,6 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
return false;
}
- /* If we use dynamic linking, we generate a section symbol for each
- output section. These are local symbols, which means that they
- must come first in the dynamic symbol table.
- That means we must increment the dynamic symbol index of every
- other dynamic symbol. */
- {
- unsigned int c, i;
-
- c = 0;
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- c = bfd_count_sections (output_bfd);
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_link_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
-
- for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
- {
- elf_section_data (s)->dynindx = i;
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
- }
- }
- }
-
return true;
}
@@ -8163,59 +8137,32 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
= MIPS_ELF_GOT_SIZE (output_bfd);
{
- asection *sdynsym;
asection *smsym;
asection *s;
- Elf_Internal_Sym sym;
Elf32_compact_rel cpt;
- /* Set up the section symbols for the output sections. SGI sets
- the STT_NOTYPE attribute for these symbols. Should we do so? */
+ /* ??? The section symbols for the output sections were set up in
+ _bfd_elf_final_link. SGI sets the STT_NOTYPE attribute for these
+ symbols. Should we do so? */
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
smsym = bfd_get_section_by_name (dynobj,
MIPS_ELF_MSYM_SECTION_NAME (dynobj));
- if (sdynsym != NULL)
+ if (smsym != NULL)
{
Elf32_Internal_Msym msym;
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
msym.ms_hash_value = 0;
msym.ms_info = ELF32_MS_INFO (0, 1);
for (s = output_bfd->sections; s != NULL; s = s->next)
{
- int indx;
- long dynindx;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
-
- dynindx = elf_section_data (s)->dynindx;
-
- (*get_elf_backend_data (output_bfd)->s->swap_symbol_out)
- (output_bfd, &sym,
- sdynsym->contents
- + (dynindx * MIPS_ELF_SYM_SIZE (output_bfd)));
-
- if (smsym)
- bfd_mips_elf_swap_msym_out
- (output_bfd, &msym,
- (((Elf32_External_Msym *) smsym->contents)
- + dynindx));
- }
+ long dynindx = elf_section_data (s)->dynindx;
- /* Set the sh_info field of the output .dynsym section to
- the index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- bfd_count_sections (output_bfd) + 1;
+ bfd_mips_elf_swap_msym_out
+ (output_bfd, &msym,
+ (((Elf32_External_Msym *) smsym->contents)
+ + dynindx));
+ }
}
if (SGI_COMPAT (output_bfd))
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index e8d512c..83689c2 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -80,8 +80,6 @@ static boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,
static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
struct elf_link_hash_entry *));
-static boolean ppc_elf_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, PTR));
-
static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
static boolean ppc_elf_relocate_section PARAMS ((bfd *,
@@ -1881,27 +1879,6 @@ ppc_elf_adjust_dynamic_symbol (info, h)
}
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-ppc_elf_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- int *cp = (int *) cparg;
-
-#ifdef DEBUG
- fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp);
-#endif
-
- if (h->dynindx != -1)
- h->dynindx += *cp;
-
- return true;
-}
-
-
/* Set the sizes of the dynamic sections. */
static boolean
@@ -2083,43 +2060,6 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section. These are local symbols, which
- means that they must come first in the dynamic symbol table.
- That means we must increment the dynamic symbol index of every
- other dynamic symbol.
-
- FIXME: We assume that there will never be relocations to
- locations in linker-created sections that do not have
- externally-visible names. Instead, we should work out precisely
- which sections relocations are targetted at. */
- if (info->shared)
- {
- int c;
-
- for (c = 0, s = output_bfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) != 0
- || (s->flags & SEC_ALLOC) == 0)
- {
- elf_section_data (s)->dynindx = 0;
- continue;
- }
-
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
-
- elf_section_data (s)->dynindx = c + 1;
-
- c++;
- }
-
- elf_link_hash_traverse (elf_hash_table (info),
- ppc_elf_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
- }
-
return true;
}
@@ -2924,54 +2864,6 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
}
- if (info->shared)
- {
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
- int maxdindx = 0;
-
- /* Set up the section symbols for the output sections. */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx, dindx;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- dindx = elf_section_data (s)->dynindx;
- if (dindx > 0)
- {
- BFD_ASSERT(indx > 0);
- BFD_ASSERT(dindx > 0);
-
- if (dindx > maxdindx)
- maxdindx = dindx;
-
- sym.st_shndx = indx;
-
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf32_External_Sym *)
- sdynsym->contents)
- + dindx));
- }
- }
-
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- maxdindx + 1;
- }
-
return true;
}
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 9cd1d91..2118c70 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -33,8 +33,6 @@ static boolean elf32_sparc_check_relocs
const Elf_Internal_Rela *));
static boolean elf32_sparc_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean elf32_sparc_adjust_dynindx
- PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf32_sparc_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf32_sparc_relocate_section
@@ -1043,51 +1041,6 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section for which we might need to copy
- relocs. These are local symbols, which means that they must come
- first in the dynamic symbol table. That means we must increment
- the dynamic symbol index of every other dynamic symbol. */
- if (info->shared)
- {
- int c;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) != 0
- || (s->flags & SEC_ALLOC) == 0)
- continue;
-
- elf_section_data (s)->dynindx = c + 1;
-
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
-
- ++c;
- }
-
- elf_link_hash_traverse (elf_hash_table (info),
- elf32_sparc_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
- }
-
- return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-elf32_sparc_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- int *cp = (int *) cparg;
-
- if (h->dynindx != -1)
- h->dynindx += *cp;
return true;
}
@@ -1850,50 +1803,6 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- if (info->shared)
- {
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
- int c;
-
- /* Set up the section symbols for the output sections. */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
-
- if (elf_section_data (s)->dynindx == 0)
- continue;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
-
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf32_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
-
- ++c;
- }
-
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
- }
-
return true;
}
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index a8a7c40..2a0cdb5 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -115,8 +115,6 @@ static boolean elf64_alpha_adjust_dynamic_symbol
PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean elf64_alpha_size_dynamic_sections
PARAMS((bfd *, struct bfd_link_info *));
-static boolean elf64_alpha_adjust_dynindx
- PARAMS((struct elf_link_hash_entry *, PTR));
static boolean elf64_alpha_relocate_section
PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
@@ -3264,34 +3262,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section. These are local symbols, which
- means that they must come first in the dynamic symbol table.
- That means we must increment the dynamic symbol index of every
- other dynamic symbol. */
- if (info->shared)
- {
- long c[2], i;
- asection *p;
-
- c[0] = 0;
- c[1] = bfd_count_sections (output_bfd);
-
- elf_hash_table (info)->dynsymcount += c[1];
- elf_link_hash_traverse (elf_hash_table(info),
- elf64_alpha_adjust_dynindx,
- (PTR) c);
-
- for (i = 1, p = output_bfd->sections;
- p != NULL;
- p = p->next, i++)
- {
- elf_section_data (p)->dynindx = i;
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
- }
- }
-
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -3332,22 +3302,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
return true;
}
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-elf64_alpha_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- long *cp = (long *)cparg;
-
- if (h->dynindx >= cp[0])
- h->dynindx += cp[1];
-
- return true;
-}
-
/* Relocate an Alpha ELF section. */
static boolean
@@ -3991,44 +3945,6 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
}
}
- if (info->shared)
- {
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
-
- /* Set up the section symbols for the output sections. */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
-
- bfd_elf64_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf64_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
- }
-
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
- bfd_count_sections (output_bfd) + 1;
- }
-
return true;
}
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index def6bce..353cdaf 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -51,8 +51,6 @@ static boolean sparc64_elf_adjust_dynamic_symbol
PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean sparc64_elf_size_dynamic_sections
PARAMS((bfd *, struct bfd_link_info *));
-static boolean sparc64_elf_adjust_dynindx
- PARAMS((struct elf_link_hash_entry *, PTR));
static boolean sparc64_elf_merge_private_bfd_data
PARAMS ((bfd *, bfd *));
@@ -1146,54 +1144,8 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section for which we might need to copy
- relocs. These are local symbols, which means that they must come
- first in the dynamic symbol table. That means we must increment
- the dynamic symbol index of every other dynamic symbol. */
- if (info->shared)
- {
- int c;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) != 0
- || (s->flags & SEC_ALLOC) == 0)
- continue;
-
- elf_section_data (s)->dynindx = c + 1;
-
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
-
- ++c;
- }
-
- elf_link_hash_traverse (elf_hash_table (info),
- sparc64_elf_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
- }
-
- return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-sparc64_elf_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- int *cp = (int *) cparg;
-
- if (h->dynindx != -1)
- h->dynindx += *cp;
return true;
}
-
/* Relocate a SPARC64 ELF section. */
@@ -2090,50 +2042,6 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8;
- if (info->shared)
- {
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
- int c;
-
- /* Set up the section symbols for the output sections. */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
-
- if (elf_section_data (s)->dynindx == 0)
- continue;
-
- sym.st_value = s->vma;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
-
- bfd_elf64_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf64_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
-
- ++c;
- }
-
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
- }
-
return true;
}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 49e156e..adbafd8 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -130,6 +130,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link)
#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit)
#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry)
+#define elf_link_record_local_dynamic_symbol \
+ NAME(_bfd_elf,link_record_local_dynamic_symbol)
#if ARCH_SIZE == 64
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e26dedd..93155b1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -260,22 +260,83 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
return true;
}
-/* Increase the index at which H will appear in the dynamic symbol
- table by INCREMENT (which is really an `int *'). Called via
- elf_link_hash_traverse. */
+/* Return the dynindex of a local dynamic symbol. */
-boolean
-_bfd_elf_link_adjust_dynindx (h, increment)
+long
+_bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ long input_indx;
+{
+ struct elf_link_local_dynamic_entry *e;
+
+ for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ if (e->input_bfd == input_bfd && e->input_indx == input_indx)
+ return e->dynindx;
+ return -1;
+}
+
+/* This function is used to renumber the dynamic symbols, if some of
+ them are removed because they are marked as local. This is called
+ via elf_link_hash_traverse. */
+
+static boolean elf_link_renumber_hash_table_dynsyms
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean
+elf_link_renumber_hash_table_dynsyms (h, data)
struct elf_link_hash_entry *h;
- PTR increment;
+ PTR data;
{
+ size_t *count = (size_t *) data;
+
if (h->dynindx != -1)
- h->dynindx += *((int *) increment);
-
+ h->dynindx = ++(*count);
+
return true;
}
+
+/* Assign dynsym indicies. In a shared library we generate a section
+ symbol for each output section, which come first. Next come all of
+ the back-end allocated local dynamic syms, followed by the rest of
+ the global symbols. */
+
+unsigned long
+_bfd_elf_link_renumber_dynsyms (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ unsigned long dynsymcount = 0;
+
+ if (info->shared)
+ {
+ asection *p;
+ for (p = output_bfd->sections; p ; p = p->next)
+ elf_section_data (p)->dynindx = ++dynsymcount;
+ }
+
+ if (elf_hash_table (info)->dynlocal)
+ {
+ struct elf_link_local_dynamic_entry *p;
+ for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
+ p->dynindx = ++dynsymcount;
+ }
+
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_renumber_hash_table_dynsyms,
+ &dynsymcount);
+
+ /* There is an unused NULL entry at the head of the table which
+ we must account for in our count. Unless there weren't any
+ symbols, which means we'll have no table at all. */
+ if (dynsymcount != 0)
+ ++dynsymcount;
+
+ return elf_hash_table (info)->dynsymcount = dynsymcount;
+}
-/* Create a special linker section, or return a pointer to a linker section already created */
+/* Create a special linker section, or return a pointer to a linker
+ section already created */
elf_linker_section_t *
_bfd_elf_create_linker_section (abfd, info, which, defaults)
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 26fee85..bf73759 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -48,14 +48,10 @@ static boolean elf_link_find_version_dependencies
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_link_assign_sym_version
PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean elf_link_renumber_dynsyms
- PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_collect_hash_codes
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_link_read_relocs_from_section
PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));
-static void elf_link_remove_section_and_adjust_dynindices
- PARAMS ((struct bfd_link_info *, asection *));
static void elf_link_output_relocs
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));
static boolean elf_link_size_reloc_section
@@ -2051,6 +2047,73 @@ elf_add_dynamic_entry (info, tag, val)
return true;
}
+
+/* Record a new local dynamic symbol. */
+
+boolean
+elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ long input_indx;
+{
+ struct elf_link_local_dynamic_entry *entry;
+ struct elf_link_hash_table *eht;
+ struct bfd_strtab_hash *dynstr;
+ Elf_External_Sym esym;
+ unsigned long dynstr_index;
+ char *name;
+ int elfsec, link;
+
+ /* See if the entry exists already. */
+ for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
+ if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
+ return true;
+
+ entry = (struct elf_link_local_dynamic_entry *)
+ bfd_alloc (input_bfd, sizeof (*entry));
+ if (entry == NULL)
+ return false;
+
+ /* Go find the symbol, so that we can find it's name. */
+ if (bfd_seek (input_bfd,
+ (elf_tdata (input_bfd)->symtab_hdr.sh_offset
+ + input_indx * sizeof (Elf_External_Sym)),
+ SEEK_SET) != 0
+ || (bfd_read (&esym, sizeof (Elf_External_Sym), 1, input_bfd)
+ != sizeof (Elf_External_Sym)))
+ return false;
+ elf_swap_symbol_in (input_bfd, &esym, &entry->isym);
+
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link,
+ entry->isym.st_name));
+
+ dynstr = elf_hash_table (info)->dynstr;
+ if (dynstr == NULL)
+ {
+ /* Create a strtab to hold the dynamic symbol names. */
+ elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init ();
+ if (dynstr == NULL)
+ return false;
+ }
+
+ dynstr_index = _bfd_stringtab_add (dynstr, name, true, false);
+ if (dynstr_index == (unsigned long) -1)
+ return false;
+ entry->isym.st_name = dynstr_index;
+
+ eht = elf_hash_table (info);
+
+ entry->next = eht->dynlocal;
+ eht->dynlocal = entry;
+ entry->input_bfd = input_bfd;
+ entry->input_indx = input_indx;
+ eht->dynsymcount++;
+
+ /* The dynindx will be set at the end of size_dynamic_sections. */
+
+ return true;
+}
/* Read and swap the relocs from the section indicated by SHDR. This
@@ -2310,8 +2373,6 @@ struct elf_assign_sym_version_info
struct bfd_elf_version_tree *verdefs;
/* Whether we are exporting all dynamic symbols. */
boolean export_dynamic;
- /* Whether we removed any symbols from the dynamic symbol table. */
- boolean removed_dynamic;
/* Whether we had a failure. */
boolean failed;
};
@@ -2486,42 +2547,6 @@ compute_bucket_count (info)
return best_size;
}
-/* Remove SECTION from the BFD. If a symbol for SECTION was going to
- be put into the dynamic symbol table, remove it, and renumber
- subsequent entries. */
-
-static void
-elf_link_remove_section_and_adjust_dynindices (info, section)
- struct bfd_link_info *info;
- asection *section;
-{
- /* Remove the section from the output list. */
- _bfd_strip_section_from_output (section);
-
- if (elf_section_data (section->output_section)->dynindx)
- {
- asection *s;
- int increment = -1;
-
- /* We were going to output an entry in the dynamic symbol table
- for the symbol corresponding to this section. Now, the
- section is gone. So, we must renumber the dynamic indices of
- all subsequent sections and all other entries in the dynamic
- symbol table. */
- elf_section_data (section->output_section)->dynindx = 0;
- for (s = section->output_section->next; s; s = s->next)
- if (elf_section_data (s)->dynindx)
- --elf_section_data (s)->dynindx;
-
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_link_adjust_dynindx,
- &increment);
-
- /* There is one less dynamic symbol than there was before. */
- --elf_hash_table (info)->dynsymcount;
- }
-}
-
/* Set up the sizes and contents of the ELF dynamic sections. This is
called by the ELF linker emulation before_allocation routine. We
must set the sizes of the sections before the linker sets the
@@ -2545,7 +2570,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
bfd_size_type soname_indx;
bfd *dynobj;
struct elf_backend_data *bed;
- bfd_size_type old_dynsymcount;
struct elf_assign_sym_version_info asvinfo;
*sinterpptr = NULL;
@@ -2650,7 +2674,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
asvinfo.info = info;
asvinfo.verdefs = verdefs;
asvinfo.export_dynamic = export_dynamic;
- asvinfo.removed_dynamic = false;
asvinfo.failed = false;
elf_link_hash_traverse (elf_hash_table (info),
@@ -2712,7 +2735,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
/* The backend must work out the sizes of all the other dynamic
sections. */
- old_dynsymcount = elf_hash_table (info)->dynsymcount;
if (bed->elf_backend_size_dynamic_sections
&& ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
return false;
@@ -2734,7 +2756,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
verdefs = asvinfo.verdefs;
if (verdefs == NULL)
- elf_link_remove_section_and_adjust_dynindices (info, s);
+ _bfd_strip_section_from_output (s);
else
{
unsigned int cdefs;
@@ -2744,23 +2766,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
Elf_Internal_Verdef def;
Elf_Internal_Verdaux defaux;
- if (asvinfo.removed_dynamic)
- {
- /* Some dynamic symbols were changed to be local
- symbols. In this case, we renumber all of the
- dynamic symbols, so that we don't have a hole. If
- the backend changed dynsymcount, then assume that the
- new symbols are at the start. This is the case on
- the MIPS. FIXME: The names of the removed symbols
- will still be in the dynamic string table, wasting
- space. */
- elf_hash_table (info)->dynsymcount =
- 1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount);
- elf_link_hash_traverse (elf_hash_table (info),
- elf_link_renumber_dynsyms,
- (PTR) info);
- }
-
cdefs = 0;
size = 0;
@@ -2927,7 +2932,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
(PTR) &sinfo);
if (elf_tdata (output_bfd)->verref == NULL)
- elf_link_remove_section_and_adjust_dynindices (info, s);
+ _bfd_strip_section_from_output (s);
else
{
Elf_Internal_Verneed *t;
@@ -3018,7 +3023,12 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
}
}
- dynsymcount = elf_hash_table (info)->dynsymcount;
+ /* Assign dynsym indicies. In a shared library we generate a
+ section symbol for each output section, which come first.
+ Next come all of the back-end allocated local dynamic syms,
+ followed by the rest of the global symbols. */
+
+ dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
/* Work out the size of the symbol version section. */
s = bfd_get_section_by_name (dynobj, ".gnu.version");
@@ -3026,10 +3036,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
if (dynsymcount == 0
|| (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
{
- elf_link_remove_section_and_adjust_dynindices (info, s);
+ _bfd_strip_section_from_output (s);
/* The DYNSYMCOUNT might have changed if we were going to
output a dynamic symbol table entry for S. */
- dynsymcount = elf_hash_table (info)->dynsymcount;
+ dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
}
else
{
@@ -3513,7 +3523,6 @@ elf_link_assign_sym_version (h, data)
&& info->shared
&& ! sinfo->export_dynamic)
{
- sinfo->removed_dynamic = true;
h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
h->elf_link_hash_flags &=~
ELF_LINK_HASH_NEEDS_PLT;
@@ -3629,7 +3638,6 @@ elf_link_assign_sym_version (h, data)
&& info->shared
&& ! sinfo->export_dynamic)
{
- sinfo->removed_dynamic = true;
h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
h->dynindx = -1;
@@ -3654,7 +3662,6 @@ elf_link_assign_sym_version (h, data)
&& info->shared
&& ! sinfo->export_dynamic)
{
- sinfo->removed_dynamic = true;
h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
h->dynindx = -1;
@@ -3667,26 +3674,6 @@ elf_link_assign_sym_version (h, data)
return true;
}
-
-/* This function is used to renumber the dynamic symbols, if some of
- them are removed because they are marked as local. This is called
- via elf_link_hash_traverse. */
-
-static boolean
-elf_link_renumber_dynsyms (h, data)
- struct elf_link_hash_entry *h;
- PTR data;
-{
- struct bfd_link_info *info = (struct bfd_link_info *) data;
-
- if (h->dynindx != -1)
- {
- h->dynindx = elf_hash_table (info)->dynsymcount;
- ++elf_hash_table (info)->dynsymcount;
- }
-
- return true;
-}
/* Final phase of ELF linker. */
@@ -4161,11 +4148,77 @@ elf_bfd_final_link (abfd, info)
return false;
}
- /* The sh_info field records the index of the first non local
- symbol. */
+ /* The sh_info field records the index of the first non local symbol. */
symtab_hdr->sh_info = bfd_get_symcount (abfd);
+
if (dynamic)
- elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
+ {
+ Elf_Internal_Sym sym;
+ Elf_External_Sym *dynsym =
+ (Elf_External_Sym *)finfo.dynsym_sec->contents;
+ unsigned long last_local = 0;
+
+ /* Write out the section symbols for the output sections. */
+ if (info->shared)
+ {
+ asection *s;
+
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+ sym.st_value = s->vma;
+
+ elf_swap_symbol_out (abfd, &sym,
+ dynsym + elf_section_data (s)->dynindx);
+ }
+
+ last_local = bfd_count_sections (abfd);
+ }
+
+ /* Write out the local dynsyms. */
+ if (elf_hash_table (info)->dynlocal)
+ {
+ struct elf_link_local_dynamic_entry *e;
+ for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ {
+ asection *s, *os;
+
+ sym.st_size = e->isym.st_size;
+ sym.st_other = e->isym.st_other;
+
+ /* Note that we saved a word of storage and overwrote
+ the original st_name with the dynstr_index. */
+ sym.st_name = e->isym.st_name;
+
+ /* Whatever binding the symbol had before, it's now local. */
+ sym.st_info = ELF_ST_INFO (STB_LOCAL,
+ ELF_ST_TYPE (e->isym.st_info));
+
+ s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
+
+ sym.st_shndx = elf_section_data (s->output_section)->this_idx;
+ sym.st_value = (s->output_section->vma
+ + s->output_offset
+ + e->isym.st_value);
+
+ if (last_local < e->dynindx)
+ last_local = e->dynindx;
+
+ elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx);
+ }
+ }
+
+ elf_section_data (finfo.dynsym_sec->output_section)
+ ->this_hdr.sh_info = last_local;
+ }
/* We get the global symbols from the hash table. */
eoinfo.failed = false;