diff options
-rw-r--r-- | bfd/ChangeLog | 14 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 4 | ||||
-rw-r--r-- | bfd/elf.c | 123 | ||||
-rw-r--r-- | bfd/elfcode.h | 19 |
4 files changed, 94 insertions, 66 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 461b27c..b13e41c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2005-02-07 Alan Modra <amodra@bigpond.net.au> + + * elf-bfd.h (elf_string_from_elf_strtab): Delete macro. + * elf.c (bfd_elf_string_from_elf_section): Expand occurrence of + elf_string_from_elf_strtab. + (_bfd_elf_setup_group_pointers, bfd_section_from_shdr): Likewise. + (bfd_section_from_shdr): For SHT_SYMTAB, load SHT_SYMTAB_SHNDX too + if it exists. Don't do the reverse for SHT_SYMTAB_SHNDX. For + SHT_STRTAB, check whether the strtab is for symtab or dynsymtab by + looking at cached symtab info first, before iterating over headers. + For SHT_REL and SHT_RELA, load dynsymtab if needed. + * elfcode.h (elf_object_p): Don't load section header stringtab + specially. + 2005-02-06 H.J. Lu <hongjiu.lu@intel.com> * elf32-i386.c (elf_i386_relocate_section): Disallow R_386_GOTOFF diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index e4d81a9..42caa3c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1378,10 +1378,6 @@ extern bfd_boolean _bfd_elf_print_private_bfd_data extern void bfd_elf_print_symbol (bfd *, void *, asymbol *, bfd_print_symbol_type); -#define elf_string_from_elf_strtab(abfd, strindex) \ - bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, \ - strindex) - extern void _bfd_elf_sprintf_vma (bfd *, char *, bfd_vma); extern void _bfd_elf_fprintf_vma @@ -291,13 +291,13 @@ bfd_elf_string_from_elf_section (bfd *abfd, if (strindex >= hdr->sh_size) { + unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx; (*_bfd_error_handler) (_("%B: invalid string offset %u >= %lu for section `%s'"), abfd, strindex, (unsigned long) hdr->sh_size, - ((shindex == elf_elfheader(abfd)->e_shstrndx - && strindex == hdr->sh_name) + (shindex == shstrndx && strindex == hdr->sh_name ? ".shstrtab" - : elf_string_from_elf_strtab (abfd, hdr->sh_name))); + : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name))); return ""; } @@ -650,7 +650,10 @@ _bfd_elf_setup_group_pointers (bfd *abfd) (_("%B: unknown [%d] section `%s' in group [%s]"), abfd, (unsigned int) idx->shdr->sh_type, - elf_string_from_elf_strtab (abfd, idx->shdr->sh_name), + bfd_elf_string_from_elf_section (abfd, + (elf_elfheader (abfd) + ->e_shstrndx), + idx->shdr->sh_name), shdr->bfd_section->name); result = FALSE; } @@ -1706,7 +1709,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) const struct elf_backend_data *bed = get_elf_backend_data (abfd); const char *name; - name = elf_string_from_elf_strtab (abfd, hdr->sh_name); + name = bfd_elf_string_from_elf_section (abfd, + elf_elfheader (abfd)->e_shstrndx, + hdr->sh_name); switch (hdr->sh_type) { @@ -1779,6 +1784,32 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) return FALSE; + /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we + can't read symbols without that section loaded as well. It + is most likely specified by the next section header. */ + if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex) + { + unsigned int i, num_sec; + + num_sec = elf_numsections (abfd); + for (i = shindex + 1; i < num_sec; i++) + { + Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; + if (hdr2->sh_type == SHT_SYMTAB_SHNDX + && hdr2->sh_link == shindex) + break; + } + if (i == num_sec) + for (i = 1; i < shindex; i++) + { + Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; + if (hdr2->sh_type == SHT_SYMTAB_SHNDX + && hdr2->sh_link == shindex) + break; + } + if (i != shindex) + return bfd_section_from_shdr (abfd, i); + } return TRUE; case SHT_DYNSYM: /* A dynamic symbol table */ @@ -1800,11 +1831,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) if (elf_symtab_shndx (abfd) == shindex) return TRUE; - /* Get the associated symbol table. */ - if (! bfd_section_from_shdr (abfd, hdr->sh_link) - || hdr->sh_link != elf_onesymtab (abfd)) - return FALSE; - + BFD_ASSERT (elf_symtab_shndx (abfd) == 0); elf_symtab_shndx (abfd) = shindex; elf_tdata (abfd)->symtab_shndx_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr; @@ -1819,37 +1846,46 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr; return TRUE; } - { - unsigned int i, num_sec; + if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex) + { + symtab_strtab: + elf_tdata (abfd)->strtab_hdr = *hdr; + elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr; + return TRUE; + } + if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex) + { + dynsymtab_strtab: + elf_tdata (abfd)->dynstrtab_hdr = *hdr; + hdr = &elf_tdata (abfd)->dynstrtab_hdr; + elf_elfsections (abfd)[shindex] = hdr; + /* We also treat this as a regular section, so that objcopy + can handle it. */ + return _bfd_elf_make_section_from_shdr (abfd, hdr, name); + } - num_sec = elf_numsections (abfd); - for (i = 1; i < num_sec; i++) - { - Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; - if (hdr2->sh_link == shindex) - { - if (! bfd_section_from_shdr (abfd, i)) - return FALSE; - if (elf_onesymtab (abfd) == i) - { - elf_tdata (abfd)->strtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = - &elf_tdata (abfd)->strtab_hdr; - return TRUE; - } - if (elf_dynsymtab (abfd) == i) - { - elf_tdata (abfd)->dynstrtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = hdr = - &elf_tdata (abfd)->dynstrtab_hdr; - /* We also treat this as a regular section, so - that objcopy can handle it. */ - break; - } - } - } - } + /* If the string table isn't one of the above, then treat it as a + regular section. We need to scan all the headers to be sure, + just in case this strtab section appeared before the above. */ + if (elf_onesymtab (abfd) == 0 || elf_dynsymtab (abfd) == 0) + { + unsigned int i, num_sec; + num_sec = elf_numsections (abfd); + for (i = 1; i < num_sec; i++) + { + Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; + if (hdr2->sh_link == shindex) + { + if (! bfd_section_from_shdr (abfd, i)) + return FALSE; + if (elf_onesymtab (abfd) == i) + goto symtab_strtab; + if (elf_dynsymtab (abfd) == i) + goto dynsymtab_strtab; + } + } + } return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_REL: @@ -1902,7 +1938,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } /* Get the symbol table. */ - if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB + if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB + || elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM) && ! bfd_section_from_shdr (abfd, hdr->sh_link)) return FALSE; @@ -2001,10 +2038,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) default: /* Check for any processor-specific section types. */ - { - if (bed->elf_backend_section_from_shdr) - (*bed->elf_backend_section_from_shdr) (abfd, hdr, name); - } + if (bed->elf_backend_section_from_shdr) + (*bed->elf_backend_section_from_shdr) (abfd, hdr, name); break; } diff --git a/bfd/elfcode.h b/bfd/elfcode.h index e1e995a..87b2663 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -475,7 +475,6 @@ elf_object_p (bfd *abfd) Elf_Internal_Shdr i_shdr; Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ unsigned int shindex; - char *shstrtab; /* Internal copy of section header stringtab */ const struct elf_backend_data *ebd; struct bfd_preserve preserve; asection *s; @@ -686,12 +685,6 @@ elf_object_p (bfd *abfd) } } - if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff) - { - if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx)) - goto got_no_match; - } - /* Read in the program headers. */ if (i_ehdrp->e_phnum == 0) elf_tdata (abfd)->phdr = NULL; @@ -717,20 +710,10 @@ elf_object_p (bfd *abfd) } } - /* Read in the string table containing the names of the sections. We - will need the base pointer to this table later. */ - /* We read this inline now, so that we don't have to go through - 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 && i_ehdrp->e_shoff) + if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff != 0) { unsigned int num_sec; - shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx); - if (!shstrtab) - goto got_no_match; - /* Once all of the section headers have been read and converted, we can start processing them. Note that the first section header is a dummy placeholder entry, so we ignore it. */ |