Make MIPS ELF use new ELF backend linker. No shared library

support yet.
	* elf32-mips.c (bfd_mips_elf32_swap_gptab_in): New function.
	(bfd_mips_elf32_swap_gptab_out): New function.
	(mips_elf_object_p): If last symbol is LOCAL, set elf_bad_symtab.
	(mips_elf_final_write_processing): Set sh_info field for .gptab.*
	sections.
	(mips_elf_fake_sections): Set sh_entsize for .gptab.* sections.
	(mips_elf_read_ecoff_info): Read and free external symbols last,
	not first, for clarity.
	(struct mips_elf_link_hash_entry): Define new structure.
	(struct mips_elf_link_hash_table): Define new structure.
	(mips_elf_link_hash_lookup): Define new macro.
	(mips_elf_link_hash_traverse): Define new macro.
	(mips_elf_hash_table): Define new macro.
	(mips_elf_link_hash_newfunc): New static function.
	(mips_elf_link_hash_table_create): New static function.
	(mips_elf_add_symbol_hook): New static function.
	(struct extsym_info): Define new structure.
	(mips_elf_get_extr, mips_elf_set_index): Remove.
	(mips_elf_output_extsym): New static function.
	(gptab_compare): New static function.
	(mips_elf_final_link): Rewrite to use ELF backend linker, and to
	merge gptab information in input files.
	(mips_elf_relocate_hi16): New static function.
	(mips_elf_relocate_section): New static function.
	(bfd_elf32_bfd_link_hash_table_create): Define as macro before
	including elf32-target.h.
	(elf_backend_relocate_section): Likewise.
	(elf_backend_add_symbol_hook): Likewise.
	* elf.c (_bfd_elf_link_hash_newfunc): Rename from
	elf_link_hash_newfunc and make globally visible.  Change caller.
	(_bfd_elf_link_hash_table_init): New function, broken out of
	_bfd_elf_link_hash_table_create.
	(_bfd_elf_link_hash_table_create): Use
	_bfd_elf_link_hash_table_init.
	* libelf.h (struct elf_obj_tdata): Add new field bad_symtab.
	(elf_bad_symtab): Define new accessor macro.
	(_bfd_elf_link_hash_newfunc): Declare.
	(_bew_elf_link_hash_table_init): Declare.
	* elfcode.h (elf_object_p): Call backend object_p hook after
	swapping in all the section headers.
	(map_program_segments): Correct typo: Internal for External.
	(elf_link_add_object_symbols): If elf_bad_symtab is set, read all
	the symbols.  Skip STB_LOCAL symbols rather than giving an error.
	(elf_bfd_final_link): If elf_bad_symtab is set, allocate space for
	all symbols, not just locals.
	(elf_link_output_extsym): Only skip a symbol not mentioned by a
	regular file if it is mentioned by a dynamic object.
	(elf_link_input_bfd): If elf_bad_symtab is set, read all the
	symbols.
This commit is contained in:
Ian Lance Taylor
1994-05-24 20:44:50 +00:00
parent f49f58c6a8
commit 5315c42827
4 changed files with 160 additions and 39 deletions

View File

@ -939,14 +939,6 @@ elf_object_p (abfd)
/* Remember the entry point specified in the ELF file header. */
bfd_get_start_address (abfd) = i_ehdrp->e_entry;
/* Let the backend double check the format and override global
information. */
if (ebd->elf_backend_object_p)
{
if ((*ebd->elf_backend_object_p) (abfd) == false)
goto got_wrong_format_error;
}
/* Allocate space for a copy of the section header table in
internal form, seek to the section header table in the file,
read it in, and convert it to internal form. */
@ -997,6 +989,14 @@ elf_object_p (abfd)
goto got_no_match;
}
/* Let the backend double check the format and override global
information. */
if (ebd->elf_backend_object_p)
{
if ((*ebd->elf_backend_object_p) (abfd) == false)
goto got_wrong_format_error;
}
return (abfd->xvec);
got_wrong_format_error:
@ -1914,7 +1914,7 @@ map_program_segments (abfd, off, first, phdr_size)
/* Make sure the return value from get_program_header_size matches
what we computed here. */
if (phdr_count != phdr_size / sizeof (Elf_Internal_Phdr))
if (phdr_count != phdr_size / sizeof (Elf_External_Phdr))
abort ();
/* Set up program header information. */
@ -4111,6 +4111,7 @@ elf_link_add_object_symbols (abfd, info)
Elf_Internal_Shdr *hdr;
size_t symcount;
size_t extsymcount;
size_t extsymoff;
Elf_External_Sym *buf = NULL;
struct elf_link_hash_entry **sym_hash;
boolean dynamic;
@ -4128,7 +4129,16 @@ elf_link_add_object_symbols (abfd, info)
/* The sh_info field of the symtab header tells us where the
external symbols start. We don't care about the local symbols at
this point. */
extsymcount = symcount - hdr->sh_info;
if (elf_bad_symtab (abfd))
{
extsymcount = symcount;
extsymoff = 0;
}
else
{
extsymcount = symcount - hdr->sh_info;
extsymoff = hdr->sh_info;
}
buf = (Elf_External_Sym *) malloc (extsymcount * sizeof (Elf_External_Sym));
if (buf == NULL && extsymcount != 0)
@ -4251,7 +4261,7 @@ elf_link_add_object_symbols (abfd, info)
}
if (bfd_seek (abfd,
hdr->sh_offset + hdr->sh_info * sizeof (Elf_External_Sym),
hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
SEEK_SET) != 0
|| (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
!= extsymcount * sizeof (Elf_External_Sym)))
@ -4283,9 +4293,9 @@ elf_link_add_object_symbols (abfd, info)
{
/* This should be impossible, since ELF requires that all
global symbols follow all local symbols, and that sh_info
point to the first global symbol. */
bfd_set_error (bfd_error_bad_value);
goto error_return;
point to the first global symbol. Unfortunatealy, Irix 5
screws this up. */
continue;
}
else if (bind == STB_GLOBAL)
flags = BSF_GLOBAL;
@ -5093,10 +5103,19 @@ elf_bfd_final_link (abfd, info)
/* We are interested in just local symbols, not all
symbols. */
if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
&& (elf_tdata (sec->owner)->symtab_hdr.sh_info
> max_sym_count))
max_sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour)
{
size_t sym_count;
if (elf_bad_symtab (sec->owner))
sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
/ sizeof (Elf_External_Sym));
else
sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
if (sym_count > max_sym_count)
max_sym_count = sym_count;
}
if ((sec->flags & SEC_RELOC) != 0)
{
@ -5688,7 +5707,9 @@ elf_link_output_extsym (h, data)
output it. */
if (h->indx == -2)
strip = false;
else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|| (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
strip = true;
else if (finfo->info->strip == strip_all
@ -5843,6 +5864,8 @@ elf_link_input_bfd (finfo, input_bfd)
asection **));
bfd *output_bfd;
Elf_Internal_Shdr *symtab_hdr;
size_t locsymcount;
size_t extsymoff;
Elf_External_Sym *esym;
Elf_External_Sym *esymend;
Elf_Internal_Sym *isym;
@ -5860,18 +5883,29 @@ elf_link_input_bfd (finfo, input_bfd)
if (elf_elfheader (input_bfd)->e_type == ET_DYN)
return true;
/* Read the local symbols. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
if (elf_bad_symtab (input_bfd))
{
locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
extsymoff = 0;
}
else
{
locsymcount = symtab_hdr->sh_info;
extsymoff = symtab_hdr->sh_info;
}
/* Read the local symbols. */
if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
|| (bfd_read (finfo->external_syms, sizeof (Elf_External_Sym),
symtab_hdr->sh_info, input_bfd)
!= symtab_hdr->sh_info * sizeof (Elf_External_Sym)))
locsymcount, input_bfd)
!= locsymcount * sizeof (Elf_External_Sym)))
return false;
/* Swap in the local symbols and write out the ones which we know
are going into the output file. */
esym = finfo->external_syms;
esymend = esym + symtab_hdr->sh_info;
esymend = esym + locsymcount;
isym = finfo->internal_syms;
pindex = finfo->indices;
ppsection = finfo->sections;
@ -5884,6 +5918,15 @@ elf_link_input_bfd (finfo, input_bfd)
elf_swap_symbol_in (input_bfd, esym, isym);
*pindex = -1;
if (elf_bad_symtab (input_bfd))
{
if (ELF_ST_BIND (isym->st_info) != STB_LOCAL)
{
*ppsection = NULL;
continue;
}
}
if (isym->st_shndx == SHN_UNDEF)
isec = &bfd_und_section;
else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
@ -6084,7 +6127,9 @@ elf_link_input_bfd (finfo, input_bfd)
if (r_symndx == 0)
continue;
if (r_symndx >= symtab_hdr->sh_info)
if (r_symndx >= locsymcount
|| (elf_bad_symtab (input_bfd)
&& finfo->sections[r_symndx] == NULL))
{
long indx;
@ -6095,7 +6140,7 @@ elf_link_input_bfd (finfo, input_bfd)
reloc to point to the global hash table entry
for this symbol. The symbol index is then
set at the end of elf_bfd_final_link. */
indx = r_symndx - symtab_hdr->sh_info;
indx = r_symndx - extsymoff;
*rel_hash = elf_sym_hashes (input_bfd)[indx];
/* Setting the index to -2 tells