From bcc2cc8eff34eec7072665903fa6f6f6df6f0401 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Fri, 27 Apr 2007 19:57:40 +0000 Subject: [PATCH] * elf32-xtensa.c (xtensa_read_table_entries): Step through table contents and relocs in parallel. --- bfd/ChangeLog | 5 +++ bfd/elf32-xtensa.c | 102 ++++++++++++++++++++++----------------------- 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 07ded055a45..55849ace938 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2007-04-27 Bob Wilson + + * elf32-xtensa.c (xtensa_read_table_entries): Step through table + contents and relocs in parallel. + 2007-04-27 Bob Wilson * elf32-xtensa.c (relax_property_section): Remove extra irel increment. diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index c773e3c7d0a..3b522994428 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -612,10 +612,10 @@ xtensa_read_table_entries (bfd *abfd, property_table_entry *blocks; int blk, block_count; bfd_size_type num_records; - Elf_Internal_Rela *internal_relocs; - bfd_vma section_addr; + Elf_Internal_Rela *internal_relocs, *irel, *rel_end; + bfd_vma section_addr, off; flagword predef_flags; - bfd_size_type table_entry_size; + bfd_size_type table_entry_size, section_limit; if (!section || !(section->flags & SEC_ALLOC) @@ -651,67 +651,63 @@ xtensa_read_table_entries (bfd *abfd, else section_addr = section->vma; - /* If the file has not yet been relocated, process the relocations - and sort out the table entries that apply to the specified section. */ internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE); if (internal_relocs && !table_section->reloc_done) { - unsigned i; - - for (i = 0; i < table_section->reloc_count; i++) - { - Elf_Internal_Rela *rel = &internal_relocs[i]; - unsigned long r_symndx; + qsort (internal_relocs, table_section->reloc_count, + sizeof (Elf_Internal_Rela), internal_reloc_compare); + irel = internal_relocs; + } + else + irel = NULL; - if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE) - continue; + section_limit = bfd_get_section_limit (abfd, section); + rel_end = internal_relocs + table_section->reloc_count; - BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32); - r_symndx = ELF32_R_SYM (rel->r_info); + for (off = 0; off < table_size; off += table_entry_size) + { + bfd_vma address = bfd_get_32 (abfd, table_data + off); - if (get_elf_r_symndx_section (abfd, r_symndx) == section) - { - bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx); - BFD_ASSERT (sym_off == 0); - blocks[block_count].address = - (section_addr + sym_off + rel->r_addend - + bfd_get_32 (abfd, table_data + rel->r_offset)); - blocks[block_count].size = - bfd_get_32 (abfd, table_data + rel->r_offset + 4); - if (predef_flags) - blocks[block_count].flags = predef_flags; - else - blocks[block_count].flags = - bfd_get_32 (abfd, table_data + rel->r_offset + 8); - block_count++; - } + /* Skip any relocations before the current offset. This should help + avoid confusion caused by unexpected relocations for the preceding + table entry. */ + while (irel && + (irel->r_offset < off + || (irel->r_offset == off + && ELF32_R_TYPE (irel->r_info) == R_XTENSA_NONE))) + { + irel += 1; + if (irel >= rel_end) + irel = 0; } - } - else - { - /* The file has already been relocated and the addresses are - already in the table. */ - bfd_vma off; - bfd_size_type section_limit = bfd_get_section_limit (abfd, section); - for (off = 0; off < table_size; off += table_entry_size) + if (irel && irel->r_offset == off) { - bfd_vma address = bfd_get_32 (abfd, table_data + off); + bfd_vma sym_off; + unsigned long r_symndx = ELF32_R_SYM (irel->r_info); + BFD_ASSERT (ELF32_R_TYPE (irel->r_info) == R_XTENSA_32); - if (address >= section_addr - && address < section_addr + section_limit) - { - blocks[block_count].address = address; - blocks[block_count].size = - bfd_get_32 (abfd, table_data + off + 4); - if (predef_flags) - blocks[block_count].flags = predef_flags; - else - blocks[block_count].flags = - bfd_get_32 (abfd, table_data + off + 8); - block_count++; - } + if (get_elf_r_symndx_section (abfd, r_symndx) != section) + continue; + + sym_off = get_elf_r_symndx_offset (abfd, r_symndx); + BFD_ASSERT (sym_off == 0); + address += (section_addr + sym_off + irel->r_addend); } + else + { + if (address < section_addr + || address >= section_addr + section_limit) + continue; + } + + blocks[block_count].address = address; + blocks[block_count].size = bfd_get_32 (abfd, table_data + off + 4); + if (predef_flags) + blocks[block_count].flags = predef_flags; + else + blocks[block_count].flags = bfd_get_32 (abfd, table_data + off + 8); + block_count++; } release_contents (table_section, table_data); -- 2.30.2