diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2000-09-12 19:13:03 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2000-09-12 19:13:03 +0000 |
commit | 1b50fce4c0ed748c156af3ac629e50cb5e4d0ef4 (patch) | |
tree | edee61faabd18b4a5d84e8cdb679d7a8d1fe171f /gnu/usr.bin/binutils/bfd/elfcode.h | |
parent | 9f1193e30b5f04af9ea81c644eec79b7b535b890 (diff) |
Help stupid cvs fixing basic conflicts.
Diffstat (limited to 'gnu/usr.bin/binutils/bfd/elfcode.h')
-rw-r--r-- | gnu/usr.bin/binutils/bfd/elfcode.h | 324 |
1 files changed, 271 insertions, 53 deletions
diff --git a/gnu/usr.bin/binutils/bfd/elfcode.h b/gnu/usr.bin/binutils/bfd/elfcode.h index c0daa2ac197..c5edf9b8250 100644 --- a/gnu/usr.bin/binutils/bfd/elfcode.h +++ b/gnu/usr.bin/binutils/bfd/elfcode.h @@ -1,5 +1,6 @@ /* ELF executable support for BFD. - Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software + Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -123,6 +124,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define elf_bfd_final_link NAME(bfd_elf,bfd_final_link) #define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section) #define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section) +#define elf_gc_sections NAME(_bfd_elf,gc_sections) +#define elf_gc_common_finalize_got_offsets \ + NAME(_bfd_elf,gc_common_finalize_got_offsets) +#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link) +#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit) +#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry) +#define elf_link_record_local_dynamic_symbol \ + NAME(_bfd_elf,link_record_local_dynamic_symbol) #if ARCH_SIZE == 64 #define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) @@ -141,7 +150,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define LOG_FILE_ALIGN 2 #endif -/* Forward declarations of static functions */ +/* Static functions */ static void elf_swap_ehdr_in PARAMS ((bfd *, const Elf_External_Ehdr *, Elf_Internal_Ehdr *)); @@ -156,10 +165,16 @@ static void elf_swap_shdr_out #define section_from_elf_index bfd_section_from_elf_index -static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **)); +static boolean elf_slurp_reloc_table_from_section + PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, + arelent *, asymbol **, boolean)); +static boolean elf_slurp_reloc_table + PARAMS ((bfd *, asection *, asymbol **, boolean)); static void write_relocs PARAMS ((bfd *, asection *, PTR)); +static boolean elf_file_p PARAMS ((Elf_External_Ehdr *)); + #ifdef DEBUG static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *)); static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); @@ -172,11 +187,15 @@ static char *elf_symbol_flags PARAMS ((flagword)); can be handled by explicitly specifying 32 bits or "the long type". */ #if ARCH_SIZE == 64 #define put_word bfd_h_put_64 +#define put_signed_word bfd_h_put_signed_64 #define get_word bfd_h_get_64 +#define get_signed_word bfd_h_get_signed_64 #endif #if ARCH_SIZE == 32 #define put_word bfd_h_put_32 +#define put_signed_word bfd_h_put_signed_32 #define get_word bfd_h_get_32 +#define get_signed_word bfd_h_get_signed_32 #endif /* Translate an ELF symbol in external format into an ELF symbol in internal @@ -188,8 +207,13 @@ elf_swap_symbol_in (abfd, src, dst) const Elf_External_Sym *src; Elf_Internal_Sym *dst; { + int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; + dst->st_name = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name); - dst->st_value = get_word (abfd, (bfd_byte *) src->st_value); + if (signed_vma) + dst->st_value = get_signed_word (abfd, (bfd_byte *) src->st_value); + else + dst->st_value = get_word (abfd, (bfd_byte *) src->st_value); dst->st_size = get_word (abfd, (bfd_byte *) src->st_size); dst->st_info = bfd_h_get_8 (abfd, (bfd_byte *) src->st_info); dst->st_other = bfd_h_get_8 (abfd, (bfd_byte *) src->st_other); @@ -276,10 +300,15 @@ elf_swap_shdr_in (abfd, src, dst) const Elf_External_Shdr *src; Elf_Internal_Shdr *dst; { + int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; + dst->sh_name = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name); dst->sh_type = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_type); dst->sh_flags = get_word (abfd, (bfd_byte *) src->sh_flags); - dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr); + if (signed_vma) + dst->sh_addr = get_signed_word (abfd, (bfd_byte *) src->sh_addr); + else + dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr); dst->sh_offset = get_word (abfd, (bfd_byte *) src->sh_offset); dst->sh_size = get_word (abfd, (bfd_byte *) src->sh_size); dst->sh_link = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_link); @@ -322,11 +351,21 @@ elf_swap_phdr_in (abfd, src, dst) const Elf_External_Phdr *src; Elf_Internal_Phdr *dst; { + int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; + dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type); dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags); dst->p_offset = get_word (abfd, (bfd_byte *) src->p_offset); - dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr); - dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr); + if (signed_vma) + { + dst->p_vaddr = get_signed_word (abfd, (bfd_byte *) src->p_vaddr); + dst->p_paddr = get_signed_word (abfd, (bfd_byte *) src->p_paddr); + } + else + { + dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr); + dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr); + } dst->p_filesz = get_word (abfd, (bfd_byte *) src->p_filesz); dst->p_memsz = get_word (abfd, (bfd_byte *) src->p_memsz); dst->p_align = get_word (abfd, (bfd_byte *) src->p_align); @@ -368,7 +407,7 @@ elf_swap_reloca_in (abfd, src, dst) { dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset); dst->r_info = get_word (abfd, (bfd_byte *) src->r_info); - dst->r_addend = get_word (abfd, (bfd_byte *) src->r_addend); + dst->r_addend = get_signed_word (abfd, (bfd_byte *) src->r_addend); } /* Translate an ELF reloc from internal format to external format. */ @@ -390,7 +429,7 @@ elf_swap_reloca_out (abfd, src, dst) { put_word (abfd, src->r_offset, dst->r_offset); put_word (abfd, src->r_info, dst->r_info); - put_word (abfd, src->r_addend, dst->r_addend); + put_signed_word (abfd, src->r_addend, dst->r_addend); } INLINE void @@ -406,11 +445,13 @@ elf_swap_dyn_in (abfd, p, dst) } INLINE void -elf_swap_dyn_out (abfd, src, dst) +elf_swap_dyn_out (abfd, src, p) bfd *abfd; const Elf_Internal_Dyn *src; - Elf_External_Dyn *dst; + PTR p; { + Elf_External_Dyn *dst = (Elf_External_Dyn *) p; + put_word (abfd, src->d_tag, dst->d_tag); put_word (abfd, src->d_un.d_val, dst->d_un.d_val); } @@ -454,6 +495,7 @@ elf_object_p (abfd) struct elf_backend_data *ebd; struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd); struct elf_obj_tdata *new_tdata = NULL; + asection *s; /* Read in the ELF header in external format. */ @@ -508,6 +550,10 @@ elf_object_p (abfd) elf_debug_file (i_ehdrp); #endif + /* Reject ET_CORE (header indicates core file, not object file) */ + if (i_ehdrp->e_type == ET_CORE) + goto got_wrong_format_error; + /* If there is no section header table, we're hosed. */ if (i_ehdrp->e_shoff == 0) goto got_wrong_format_error; @@ -562,7 +608,11 @@ elf_object_p (abfd) abfd->flags |= D_PAGED; if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)) - goto got_no_match; + { + /* It's OK if this fails for the generic target. */ + if (ebd->elf_machine_code != EM_NONE) + goto got_no_match; + } /* Remember the entry point specified in the ELF file header. */ bfd_get_start_address (abfd) = i_ehdrp->e_entry; @@ -657,12 +707,30 @@ elf_object_p (abfd) goto got_wrong_format_error; } + /* If we have created any reloc sections that are associated with + debugging sections, mark the reloc sections as debugging as well. */ + for (s = abfd->sections; s != NULL; s = s->next) + { + if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL + || elf_section_data (s)->this_hdr.sh_type == SHT_RELA) + && elf_section_data (s)->this_hdr.sh_info > 0) + { + unsigned long targ_index; + asection *targ_sec; + + targ_index = elf_section_data (s)->this_hdr.sh_info; + targ_sec = bfd_section_from_elf_index (abfd, targ_index); + if (targ_sec != NULL + && (targ_sec->flags & SEC_DEBUGGING) != 0) + s->flags |= SEC_DEBUGGING; + } + } + return (abfd->xvec); -got_wrong_format_error: + got_wrong_format_error: bfd_set_error (bfd_error_wrong_format); - goto got_no_match; -got_no_match: + got_no_match: if (new_tdata != NULL && new_tdata->elf_sect_ptr != NULL) bfd_release (abfd, new_tdata->elf_sect_ptr); @@ -689,7 +757,7 @@ write_relocs (abfd, sec, data) Elf_External_Rela *outbound_relocas; Elf_External_Rel *outbound_relocs; unsigned int idx; - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; + int use_rela_p; asymbol *last_sym = 0; int last_sym_idx = 0; @@ -717,6 +785,16 @@ write_relocs (abfd, sec, data) return; } + /* Figure out whether the relocations are RELA or REL relocations. */ + if (rela_hdr->sh_type == SHT_RELA) + use_rela_p = true; + else if (rela_hdr->sh_type == SHT_REL) + use_rela_p = false; + else + /* Every relocation section should be either an SHT_RELA or an + SHT_REL section. */ + abort (); + /* orelocation has the data, reloc_count has the count... */ if (use_rela_p) { @@ -799,6 +877,8 @@ write_relocs (abfd, sec, data) if (sym == last_sym) n = last_sym_idx; + else if (bfd_is_abs_section (sym->section) && sym->value == 0) + n = STN_UNDEF; else { last_sym = sym; @@ -811,7 +891,8 @@ write_relocs (abfd, sec, data) last_sym_idx = n; } - if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec + if ((*ptr->sym_ptr_ptr)->the_bfd != NULL + && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec && ! _bfd_elf_validate_reloc (abfd, ptr)) { *failedp = true; @@ -901,11 +982,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) boolean dynamic; { Elf_Internal_Shdr *hdr; - long symcount; /* Number of external ELF symbols */ + Elf_Internal_Shdr *verhdr; + unsigned long symcount; /* Number of external ELF symbols */ elf_symbol_type *sym; /* Pointer to current bfd symbol */ elf_symbol_type *symbase; /* Buffer for generated bfd symbols */ Elf_Internal_Sym i_sym; Elf_External_Sym *x_symp = NULL; + Elf_External_Versym *x_versymp = NULL; /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a @@ -917,10 +1000,28 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) space left over at the end. When we have all the symbols, we build the caller's pointer vector. */ - if (dynamic) - hdr = &elf_tdata (abfd)->dynsymtab_hdr; + if (! dynamic) + { + hdr = &elf_tdata (abfd)->symtab_hdr; + verhdr = NULL; + } else - hdr = &elf_tdata (abfd)->symtab_hdr; + { + hdr = &elf_tdata (abfd)->dynsymtab_hdr; + if (elf_dynversym (abfd) == 0) + verhdr = NULL; + else + verhdr = &elf_tdata (abfd)->dynversym_hdr; + if ((elf_tdata (abfd)->dynverdef_section != 0 + && elf_tdata (abfd)->verdef == NULL) + || (elf_tdata (abfd)->dynverref_section != 0 + && elf_tdata (abfd)->verref == NULL)) + { + if (! _bfd_elf_slurp_version_tables (abfd)) + return -1; + } + } + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) return -1; @@ -930,7 +1031,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) sym = symbase = NULL; else { - long i; + unsigned long i; if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) return -1; @@ -950,6 +1051,37 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) != symcount * sizeof (Elf_External_Sym)) goto error_return; + + /* Read the raw ELF version symbol information. */ + + if (verhdr != NULL + && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount) + { + (*_bfd_error_handler) + (_("%s: version count (%ld) does not match symbol count (%ld)"), + abfd->filename, + (long) (verhdr->sh_size / sizeof (Elf_External_Versym)), + symcount); + + /* Slurp in the symbols without the version information, + since that is more helpful than just quitting. */ + verhdr = NULL; + } + + if (verhdr != NULL) + { + if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) + goto error_return; + + x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); + if (x_versymp == NULL && verhdr->sh_size != 0) + goto error_return; + + if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd) + != verhdr->sh_size) + goto error_return; + } + /* Skip first symbol, which is a null dummy. */ for (i = 1; i < symcount; i++) { @@ -998,7 +1130,10 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) else sym->symbol.section = bfd_abs_section_ptr; - sym->symbol.value -= sym->symbol.section->vma; + /* If this is a relocateable file, then the symbol value is + already section relative. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) + sym->symbol.value -= sym->symbol.section->vma; switch (ELF_ST_BIND (i_sym.st_info)) { @@ -1034,6 +1169,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (dynamic) sym->symbol.flags |= BSF_DYNAMIC; + if (x_versymp != NULL) + { + Elf_Internal_Versym iversym; + + _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym); + sym->version = iversym.vs_vers; + } + /* Do some backend-specific processing on this symbol. */ { struct elf_backend_data *ebd = get_elf_backend_data (abfd); @@ -1070,63 +1213,57 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) *symptrs = 0; /* Final null pointer */ } + if (x_versymp != NULL) + free (x_versymp); if (x_symp != NULL) free (x_symp); return symcount; error_return: + if (x_versymp != NULL) + free (x_versymp); if (x_symp != NULL) free (x_symp); return -1; } -/* Read in and swap the external relocs. */ +/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of + them. */ static boolean -elf_slurp_reloc_table (abfd, asect, symbols) +elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, + relents, symbols, dynamic) bfd *abfd; asection *asect; + Elf_Internal_Shdr *rel_hdr; + bfd_size_type reloc_count; + arelent *relents; asymbol **symbols; + boolean dynamic; { struct elf_backend_data * const ebd = get_elf_backend_data (abfd); - struct bfd_elf_section_data * const d = elf_section_data (asect); PTR allocated = NULL; bfd_byte *native_relocs; - arelent *relents; arelent *relent; unsigned int i; int entsize; - if (asect->relocation != NULL - || (asect->flags & SEC_RELOC) == 0 - || asect->reloc_count == 0) - return true; - - BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset - && (asect->reloc_count - == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize)); - - allocated = (PTR) bfd_malloc ((size_t) d->rel_hdr.sh_size); + allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size); if (allocated == NULL) goto error_return; - if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0 - || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd) - != d->rel_hdr.sh_size)) + if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) + != rel_hdr->sh_size)) goto error_return; native_relocs = (bfd_byte *) allocated; - relents = ((arelent *) - bfd_alloc (abfd, asect->reloc_count * sizeof (arelent))); - if (relents == NULL) - goto error_return; - - entsize = d->rel_hdr.sh_entsize; + entsize = rel_hdr->sh_entsize; BFD_ASSERT (entsize == sizeof (Elf_External_Rel) || entsize == sizeof (Elf_External_Rela)); for (i = 0, relent = relents; - i < asect->reloc_count; + i < reloc_count; i++, relent++, native_relocs += entsize) { Elf_Internal_Rela rela; @@ -1144,8 +1281,9 @@ elf_slurp_reloc_table (abfd, asect, symbols) /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. - The address of a BFD reloc is always section relative. */ - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + The address of a normal BFD reloc is always section relative, + and the address of a dynamic reloc is absolute.. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic) relent->address = rela.r_offset; else relent->address = rela.r_offset - asect->vma; @@ -1174,8 +1312,6 @@ elf_slurp_reloc_table (abfd, asect, symbols) (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel); } - asect->relocation = relents; - if (allocated != NULL) free (allocated); @@ -1187,6 +1323,82 @@ elf_slurp_reloc_table (abfd, asect, symbols) return false; } +/* Read in and swap the external relocs. */ + +static boolean +elf_slurp_reloc_table (abfd, asect, symbols, dynamic) + bfd *abfd; + asection *asect; + asymbol **symbols; + boolean dynamic; +{ + struct bfd_elf_section_data * const d = elf_section_data (asect); + Elf_Internal_Shdr *rel_hdr; + Elf_Internal_Shdr *rel_hdr2; + bfd_size_type reloc_count; + bfd_size_type reloc_count2; + arelent *relents; + + if (asect->relocation != NULL) + return true; + + if (! dynamic) + { + if ((asect->flags & SEC_RELOC) == 0 + || asect->reloc_count == 0) + return true; + + rel_hdr = &d->rel_hdr; + reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize; + rel_hdr2 = d->rel_hdr2; + reloc_count2 = (rel_hdr2 + ? (rel_hdr2->sh_size / rel_hdr2->sh_entsize) + : 0); + + BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2); + BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); + + } + else + { + /* Note that ASECT->RELOC_COUNT tends not to be accurate in this + case because relocations against this section may use the + dynamic symbol table, and in that case bfd_section_from_shdr + in elf.c does not update the RELOC_COUNT. */ + if (asect->_raw_size == 0) + return true; + + rel_hdr = &d->this_hdr; + reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize; + rel_hdr2 = NULL; + reloc_count2 = 0; + } + + relents = ((arelent *) + bfd_alloc (abfd, + (reloc_count + reloc_count2) * sizeof (arelent))); + if (relents == NULL) + return false; + + if (!elf_slurp_reloc_table_from_section (abfd, asect, + rel_hdr, reloc_count, + relents, + symbols, dynamic)) + return false; + + if (rel_hdr2 + && !elf_slurp_reloc_table_from_section (abfd, asect, + rel_hdr2, reloc_count2, + relents + reloc_count, + symbols, dynamic)) + return false; + + + asect->relocation = relents; + return true; +} + #ifdef DEBUG static void elf_debug_section (num, hdr) @@ -1315,7 +1527,8 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = { sizeof (Elf_External_Sym), sizeof (Elf_External_Dyn), sizeof (Elf_External_Note), - + ARCH_SIZE / 8, + 1, ARCH_SIZE, FILE_ALIGN, ELFCLASS, EV_CURRENT, elf_write_out_phdrs, @@ -1324,5 +1537,10 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = { elf_swap_symbol_out, elf_slurp_reloc_table, elf_slurp_symbol_table, - elf_swap_dyn_in + elf_swap_dyn_in, + elf_swap_dyn_out, + NULL, + NULL, + NULL, + NULL }; |