* 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.
This commit is contained in:
Richard Henderson 1999-07-13 18:21:29 +00:00
parent e1ee1229a2
commit 30b30c2181
11 changed files with 306 additions and 635 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
long dynindx = elf_section_data (s)->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));
bfd_mips_elf_swap_msym_out
(output_bfd, &msym,
(((Elf32_External_Msym *) smsym->contents)
+ 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;
}
if (SGI_COMPAT (output_bfd))

View File

@ -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 *,
@ -1880,27 +1878,6 @@ ppc_elf_adjust_dynamic_symbol (info, h)
return true;
}
/* 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. */
@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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)
struct elf_link_hash_entry *h;
PTR 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 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)

View File

@ -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;