* elf-bfd.h (struct elf_reloc_cookie): Add r_sym_shift field.

* elflink.h: Replace all occurrences of sizeof (Elf_External_*)
	where Elf_External_* is different for 64 and 32 bit, with
	corresponding elf_size_info field.
	(struct elf_final_link_info): Use "bfd_byte *" instead
	of "Elf_External_Sym *" for external_syms and symbuf.
	(elf_link_adjust_relocs): Set up r_type_mask and r_sym_shift local
	vars and use instead of ELF_R_INFO and ELF_R_TYPE macros.
	(struct elf_link_sort_rela): Add "sym_mask" alias for "offset".
	(elf_link_sort_cmp1): Use sym_mask field instead of ELF_R_SYM.
	(elf_link_sort_cmp2): Adjust.
	(elf_link_sort_relocs): Set up r_sym_mask local var instead of
	using ELF_R_SYM macro.  Set u.sym_mask.
	(elf_bfd_final_link): Call _bfd_elf_stringtab_init instead of macro
	version, elf_stringtab_init.  Ditto for bfd_section_from_elf_index
	vs. section_from_elf_index.  Adjust Elf_External_Sym pointer
	arithmetic.  Pass bed to elf_link_flush_output_syms.  Adjust
	Elf_External_Dyn pointer arithmentic.  Use bed swap_dyn_in and
	swap_syn_out functions.  Rearrange dyn swap in/out switch.
	(elf_link_output_sym): Adjust Elf_External_Sym pointer arithmentic.
	Pass bed to elf_link_flush_output_syms.  Use bed swap_symbol_out.
	(elf_link_flush_output_syms): Add elf_backend_data arg.
	(elf_link_check_versioned_symbol): Likewise.
	(elf_link_output_extsym): Pass bed to elf_link_check_versioned_symbol.
	Adjust Elf_External_Sym pointer arithmetic.  Use bed swap_symbol_out.
	(elf_link_input_bfd): Use bfd_section_from_elf_index.  Set up
	r_type_mask and r_sym_shift local vars and use instead of ELF_R_SYM,
	ELF_R_TYPE and ELF_R_INFO macros.
	(elf_reloc_link_order): Select ELF32_R_INFO or ELF64_R_INFO invocation
	based on size rather than using ELF_R_INFO.
	(elf_gc_mark): Set up r_sym_shift local var and use instead of
	ELF_R_SYM macro.
	(struct alloc_got_off_arg): New.
	(elf_gc_common_finalize_got_offsets): Use elf_size_info instead of
	ARCH_SIZE.  Pass get entry size down to elf_gc_allocate_got_offsets.
	(elf_gc_allocate_got_offsets): Adjust.
	(elf_reloc_symbol_deleted_p): Usee cookie.r_sym_shift instead of
	ELF_R_SYM.  Use bfd_section_from_elf_index.
	(elf_bfd_discard_info): Set cookie.r_sym_shift.
	* elfcode.h (elf_stringtab_init, section_from_elf_index): Delete.
	(elf_slurp_symbol_table): Use bfd_section_from_elf_index.
This commit is contained in:
Alan Modra 2004-03-27 10:08:59 +00:00
parent 14bde3788a
commit 140f6c8e6d
4 changed files with 204 additions and 106 deletions

View File

@ -1,3 +1,47 @@
2004-03-27 Alan Modra <amodra@bigpond.net.au>
* elf-bfd.h (struct elf_reloc_cookie): Add r_sym_shift field.
* elflink.h: Replace all occurrences of sizeof (Elf_External_*)
where Elf_External_* is different for 64 and 32 bit, with
corresponding elf_size_info field.
(struct elf_final_link_info): Use "bfd_byte *" instead
of "Elf_External_Sym *" for external_syms and symbuf.
(elf_link_adjust_relocs): Set up r_type_mask and r_sym_shift local
vars and use instead of ELF_R_INFO and ELF_R_TYPE macros.
(struct elf_link_sort_rela): Add "sym_mask" alias for "offset".
(elf_link_sort_cmp1): Use sym_mask field instead of ELF_R_SYM.
(elf_link_sort_cmp2): Adjust.
(elf_link_sort_relocs): Set up r_sym_mask local var instead of
using ELF_R_SYM macro. Set u.sym_mask.
(elf_bfd_final_link): Call _bfd_elf_stringtab_init instead of macro
version, elf_stringtab_init. Ditto for bfd_section_from_elf_index
vs. section_from_elf_index. Adjust Elf_External_Sym pointer
arithmetic. Pass bed to elf_link_flush_output_syms. Adjust
Elf_External_Dyn pointer arithmentic. Use bed swap_dyn_in and
swap_syn_out functions. Rearrange dyn swap in/out switch.
(elf_link_output_sym): Adjust Elf_External_Sym pointer arithmentic.
Pass bed to elf_link_flush_output_syms. Use bed swap_symbol_out.
(elf_link_flush_output_syms): Add elf_backend_data arg.
(elf_link_check_versioned_symbol): Likewise.
(elf_link_output_extsym): Pass bed to elf_link_check_versioned_symbol.
Adjust Elf_External_Sym pointer arithmetic. Use bed swap_symbol_out.
(elf_link_input_bfd): Use bfd_section_from_elf_index. Set up
r_type_mask and r_sym_shift local vars and use instead of ELF_R_SYM,
ELF_R_TYPE and ELF_R_INFO macros.
(elf_reloc_link_order): Select ELF32_R_INFO or ELF64_R_INFO invocation
based on size rather than using ELF_R_INFO.
(elf_gc_mark): Set up r_sym_shift local var and use instead of
ELF_R_SYM macro.
(struct alloc_got_off_arg): New.
(elf_gc_common_finalize_got_offsets): Use elf_size_info instead of
ARCH_SIZE. Pass get entry size down to elf_gc_allocate_got_offsets.
(elf_gc_allocate_got_offsets): Adjust.
(elf_reloc_symbol_deleted_p): Usee cookie.r_sym_shift instead of
ELF_R_SYM. Use bfd_section_from_elf_index.
(elf_bfd_discard_info): Set cookie.r_sym_shift.
* elfcode.h (elf_stringtab_init, section_from_elf_index): Delete.
(elf_slurp_symbol_table): Use bfd_section_from_elf_index.
2004-03-26 Stan Shebs <shebs@apple.com> 2004-03-26 Stan Shebs <shebs@apple.com>
Remove MPW support, no longer used. Remove MPW support, no longer used.

View File

@ -492,6 +492,7 @@ struct elf_reloc_cookie
size_t locsymcount; size_t locsymcount;
size_t extsymoff; size_t extsymoff;
struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **sym_hashes;
int r_sym_shift;
bfd_boolean bad_symtab; bfd_boolean bad_symtab;
}; };

View File

@ -149,10 +149,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define LOG_FILE_ALIGN 2 #define LOG_FILE_ALIGN 2
#endif #endif
#define elf_stringtab_init _bfd_elf_stringtab_init
#define section_from_elf_index bfd_section_from_elf_index
#ifdef DEBUG #ifdef DEBUG
static void elf_debug_section (int, Elf_Internal_Shdr *); static void elf_debug_section (int, Elf_Internal_Shdr *);
static void elf_debug_file (Elf_Internal_Ehdr *); static void elf_debug_file (Elf_Internal_Ehdr *);
@ -1109,7 +1105,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
else if (isym->st_shndx < SHN_LORESERVE else if (isym->st_shndx < SHN_LORESERVE
|| isym->st_shndx > SHN_HIRESERVE) || isym->st_shndx > SHN_HIRESERVE)
{ {
sym->symbol.section = section_from_elf_index (abfd, sym->symbol.section = bfd_section_from_elf_index (abfd,
isym->st_shndx); isym->st_shndx);
if (sym->symbol.section == NULL) if (sym->symbol.section == NULL)
{ {

View File

@ -48,7 +48,7 @@ struct elf_final_link_info
Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *internal_relocs;
/* Buffer large enough to hold external local symbols of any input /* Buffer large enough to hold external local symbols of any input
BFD. */ BFD. */
Elf_External_Sym *external_syms; bfd_byte *external_syms;
/* And a buffer for symbol section indices. */ /* And a buffer for symbol section indices. */
Elf_External_Sym_Shndx *locsym_shndx; Elf_External_Sym_Shndx *locsym_shndx;
/* Buffer large enough to hold internal local symbols of any input /* Buffer large enough to hold internal local symbols of any input
@ -61,7 +61,7 @@ struct elf_final_link_info
symbol of any input BFD. */ symbol of any input BFD. */
asection **sections; asection **sections;
/* Buffer to hold swapped out symbols. */ /* Buffer to hold swapped out symbols. */
Elf_External_Sym *symbuf; bfd_byte *symbuf;
/* And one for symbol section indices. */ /* And one for symbol section indices. */
Elf_External_Sym_Shndx *symshndxbuf; Elf_External_Sym_Shndx *symshndxbuf;
/* Number of swapped out symbols in buffer. */ /* Number of swapped out symbols in buffer. */
@ -76,7 +76,7 @@ static bfd_boolean elf_link_output_sym
(struct elf_final_link_info *, const char *, Elf_Internal_Sym *, asection *, (struct elf_final_link_info *, const char *, Elf_Internal_Sym *, asection *,
struct elf_link_hash_entry *); struct elf_link_hash_entry *);
static bfd_boolean elf_link_flush_output_syms static bfd_boolean elf_link_flush_output_syms
(struct elf_final_link_info *); (struct elf_final_link_info *, const struct elf_backend_data *);
static bfd_boolean elf_link_output_extsym static bfd_boolean elf_link_output_extsym
(struct elf_link_hash_entry *, void *); (struct elf_link_hash_entry *, void *);
static bfd_boolean elf_link_input_bfd static bfd_boolean elf_link_input_bfd
@ -109,13 +109,15 @@ elf_link_adjust_relocs (bfd *abfd,
bfd_byte *erela; bfd_byte *erela;
void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
bfd_vma r_type_mask;
int r_sym_shift;
if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
{ {
swap_in = bed->s->swap_reloc_in; swap_in = bed->s->swap_reloc_in;
swap_out = bed->s->swap_reloc_out; swap_out = bed->s->swap_reloc_out;
} }
else if (rel_hdr->sh_entsize == sizeof (Elf_External_Rela)) else if (rel_hdr->sh_entsize == bed->s->sizeof_rela)
{ {
swap_in = bed->s->swap_reloca_in; swap_in = bed->s->swap_reloca_in;
swap_out = bed->s->swap_reloca_out; swap_out = bed->s->swap_reloca_out;
@ -126,6 +128,17 @@ elf_link_adjust_relocs (bfd *abfd,
if (bed->s->int_rels_per_ext_rel > MAX_INT_RELS_PER_EXT_REL) if (bed->s->int_rels_per_ext_rel > MAX_INT_RELS_PER_EXT_REL)
abort (); abort ();
if (bed->s->arch_size == 32)
{
r_type_mask = 0xff;
r_sym_shift = 8;
}
else
{
r_type_mask = 0xffffffff;
r_sym_shift = 32;
}
erela = rel_hdr->contents; erela = rel_hdr->contents;
for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize) for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize)
{ {
@ -139,15 +152,18 @@ elf_link_adjust_relocs (bfd *abfd,
(*swap_in) (abfd, erela, irela); (*swap_in) (abfd, erela, irela);
for (j = 0; j < bed->s->int_rels_per_ext_rel; j++) for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
irela[j].r_info = ELF_R_INFO ((*rel_hash)->indx, irela[j].r_info = ((bfd_vma) (*rel_hash)->indx << r_sym_shift
ELF_R_TYPE (irela[j].r_info)); | (irela[j].r_info & r_type_mask));
(*swap_out) (abfd, irela, erela); (*swap_out) (abfd, irela, erela);
} }
} }
struct elf_link_sort_rela struct elf_link_sort_rela
{ {
union {
bfd_vma offset; bfd_vma offset;
bfd_vma sym_mask;
} u;
enum elf_reloc_type_class type; enum elf_reloc_type_class type;
/* We use this as an array of size int_rels_per_ext_rel. */ /* We use this as an array of size int_rels_per_ext_rel. */
Elf_Internal_Rela rela[1]; Elf_Internal_Rela rela[1];
@ -167,9 +183,9 @@ elf_link_sort_cmp1 (const void *A, const void *B)
return 1; return 1;
if (relativea > relativeb) if (relativea > relativeb)
return -1; return -1;
if (ELF_R_SYM (a->rela->r_info) < ELF_R_SYM (b->rela->r_info)) if ((a->rela->r_info & a->u.sym_mask) < (b->rela->r_info & b->u.sym_mask))
return -1; return -1;
if (ELF_R_SYM (a->rela->r_info) > ELF_R_SYM (b->rela->r_info)) if ((a->rela->r_info & a->u.sym_mask) > (b->rela->r_info & b->u.sym_mask))
return 1; return 1;
if (a->rela->r_offset < b->rela->r_offset) if (a->rela->r_offset < b->rela->r_offset)
return -1; return -1;
@ -185,9 +201,9 @@ elf_link_sort_cmp2 (const void *A, const void *B)
const struct elf_link_sort_rela *b = B; const struct elf_link_sort_rela *b = B;
int copya, copyb; int copya, copyb;
if (a->offset < b->offset) if (a->u.offset < b->u.offset)
return -1; return -1;
if (a->offset > b->offset) if (a->u.offset > b->u.offset)
return 1; return 1;
copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt); copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt); copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
@ -215,6 +231,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
struct bfd_link_order *lo; struct bfd_link_order *lo;
bfd_vma r_sym_mask;
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
if (reldyn == NULL || reldyn->_raw_size == 0) if (reldyn == NULL || reldyn->_raw_size == 0)
@ -222,13 +239,13 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
reldyn = bfd_get_section_by_name (abfd, ".rel.dyn"); reldyn = bfd_get_section_by_name (abfd, ".rel.dyn");
if (reldyn == NULL || reldyn->_raw_size == 0) if (reldyn == NULL || reldyn->_raw_size == 0)
return 0; return 0;
ext_size = sizeof (Elf_External_Rel); ext_size = bed->s->sizeof_rel;
swap_in = bed->s->swap_reloc_in; swap_in = bed->s->swap_reloc_in;
swap_out = bed->s->swap_reloc_out; swap_out = bed->s->swap_reloc_out;
} }
else else
{ {
ext_size = sizeof (Elf_External_Rela); ext_size = bed->s->sizeof_rela;
swap_in = bed->s->swap_reloca_in; swap_in = bed->s->swap_reloca_in;
swap_out = bed->s->swap_reloca_out; swap_out = bed->s->swap_reloca_out;
} }
@ -255,6 +272,11 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
return 0; return 0;
} }
if (bed->s->arch_size == 32)
r_sym_mask = ~(bfd_vma) 0xff;
else
r_sym_mask = ~(bfd_vma) 0xffffffff;
for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next) for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
if (lo->type == bfd_indirect_link_order) if (lo->type == bfd_indirect_link_order)
{ {
@ -269,6 +291,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
(*swap_in) (abfd, erel, s->rela); (*swap_in) (abfd, erel, s->rela);
s->type = (*bed->elf_backend_reloc_type_class) (s->rela); s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
s->u.sym_mask = r_sym_mask;
p += sort_elt; p += sort_elt;
erel += ext_size; erel += ext_size;
} }
@ -289,9 +312,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
for (; i < count; i++, p += sort_elt) for (; i < count; i++, p += sort_elt)
{ {
struct elf_link_sort_rela *sp = (struct elf_link_sort_rela *) p; struct elf_link_sort_rela *sp = (struct elf_link_sort_rela *) p;
if (ELF_R_SYM (sp->rela->r_info) != ELF_R_SYM (sq->rela->r_info)) if (((sp->rela->r_info ^ sq->rela->r_info) & r_sym_mask) != 0)
sq = sp; sq = sp;
sp->offset = sq->rela->r_offset; sp->u.offset = sq->rela->r_offset;
} }
qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2); qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
@ -364,7 +387,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
finfo.info = info; finfo.info = info;
finfo.output_bfd = abfd; finfo.output_bfd = abfd;
finfo.symstrtab = elf_stringtab_init (); finfo.symstrtab = _bfd_elf_stringtab_init ();
if (finfo.symstrtab == NULL) if (finfo.symstrtab == NULL)
return FALSE; return FALSE;
@ -464,7 +487,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
if (elf_bad_symtab (sec->owner)) if (elf_bad_symtab (sec->owner))
sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
/ sizeof (Elf_External_Sym)); / bed->s->sizeof_sym);
else else
sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info; sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
@ -506,10 +529,9 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
bfd_size_type entsize1; bfd_size_type entsize1;
entsize1 = esdi->rel_hdr.sh_entsize; entsize1 = esdi->rel_hdr.sh_entsize;
BFD_ASSERT (entsize1 == sizeof (Elf_External_Rel) BFD_ASSERT (entsize1 == bed->s->sizeof_rel
|| entsize1 == sizeof (Elf_External_Rela)); || entsize1 == bed->s->sizeof_rela);
same_size = (!o->use_rela_p same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel);
== (entsize1 == sizeof (Elf_External_Rel)));
if (!same_size) if (!same_size)
rel_count1 = &esdo->rel_count2; rel_count1 = &esdo->rel_count2;
@ -521,8 +543,8 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
unsigned int *rel_count2; unsigned int *rel_count2;
BFD_ASSERT (entsize2 != entsize1 BFD_ASSERT (entsize2 != entsize1
&& (entsize2 == sizeof (Elf_External_Rel) && (entsize2 == bed->s->sizeof_rel
|| entsize2 == sizeof (Elf_External_Rela))); || entsize2 == bed->s->sizeof_rela));
rel_count2 = &esdo->rel_count2; rel_count2 = &esdo->rel_count2;
if (!same_size) if (!same_size)
@ -603,7 +625,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
/* sh_name is set in prep_headers. */ /* sh_name is set in prep_headers. */
symtab_hdr->sh_type = SHT_SYMTAB; symtab_hdr->sh_type = SHT_SYMTAB;
/* sh_flags, sh_addr and sh_size all start off zero. */ /* sh_flags, sh_addr and sh_size all start off zero. */
symtab_hdr->sh_entsize = sizeof (Elf_External_Sym); symtab_hdr->sh_entsize = bed->s->sizeof_sym;
/* sh_link is set in assign_section_numbers. */ /* sh_link is set in assign_section_numbers. */
/* sh_info is set below. */ /* sh_info is set below. */
/* sh_offset is set just below. */ /* sh_offset is set just below. */
@ -623,7 +645,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
else else
finfo.symbuf_size = max_sym_count; finfo.symbuf_size = max_sym_count;
amt = finfo.symbuf_size; amt = finfo.symbuf_size;
amt *= sizeof (Elf_External_Sym); amt *= bed->s->sizeof_sym;
finfo.symbuf = bfd_malloc (amt); finfo.symbuf = bfd_malloc (amt);
if (finfo.symbuf == NULL) if (finfo.symbuf == NULL)
goto error_return; goto error_return;
@ -682,7 +704,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
elfsym.st_other = 0; elfsym.st_other = 0;
for (i = 1; i < elf_numsections (abfd); i++) for (i = 1; i < elf_numsections (abfd); i++)
{ {
o = section_from_elf_index (abfd, i); o = bfd_section_from_elf_index (abfd, i);
if (o != NULL) if (o != NULL)
o->target_index = bfd_get_symcount (abfd); o->target_index = bfd_get_symcount (abfd);
elfsym.st_shndx = i; elfsym.st_shndx = i;
@ -724,7 +746,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
if (max_sym_count != 0) if (max_sym_count != 0)
{ {
amt = max_sym_count * sizeof (Elf_External_Sym); amt = max_sym_count * bed->s->sizeof_sym;
finfo.external_syms = bfd_malloc (amt); finfo.external_syms = bfd_malloc (amt);
if (finfo.external_syms == NULL) if (finfo.external_syms == NULL)
goto error_return; goto error_return;
@ -857,8 +879,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
&& finfo.dynsym_sec->output_section != bfd_abs_section_ptr) && finfo.dynsym_sec->output_section != bfd_abs_section_ptr)
{ {
Elf_Internal_Sym sym; Elf_Internal_Sym sym;
Elf_External_Sym *dynsym = bfd_byte *dynsym = finfo.dynsym_sec->contents;
(Elf_External_Sym *) finfo.dynsym_sec->contents;
long last_local = 0; long last_local = 0;
/* Write out the section symbols for the output sections. */ /* Write out the section symbols for the output sections. */
@ -874,14 +895,16 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
for (s = abfd->sections; s != NULL; s = s->next) for (s = abfd->sections; s != NULL; s = s->next)
{ {
int indx; int indx;
Elf_External_Sym *dest; bfd_byte *dest;
long dynindx;
indx = elf_section_data (s)->this_idx; indx = elf_section_data (s)->this_idx;
dynindx = elf_section_data (s)->dynindx;
BFD_ASSERT (indx > 0); BFD_ASSERT (indx > 0);
sym.st_shndx = indx; sym.st_shndx = indx;
sym.st_value = s->vma; sym.st_value = s->vma;
dest = dynsym + elf_section_data (s)->dynindx; dest = dynsym + dynindx * bed->s->sizeof_sym;
elf_swap_symbol_out (abfd, &sym, dest, 0); bed->s->swap_symbol_out (abfd, &sym, dest, 0);
} }
last_local = bfd_count_sections (abfd); last_local = bfd_count_sections (abfd);
@ -894,7 +917,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
{ {
asection *s; asection *s;
Elf_External_Sym *dest; bfd_byte *dest;
sym.st_size = e->isym.st_size; sym.st_size = e->isym.st_size;
sym.st_other = e->isym.st_other; sym.st_other = e->isym.st_other;
@ -921,8 +944,8 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
if (last_local < e->dynindx) if (last_local < e->dynindx)
last_local = e->dynindx; last_local = e->dynindx;
dest = dynsym + e->dynindx; dest = dynsym + e->dynindx * bed->s->sizeof_sym;
elf_swap_symbol_out (abfd, &sym, dest, 0); bed->s->swap_symbol_out (abfd, &sym, dest, 0);
} }
} }
@ -953,7 +976,7 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
} }
/* Flush all symbols to the file. */ /* Flush all symbols to the file. */
if (! elf_link_flush_output_syms (&finfo)) if (! elf_link_flush_output_syms (&finfo, bed))
return FALSE; return FALSE;
/* Now we know the size of the symtab section. */ /* Now we know the size of the symtab section. */
@ -1028,43 +1051,41 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
shared library, finish up the dynamic linking information. */ shared library, finish up the dynamic linking information. */
if (dynamic) if (dynamic)
{ {
Elf_External_Dyn *dyncon, *dynconend; bfd_byte *dyncon, *dynconend;
/* Fix up .dynamic entries. */ /* Fix up .dynamic entries. */
o = bfd_get_section_by_name (dynobj, ".dynamic"); o = bfd_get_section_by_name (dynobj, ".dynamic");
BFD_ASSERT (o != NULL); BFD_ASSERT (o != NULL);
dyncon = (Elf_External_Dyn *) o->contents; dyncon = o->contents;
dynconend = (Elf_External_Dyn *) (o->contents + o->_raw_size); dynconend = o->contents + o->_raw_size;
for (; dyncon < dynconend; dyncon++) for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn)
{ {
Elf_Internal_Dyn dyn; Elf_Internal_Dyn dyn;
const char *name; const char *name;
unsigned int type; unsigned int type;
elf_swap_dyn_in (dynobj, dyncon, &dyn); bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
switch (dyn.d_tag) switch (dyn.d_tag)
{ {
default: default:
break; continue;
case DT_NULL: case DT_NULL:
if (relativecount > 0 && dyncon + 1 < dynconend) if (relativecount > 0 && dyncon + bed->s->sizeof_dyn < dynconend)
{ {
switch (elf_section_data (reldyn)->this_hdr.sh_type) switch (elf_section_data (reldyn)->this_hdr.sh_type)
{ {
case SHT_REL: dyn.d_tag = DT_RELCOUNT; break; case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break; case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
default: break; default: continue;
} }
if (dyn.d_tag != DT_NULL)
{
dyn.d_un.d_val = relativecount; dyn.d_un.d_val = relativecount;
elf_swap_dyn_out (dynobj, &dyn, dyncon);
relativecount = 0; relativecount = 0;
}
}
break; break;
}
continue;
case DT_INIT: case DT_INIT:
name = info->init_function; name = info->init_function;
goto get_sym; goto get_sym;
@ -1091,11 +1112,10 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
library and does not apply to this one. */ library and does not apply to this one. */
dyn.d_un.d_val = 0; dyn.d_un.d_val = 0;
} }
elf_swap_dyn_out (dynobj, &dyn, dyncon);
}
}
break; break;
}
}
continue;
case DT_PREINIT_ARRAYSZ: case DT_PREINIT_ARRAYSZ:
name = ".preinit_array"; name = ".preinit_array";
@ -1118,7 +1138,6 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
(*_bfd_error_handler) (*_bfd_error_handler)
(_("warning: %s section has zero size"), name); (_("warning: %s section has zero size"), name);
dyn.d_un.d_val = o->_raw_size; dyn.d_un.d_val = o->_raw_size;
elf_swap_dyn_out (dynobj, &dyn, dyncon);
break; break;
case DT_PREINIT_ARRAY: case DT_PREINIT_ARRAY:
@ -1158,7 +1177,6 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
goto error_return; goto error_return;
} }
dyn.d_un.d_ptr = o->vma; dyn.d_un.d_ptr = o->vma;
elf_swap_dyn_out (dynobj, &dyn, dyncon);
break; break;
case DT_REL: case DT_REL:
@ -1188,9 +1206,9 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
} }
} }
} }
elf_swap_dyn_out (dynobj, &dyn, dyncon);
break; break;
} }
bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
} }
} }
@ -1332,14 +1350,15 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
asection *input_sec, asection *input_sec,
struct elf_link_hash_entry *h) struct elf_link_hash_entry *h)
{ {
Elf_External_Sym *dest; bfd_byte *dest;
Elf_External_Sym_Shndx *destshndx; Elf_External_Sym_Shndx *destshndx;
bfd_boolean (*output_symbol_hook) bfd_boolean (*output_symbol_hook)
(struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *, (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
struct elf_link_hash_entry *); struct elf_link_hash_entry *);
const struct elf_backend_data *bed;
output_symbol_hook = get_elf_backend_data (finfo->output_bfd)-> bed = get_elf_backend_data (finfo->output_bfd);
elf_backend_link_output_symbol_hook; output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
if (output_symbol_hook != NULL) if (output_symbol_hook != NULL)
{ {
if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h)) if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
@ -1360,11 +1379,11 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
if (finfo->symbuf_count >= finfo->symbuf_size) if (finfo->symbuf_count >= finfo->symbuf_size)
{ {
if (! elf_link_flush_output_syms (finfo)) if (! elf_link_flush_output_syms (finfo, bed))
return FALSE; return FALSE;
} }
dest = finfo->symbuf + finfo->symbuf_count; dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
destshndx = finfo->symshndxbuf; destshndx = finfo->symshndxbuf;
if (destshndx != NULL) if (destshndx != NULL)
{ {
@ -1382,7 +1401,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
destshndx += bfd_get_symcount (finfo->output_bfd); destshndx += bfd_get_symcount (finfo->output_bfd);
} }
elf_swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx); bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx);
finfo->symbuf_count += 1; finfo->symbuf_count += 1;
bfd_get_symcount (finfo->output_bfd) += 1; bfd_get_symcount (finfo->output_bfd) += 1;
@ -1392,7 +1411,8 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
/* Flush the output symbols to the file. */ /* Flush the output symbols to the file. */
static bfd_boolean static bfd_boolean
elf_link_flush_output_syms (struct elf_final_link_info *finfo) elf_link_flush_output_syms (struct elf_final_link_info *finfo,
const struct elf_backend_data *bed)
{ {
if (finfo->symbuf_count > 0) if (finfo->symbuf_count > 0)
{ {
@ -1402,7 +1422,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo)
hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr; hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr;
pos = hdr->sh_offset + hdr->sh_size; pos = hdr->sh_offset + hdr->sh_size;
amt = finfo->symbuf_count * sizeof (Elf_External_Sym); amt = finfo->symbuf_count * bed->s->sizeof_sym;
if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0 if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
|| bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt) || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt)
return FALSE; return FALSE;
@ -1422,6 +1442,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo)
static bfd_boolean static bfd_boolean
elf_link_check_versioned_symbol (struct bfd_link_info *info, elf_link_check_versioned_symbol (struct bfd_link_info *info,
const struct elf_backend_data *bed,
struct elf_link_hash_entry *h) struct elf_link_hash_entry *h)
{ {
bfd *abfd; bfd *abfd;
@ -1481,7 +1502,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
hdr = &elf_tdata (input)->dynsymtab_hdr; hdr = &elf_tdata (input)->dynsymtab_hdr;
symcount = hdr->sh_size / sizeof (Elf_External_Sym); symcount = hdr->sh_size / bed->s->sizeof_sym;
if (elf_bad_symtab (input)) if (elf_bad_symtab (input))
{ {
extsymcount = symcount; extsymcount = symcount;
@ -1576,6 +1597,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
bfd_boolean strip; bfd_boolean strip;
Elf_Internal_Sym sym; Elf_Internal_Sym sym;
asection *input_sec; asection *input_sec;
const struct elf_backend_data *bed;
if (h->root.type == bfd_link_hash_warning) if (h->root.type == bfd_link_hash_warning)
{ {
@ -1596,6 +1618,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
return TRUE; return TRUE;
} }
bed = get_elf_backend_data (finfo->output_bfd);
/* If we have an undefined symbol reference here then it must have /* If we have an undefined symbol reference here then it must have
come from a shared library that is being linked in. (Undefined come from a shared library that is being linked in. (Undefined
references in regular files have already been handled). If we references in regular files have already been handled). If we
@ -1603,7 +1627,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
if (h->root.type == bfd_link_hash_undefined if (h->root.type == bfd_link_hash_undefined
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
&& ! elf_link_check_versioned_symbol (finfo->info, h) && ! elf_link_check_versioned_symbol (finfo->info, bed, h)
&& finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
{ {
if (! ((*finfo->info->callbacks->undefined_symbol) if (! ((*finfo->info->callbacks->undefined_symbol)
@ -1622,7 +1646,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
&& (h->elf_link_hash_flags && (h->elf_link_hash_flags
& (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_DYNAMIC_DEF | ELF_LINK_DYNAMIC_WEAK)) & (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_DYNAMIC_DEF | ELF_LINK_DYNAMIC_WEAK))
== (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC) == (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC)
&& ! elf_link_check_versioned_symbol (finfo->info, h)) && ! elf_link_check_versioned_symbol (finfo->info, bed, h))
{ {
(*_bfd_error_handler) (*_bfd_error_handler)
(_("%s: %s symbol `%s' in %s is referenced by DSO"), (_("%s: %s symbol `%s' in %s is referenced by DSO"),
@ -1768,9 +1792,6 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
&& elf_hash_table (finfo->info)->dynamic_sections_created) && elf_hash_table (finfo->info)->dynamic_sections_created)
{ {
const struct elf_backend_data *bed;
bed = get_elf_backend_data (finfo->output_bfd);
if (! ((*bed->elf_backend_finish_dynamic_symbol) if (! ((*bed->elf_backend_finish_dynamic_symbol)
(finfo->output_bfd, finfo->info, h, &sym))) (finfo->output_bfd, finfo->info, h, &sym)))
{ {
@ -1830,11 +1851,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
size_t hash_entry_size; size_t hash_entry_size;
bfd_byte *bucketpos; bfd_byte *bucketpos;
bfd_vma chain; bfd_vma chain;
Elf_External_Sym *esym; bfd_byte *esym;
sym.st_name = h->dynstr_index; sym.st_name = h->dynstr_index;
esym = (Elf_External_Sym *) finfo->dynsym_sec->contents + h->dynindx; esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
elf_swap_symbol_out (finfo->output_bfd, &sym, esym, 0); bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0);
bucketcount = elf_hash_table (finfo->info)->bucketcount; bucketcount = elf_hash_table (finfo->info)->bucketcount;
bucket = h->elf_hash_value % bucketcount; bucket = h->elf_hash_value % bucketcount;
@ -1935,7 +1956,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
if (elf_bad_symtab (input_bfd)) if (elf_bad_symtab (input_bfd))
{ {
locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym); locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
extsymoff = 0; extsymoff = 0;
} }
else else
@ -1984,7 +2005,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
else if (isym->st_shndx < SHN_LORESERVE else if (isym->st_shndx < SHN_LORESERVE
|| isym->st_shndx > SHN_HIRESERVE) || isym->st_shndx > SHN_HIRESERVE)
{ {
isec = section_from_elf_index (input_bfd, isym->st_shndx); isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
if (isec if (isec
&& isec->sec_info_type == ELF_INFO_TYPE_MERGE && isec->sec_info_type == ELF_INFO_TYPE_MERGE
&& ELF_ST_TYPE (isym->st_info) != STT_SECTION) && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
@ -2133,6 +2154,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
if ((o->flags & SEC_RELOC) != 0) if ((o->flags & SEC_RELOC) != 0)
{ {
Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *internal_relocs;
bfd_vma r_type_mask;
int r_sym_shift;
/* Get the swapped relocs. */ /* Get the swapped relocs. */
internal_relocs internal_relocs
@ -2142,6 +2165,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
&& o->reloc_count > 0) && o->reloc_count > 0)
return FALSE; return FALSE;
if (bed->s->arch_size == 32)
{
r_type_mask = 0xff;
r_sym_shift = 8;
}
else
{
r_type_mask = 0xffffffff;
r_sym_shift = 32;
}
/* Run through the relocs looking for any against symbols /* Run through the relocs looking for any against symbols
from discarded sections and section symbols from from discarded sections and section symbols from
removed link-once sections. Complain about relocs removed link-once sections. Complain about relocs
@ -2156,7 +2190,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
for ( ; rel < relend; rel++) for ( ; rel < relend; rel++)
{ {
unsigned long r_symndx = ELF_R_SYM (rel->r_info); unsigned long r_symndx = rel->r_info >> r_sym_shift;
asection *sec; asection *sec;
if (r_symndx >= locsymcount if (r_symndx >= locsymcount
@ -2217,8 +2251,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
= sec->kept_section; = sec->kept_section;
else else
{ {
rel->r_info rel->r_info &= r_type_mask;
= ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
rel->r_addend = 0; rel->r_addend = 0;
} }
} }
@ -2287,7 +2320,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
input_rel_hdr = &elf_section_data (o)->rel_hdr; input_rel_hdr = &elf_section_data (o)->rel_hdr;
rela_normal = (bed->rela_normal rela_normal = (bed->rela_normal
&& (input_rel_hdr->sh_entsize && (input_rel_hdr->sh_entsize
== sizeof (Elf_External_Rela))); == bed->s->sizeof_rela));
/* Adjust the reloc addresses and symbol indices. */ /* Adjust the reloc addresses and symbol indices. */
@ -2335,7 +2368,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
last_offset = irela->r_offset; last_offset = irela->r_offset;
r_symndx = ELF_R_SYM (irela->r_info); r_symndx = irela->r_info >> r_sym_shift;
if (r_symndx == STN_UNDEF) if (r_symndx == STN_UNDEF)
continue; continue;
@ -2459,8 +2492,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
r_symndx = finfo->indices[r_symndx]; r_symndx = finfo->indices[r_symndx];
} }
irela->r_info = ELF_R_INFO (r_symndx, irela->r_info = ((bfd_vma) r_symndx << r_sym_shift
ELF_R_TYPE (irela->r_info)); | (irela->r_info & r_type_mask));
} }
/* Swap out the relocs. */ /* Swap out the relocs. */
@ -2674,21 +2707,24 @@ elf_reloc_link_order (bfd *output_bfd,
irel[i].r_info = 0; irel[i].r_info = 0;
irel[i].r_addend = 0; irel[i].r_addend = 0;
} }
irel[0].r_info = ELF_R_INFO (indx, howto->type); if (bed->s->arch_size == 32)
irel[0].r_info = ELF32_R_INFO (indx, howto->type);
else
irel[0].r_info = ELF64_R_INFO (indx, howto->type);
rel_hdr = &elf_section_data (output_section)->rel_hdr; rel_hdr = &elf_section_data (output_section)->rel_hdr;
erel = rel_hdr->contents; erel = rel_hdr->contents;
if (rel_hdr->sh_type == SHT_REL) if (rel_hdr->sh_type == SHT_REL)
{ {
erel += (elf_section_data (output_section)->rel_count erel += (elf_section_data (output_section)->rel_count
* sizeof (Elf_External_Rel)); * bed->s->sizeof_rel);
(*bed->s->swap_reloc_out) (output_bfd, irel, erel); (*bed->s->swap_reloc_out) (output_bfd, irel, erel);
} }
else else
{ {
irel[0].r_addend = addend; irel[0].r_addend = addend;
erel += (elf_section_data (output_section)->rel_count erel += (elf_section_data (output_section)->rel_count
* sizeof (Elf_External_Rela)); * bed->s->sizeof_rela);
(*bed->s->swap_reloca_out) (output_bfd, irel, erel); (*bed->s->swap_reloca_out) (output_bfd, irel, erel);
} }
@ -2741,6 +2777,7 @@ elf_gc_mark (struct bfd_link_info *info,
bfd *input_bfd = sec->owner; bfd *input_bfd = sec->owner;
const struct elf_backend_data *bed = get_elf_backend_data (input_bfd); const struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
Elf_Internal_Sym *isym = NULL; Elf_Internal_Sym *isym = NULL;
int r_sym_shift;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd); sym_hashes = elf_sym_hashes (input_bfd);
@ -2748,7 +2785,7 @@ elf_gc_mark (struct bfd_link_info *info,
/* Read the local symbols. */ /* Read the local symbols. */
if (elf_bad_symtab (input_bfd)) if (elf_bad_symtab (input_bfd))
{ {
nlocsyms = symtab_hdr->sh_size / sizeof (Elf_External_Sym); nlocsyms = symtab_hdr->sh_size / bed->s->sizeof_sym;
extsymoff = 0; extsymoff = 0;
} }
else else
@ -2773,13 +2810,18 @@ elf_gc_mark (struct bfd_link_info *info,
} }
relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel; relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
if (bed->s->arch_size == 32)
r_sym_shift = 8;
else
r_sym_shift = 32;
for (rel = relstart; rel < relend; rel++) for (rel = relstart; rel < relend; rel++)
{ {
unsigned long r_symndx; unsigned long r_symndx;
asection *rsec; asection *rsec;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
r_symndx = ELF_R_SYM (rel->r_info); r_symndx = rel->r_info >> r_sym_shift;
if (r_symndx == 0) if (r_symndx == 0)
continue; continue;
@ -3097,11 +3139,12 @@ elf_gc_record_vtinherit (bfd *abfd,
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
struct elf_link_hash_entry **search, *child; struct elf_link_hash_entry **search, *child;
bfd_size_type extsymcount; bfd_size_type extsymcount;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
/* The sh_info field of the symtab header tells us where the /* The sh_info field of the symtab header tells us where the
external symbols start. We don't care about the local symbols at external symbols start. We don't care about the local symbols at
this point. */ this point. */
extsymcount = elf_tdata (abfd)->symtab_hdr.sh_size/sizeof (Elf_External_Sym); extsymcount = elf_tdata (abfd)->symtab_hdr.sh_size / bed->s->sizeof_sym;
if (!elf_bad_symtab (abfd)) if (!elf_bad_symtab (abfd))
extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info; extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info;
@ -3208,6 +3251,11 @@ elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
return TRUE; return TRUE;
} }
struct alloc_got_off_arg {
bfd_vma gotoff;
unsigned int got_elt_size;
};
/* And an accompanying bit to work out final got entry offsets once /* And an accompanying bit to work out final got entry offsets once
we're done. Should be called from final_link. */ we're done. Should be called from final_link. */
@ -3218,6 +3266,8 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
bfd *i; bfd *i;
const struct elf_backend_data *bed = get_elf_backend_data (abfd); const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_vma gotoff; bfd_vma gotoff;
unsigned int got_elt_size = bed->s->arch_size / 8;
struct alloc_got_off_arg gofarg;
if (! is_elf_hash_table (info->hash)) if (! is_elf_hash_table (info->hash))
return FALSE; return FALSE;
@ -3245,7 +3295,7 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
symtab_hdr = &elf_tdata (i)->symtab_hdr; symtab_hdr = &elf_tdata (i)->symtab_hdr;
if (elf_bad_symtab (i)) if (elf_bad_symtab (i))
locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym); locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
else else
locsymcount = symtab_hdr->sh_info; locsymcount = symtab_hdr->sh_info;
@ -3254,7 +3304,7 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
if (local_got[j] > 0) if (local_got[j] > 0)
{ {
local_got[j] = gotoff; local_got[j] = gotoff;
gotoff += ARCH_SIZE / 8; gotoff += got_elt_size;
} }
else else
local_got[j] = (bfd_vma) -1; local_got[j] = (bfd_vma) -1;
@ -3263,9 +3313,11 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
/* Then the global .got entries. .plt refcounts are handled by /* Then the global .got entries. .plt refcounts are handled by
adjust_dynamic_symbol */ adjust_dynamic_symbol */
gofarg.gotoff = gotoff;
gofarg.got_elt_size = got_elt_size;
elf_link_hash_traverse (elf_hash_table (info), elf_link_hash_traverse (elf_hash_table (info),
elf_gc_allocate_got_offsets, elf_gc_allocate_got_offsets,
&gotoff); &gofarg);
return TRUE; return TRUE;
} }
@ -3273,17 +3325,17 @@ elf_gc_common_finalize_got_offsets (bfd *abfd,
to real got offsets. */ to real got offsets. */
static bfd_boolean static bfd_boolean
elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *offarg) elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
{ {
bfd_vma *off = offarg; struct alloc_got_off_arg *gofarg = arg;
if (h->root.type == bfd_link_hash_warning) if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->got.refcount > 0) if (h->got.refcount > 0)
{ {
h->got.offset = off[0]; h->got.offset = gofarg->gotoff;
off[0] += ARCH_SIZE / 8; gofarg->gotoff += gofarg->got_elt_size;
} }
else else
h->got.offset = (bfd_vma) -1; h->got.offset = (bfd_vma) -1;
@ -3322,7 +3374,7 @@ elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
if (rcookie->rel->r_offset != offset) if (rcookie->rel->r_offset != offset)
continue; continue;
r_symndx = ELF_R_SYM (rcookie->rel->r_info); r_symndx = rcookie->rel->r_info >> rcookie->r_sym_shift;
if (r_symndx == SHN_UNDEF) if (r_symndx == SHN_UNDEF)
return TRUE; return TRUE;
@ -3356,7 +3408,7 @@ elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
isym = &rcookie->locsyms[r_symndx]; isym = &rcookie->locsyms[r_symndx];
if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE) if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
{ {
isec = section_from_elf_index (rcookie->abfd, isym->st_shndx); isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
if (isec != NULL && elf_discarded_section (isec)) if (isec != NULL && elf_discarded_section (isec))
return TRUE; return TRUE;
} }
@ -3421,7 +3473,7 @@ elf_bfd_discard_info (bfd *output_bfd, struct bfd_link_info *info)
cookie.bad_symtab = elf_bad_symtab (abfd); cookie.bad_symtab = elf_bad_symtab (abfd);
if (cookie.bad_symtab) if (cookie.bad_symtab)
{ {
cookie.locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym); cookie.locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
cookie.extsymoff = 0; cookie.extsymoff = 0;
} }
else else
@ -3430,6 +3482,11 @@ elf_bfd_discard_info (bfd *output_bfd, struct bfd_link_info *info)
cookie.extsymoff = symtab_hdr->sh_info; cookie.extsymoff = symtab_hdr->sh_info;
} }
if (bed->s->arch_size == 32)
cookie.r_sym_shift = 8;
else
cookie.r_sym_shift = 32;
cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
if (cookie.locsyms == NULL && cookie.locsymcount != 0) if (cookie.locsyms == NULL && cookie.locsymcount != 0)
{ {