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

@ -1,3 +1,57 @@
Tue May 24 16:17:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
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.
Fri May 20 13:38:23 1994 Jeff Law (law@snake.cs.utah.edu)
* som.c (som_set_reloc_info): Do not set any relocation info

View File

@ -301,15 +301,10 @@ bfd_elf_generic_reloc (abfd,
return bfd_reloc_continue;
}
/* Generic ELF link code. */
static struct bfd_hash_entry *elf_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
/* Create an entry in an ELF linker hash table. */
static struct bfd_hash_entry *
elf_link_hash_newfunc (entry, table, string)
struct bfd_hash_entry *
_bfd_elf_link_hash_newfunc (entry, table, string)
struct bfd_hash_entry *entry;
struct bfd_hash_table *table;
const char *string;
@ -347,6 +342,23 @@ elf_link_hash_newfunc (entry, table, string)
return (struct bfd_hash_entry *) ret;
}
/* Initialize an ELF linker hash table. */
boolean
_bfd_elf_link_hash_table_init (table, abfd, newfunc)
struct elf_link_hash_table *table;
bfd *abfd;
struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *));
{
table->dynobj = NULL;
table->dynsymcount = 0;
table->dynstr = NULL;
table->bucketcount = 0;
return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
}
/* Create an ELF linker hash table. */
struct bfd_link_hash_table *
@ -362,17 +374,12 @@ _bfd_elf_link_hash_table_create (abfd)
bfd_set_error (bfd_error_no_memory);
return NULL;
}
if (! _bfd_link_hash_table_init (&ret->root, abfd,
elf_link_hash_newfunc))
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
{
bfd_release (abfd, ret);
return NULL;
}
ret->dynobj = NULL;
ret->dynsymcount = 0;
ret->dynstr = NULL;
ret->bucketcount = 0;
return &ret->root;
}

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

View File

@ -416,6 +416,13 @@ struct elf_obj_tdata
table, used when linking. This is indexed by the symbol index
minus the sh_info field of the symbol table header. */
struct elf_link_hash_entry **sym_hashes;
/* Irix 5 often screws up the symbol table, sorting local symbols
after global symbols. This flag is set if the symbol table in
this BFD appears to be screwed up. If it is, we ignore the
sh_info field in the symbol table header, and always read all the
symbols. */
boolean bad_symtab;
};
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
@ -434,6 +441,7 @@ struct elf_obj_tdata
#define elf_gp(bfd) (elf_tdata(bfd) -> gp)
#define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size)
#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes)
#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned));
extern char * elf_get_str_section PARAMS ((bfd *, unsigned));
@ -455,8 +463,15 @@ extern boolean bfd_elf_mkobject PARAMS ((bfd *));
extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *));
extern boolean _bfd_elf_make_section_from_shdr
PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, const char *name));
extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create
PARAMS ((bfd *));
extern boolean _bfd_elf_link_hash_table_init
PARAMS ((struct elf_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *)));
extern boolean bfd_elf32_write_object_contents PARAMS ((bfd *));
extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *));