From 5315c42827694b2d9d25cf99f238de673fbe475c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 24 May 1994 20:44:50 +0000 Subject: 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. --- bfd/elfcode.h | 95 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 25 deletions(-) (limited to 'bfd/elfcode.h') diff --git a/bfd/elfcode.h b/bfd/elfcode.h index db0316a..21deffd 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -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 -- cgit v1.1