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.
+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
return bfd_reloc_continue;
}
\f
-/* 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;
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 *
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;
}
/* 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. */
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:
/* 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. */
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;
/* 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)
}
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)))
{
/* 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;
/* 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)
{
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
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;
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;
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)
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;
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
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)
#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)
\f
extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned));
extern char * elf_get_str_section PARAMS ((bfd *, unsigned));
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 *));