diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-05-24 20:44:50 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-05-24 20:44:50 +0000 |
commit | 5315c42827694b2d9d25cf99f238de673fbe475c (patch) | |
tree | ae7c88d0caca8b07e70c20bc34d922a9af1ad081 /bfd/elfcode.h | |
parent | f49f58c6a8ffdc40d3f11ffe9e5de782ef5e0017 (diff) | |
download | gdb-5315c42827694b2d9d25cf99f238de673fbe475c.zip gdb-5315c42827694b2d9d25cf99f238de673fbe475c.tar.gz gdb-5315c42827694b2d9d25cf99f238de673fbe475c.tar.bz2 |
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.
Diffstat (limited to 'bfd/elfcode.h')
-rw-r--r-- | bfd/elfcode.h | 95 |
1 files changed, 70 insertions, 25 deletions
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 |