diff options
Diffstat (limited to 'bfd/elfcode.h')
-rw-r--r-- | bfd/elfcode.h | 198 |
1 files changed, 83 insertions, 115 deletions
diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 203323c..eb667eb 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1,6 +1,6 @@ /* ELF executable support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001 Free Software Foundation, Inc. + 2001, 2002 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -203,12 +203,14 @@ static char *elf_symbol_flags PARAMS ((flagword)); format. */ void -elf_swap_symbol_in (abfd, src, shndx, dst) +elf_swap_symbol_in (abfd, psrc, pshn, dst) bfd *abfd; - const Elf_External_Sym *src; - const Elf_External_Sym_Shndx *shndx; + const PTR psrc; + const PTR pshn; Elf_Internal_Sym *dst; { + const Elf_External_Sym *src = (const Elf_External_Sym *) psrc; + const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn; int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; dst->st_name = H_GET_32 (abfd, src->st_name); @@ -557,9 +559,9 @@ elf_object_p (abfd) section header table (FIXME: See comments re sections at top of this file). */ - if ((elf_file_p (&x_ehdr) == false) || - (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) || - (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)) + if (! elf_file_p (&x_ehdr) + || x_ehdr.e_ident[EI_VERSION] != EV_CURRENT + || x_ehdr.e_ident[EI_CLASS] != ELFCLASS) goto got_wrong_format_error; /* Check that file's byte order matches xvec's */ @@ -622,6 +624,10 @@ elf_object_p (abfd) if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0) goto got_wrong_format_error; + /* Further sanity check. */ + if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0) + goto got_wrong_format_error; + ebd = get_elf_backend_data (abfd); /* Check that the ELF e_machine field matches what this particular @@ -675,25 +681,28 @@ elf_object_p (abfd) /* Remember the entry point specified in the ELF file header. */ bfd_set_start_address (abfd, i_ehdrp->e_entry); - /* Seek to the section header table in the file. */ - if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) - goto got_no_match; + if (i_ehdrp->e_shoff != 0) + { + /* Seek to the section header table in the file. */ + if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) + goto got_no_match; - /* Read the first section header at index 0, and convert to internal - form. */ - if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd) - != sizeof (x_shdr)) - goto got_no_match; - elf_swap_shdr_in (abfd, &x_shdr, &i_shdr); + /* Read the first section header at index 0, and convert to internal + form. */ + if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd) + != sizeof (x_shdr)) + goto got_no_match; + elf_swap_shdr_in (abfd, &x_shdr, &i_shdr); - /* If the section count is zero, the actual count is in the first - section header. */ - if (i_ehdrp->e_shnum == SHN_UNDEF) - i_ehdrp->e_shnum = i_shdr.sh_size; + /* If the section count is zero, the actual count is in the first + section header. */ + if (i_ehdrp->e_shnum == SHN_UNDEF) + i_ehdrp->e_shnum = i_shdr.sh_size; - /* And similarly for the string table index. */ - if (i_ehdrp->e_shstrndx == SHN_XINDEX) - i_ehdrp->e_shstrndx = i_shdr.sh_link; + /* And similarly for the string table index. */ + if (i_ehdrp->e_shstrndx == SHN_XINDEX) + i_ehdrp->e_shstrndx = i_shdr.sh_link; + } /* Allocate space for a copy of the section header table in internal form. */ @@ -749,7 +758,7 @@ elf_object_p (abfd) } } - if (i_ehdrp->e_shstrndx) + if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff) { if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx)) goto got_no_match; @@ -787,7 +796,7 @@ elf_object_p (abfd) bfd_section_from_shdr with it (since this particular strtab is used to find all of the ELF section names.) */ - if (i_ehdrp->e_shstrndx != 0) + if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff) { unsigned int num_sec; @@ -812,7 +821,7 @@ elf_object_p (abfd) information. */ if (ebd->elf_backend_object_p) { - if ((*ebd->elf_backend_object_p) (abfd) == false) + if (! (*ebd->elf_backend_object_p) (abfd)) goto got_wrong_format_error; } @@ -1124,10 +1133,12 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) 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_Sym_Shndx *x_shndx = NULL; - Elf_External_Versym *x_versymp = NULL; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + Elf_Internal_Sym *isymbuf = NULL; + Elf_External_Versym *xver; + Elf_External_Versym *xverbuf = NULL; + struct elf_backend_data *ebd; bfd_size_type amt; /* Read each raw ELF symbol, converting from external ELF form to @@ -1142,24 +1153,8 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (! dynamic) { - Elf_Internal_Shdr *shndx_hdr; - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; verhdr = NULL; - - /* If we have a SHT_SYMTAB_SHNDX section for the symbol table, - read the raw contents. */ - if (elf_elfsections (abfd) != NULL - && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr) - { - amt = shndx_hdr->sh_size; - x_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (x_shndx == NULL - || bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) x_shndx, amt, abfd) != amt) - goto error_return; - } } else { @@ -1178,39 +1173,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) } } - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) - goto error_return; - + ebd = get_elf_backend_data (abfd); symcount = hdr->sh_size / sizeof (Elf_External_Sym); - if (symcount == 0) sym = symbase = NULL; else { - unsigned long i; - - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0) - goto error_return; + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + return -1; amt = symcount; amt *= sizeof (elf_symbol_type); symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt); if (symbase == (elf_symbol_type *) NULL) goto error_return; - sym = symbase; - - /* Temporarily allocate room for the raw ELF symbols. */ - amt = symcount; - amt *= sizeof (Elf_External_Sym); - x_symp = (Elf_External_Sym *) bfd_malloc (amt); - if (x_symp == NULL) - goto error_return; - - if (bfd_bread ((PTR) x_symp, amt, abfd) != amt) - goto error_return; /* Read the raw ELF version symbol information. */ - if (verhdr != NULL && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount) { @@ -1230,41 +1210,40 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) 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) + xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); + if (xverbuf == NULL && verhdr->sh_size != 0) goto error_return; - if (bfd_bread ((PTR) x_versymp, verhdr->sh_size, abfd) + if (bfd_bread ((PTR) xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size) goto error_return; } /* Skip first symbol, which is a null dummy. */ - for (i = 1; i < symcount; i++) + xver = xverbuf; + if (xver != NULL) + ++xver; + isymend = isymbuf + symcount; + for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++) { - elf_swap_symbol_in (abfd, x_symp + i, - x_shndx + (x_shndx != NULL ? i : 0), &i_sym); - memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym)); -#ifdef ELF_KEEP_EXTSYM - memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym)); -#endif + memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym)); sym->symbol.the_bfd = abfd; sym->symbol.name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, - i_sym.st_name); + isym->st_name); - sym->symbol.value = i_sym.st_value; + sym->symbol.value = isym->st_value; - if (i_sym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) { sym->symbol.section = bfd_und_section_ptr; } - else if (i_sym.st_shndx < SHN_LORESERVE - || i_sym.st_shndx > SHN_HIRESERVE) + else if (isym->st_shndx < SHN_LORESERVE + || isym->st_shndx > SHN_HIRESERVE) { sym->symbol.section = section_from_elf_index (abfd, - i_sym.st_shndx); + isym->st_shndx); if (sym->symbol.section == NULL) { /* This symbol is in a section for which we did not @@ -1273,18 +1252,18 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) sym->symbol.section = bfd_abs_section_ptr; } } - else if (i_sym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) { sym->symbol.section = bfd_abs_section_ptr; } - else if (i_sym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) { sym->symbol.section = bfd_com_section_ptr; /* Elf puts the alignment into the `value' field, and the size into the `size' field. BFD wants to see the size in the value field, and doesn't care (at the moment) about the alignment. */ - sym->symbol.value = i_sym.st_size; + sym->symbol.value = isym->st_size; } else sym->symbol.section = bfd_abs_section_ptr; @@ -1294,14 +1273,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) sym->symbol.value -= sym->symbol.section->vma; - switch (ELF_ST_BIND (i_sym.st_info)) + switch (ELF_ST_BIND (isym->st_info)) { case STB_LOCAL: sym->symbol.flags |= BSF_LOCAL; break; case STB_GLOBAL: - if (i_sym.st_shndx != SHN_UNDEF - && i_sym.st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON) sym->symbol.flags |= BSF_GLOBAL; break; case STB_WEAK: @@ -1309,7 +1287,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) break; } - switch (ELF_ST_TYPE (i_sym.st_info)) + switch (ELF_ST_TYPE (isym->st_info)) { case STT_SECTION: sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING; @@ -1328,31 +1306,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (dynamic) sym->symbol.flags |= BSF_DYNAMIC; - if (x_versymp != NULL) + if (xver != NULL) { Elf_Internal_Versym iversym; - _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym); + _bfd_elf_swap_versym_in (abfd, xver, &iversym); sym->version = iversym.vs_vers; + xver++; } /* Do some backend-specific processing on this symbol. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_processing) - (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); - } - - sym++; + if (ebd->elf_backend_symbol_processing) + (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); } } /* Do some backend-specific processing on this symbol table. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_table_processing) - (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); - } + if (ebd->elf_backend_symbol_table_processing) + (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); /* We rely on the zalloc to clear out the final symbol entry. */ @@ -1372,21 +1343,17 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) *symptrs = 0; /* Final null pointer */ } - if (x_shndx != NULL) - free (x_shndx); - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return symcount; error_return: - if (x_shndx != NULL) - free (x_shndx); - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return -1; } @@ -1695,6 +1662,7 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = { elf_write_out_phdrs, elf_write_shdrs_and_ehdr, elf_write_relocs, + elf_swap_symbol_in, elf_swap_symbol_out, elf_slurp_reloc_table, elf_slurp_symbol_table, |