diff options
author | paulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-18 22:07:53 +0000 |
---|---|---|
committer | paulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-18 22:07:53 +0000 |
commit | a8e80416be9ccd606ce54f7f192b91133bb23b98 (patch) | |
tree | 0972d2fe6b393a5e07e7a1267be5b616643b7eec /courgette/disassembler_elf_32_arm.cc | |
parent | ba79a799579a5417511d472071e3f8fc5e2b67a5 (diff) | |
download | chromium_src-a8e80416be9ccd606ce54f7f192b91133bb23b98.zip chromium_src-a8e80416be9ccd606ce54f7f192b91133bb23b98.tar.gz chromium_src-a8e80416be9ccd606ce54f7f192b91133bb23b98.tar.bz2 |
Fixed Courgette to correctly regenerate the ELF relocation table for
ARM binaries.
Note for reviewers:
Don: general courgette correctness
Ben: style, correctness
BUG=258648
Review URL: https://chromiumcodereview.appspot.com/19022007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212449 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/disassembler_elf_32_arm.cc')
-rw-r--r-- | courgette/disassembler_elf_32_arm.cc | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/courgette/disassembler_elf_32_arm.cc b/courgette/disassembler_elf_32_arm.cc index b321e06..f271020 100644 --- a/courgette/disassembler_elf_32_arm.cc +++ b/courgette/disassembler_elf_32_arm.cc @@ -51,20 +51,20 @@ CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { CheckBool DisassemblerElf32ARM::ParseRelocationSection( const Elf32_Shdr *section_header, AssemblyProgram* program) { - // We can reproduce the R_386_RELATIVE entries in one of the relocation - // table based on other information in the patch, given these - // conditions.... - // - // All R_386_RELATIVE entries are: - // 1) In the same relocation table - // 2) Are consecutive - // 3) Are sorted in memory address order + // This method compresses a contiguous stretch of R_ARM_RELATIVE + // entries in the relocation table with a Courgette relocation table + // instruction. It skips any entries at the beginning that appear + // in a section that Courgette doesn't support, e.g. INIT. + // Specifically, the entries should be + // (1) In the same relocation table + // (2) Are consecutive + // (3) Are sorted in memory address order // // Happily, this is normally the case, but it's not required by spec // so we check, and just don't do it if we don't match up. - + // // The expectation is that one relocation section will contain - // all of our R_386_RELATIVE entries in the expected order followed + // all of our R_ARM_RELATIVE entries in the expected order followed // by assorted other entries we can't use special handling for. bool match = true; @@ -82,21 +82,36 @@ CheckBool DisassemblerElf32ARM::ParseRelocationSection( if (abs32_locations_.size() > section_relocs_count) match = false; - std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); + if (!abs32_locations_.empty()) { + std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); - while (match && (reloc_iter != abs32_locations_.end())) { - if (section_relocs_iter->r_info != R_ARM_RELATIVE || - section_relocs_iter->r_offset != *reloc_iter) - match = false; - section_relocs_iter++; - reloc_iter++; - } + for (uint32 i = 0; i < section_relocs_count; i++) { + if (section_relocs_iter->r_offset == *reloc_iter) + break; - if (match) { - // Skip over relocation tables - if (!program->EmitElfRelocationInstruction()) - return false; - file_offset += sizeof(Elf32_Rel) * abs32_locations_.size(); + if (!ParseSimpleRegion(file_offset, file_offset + sizeof(Elf32_Rel), + program)) + return false; + + file_offset += sizeof(Elf32_Rel); + ++section_relocs_iter; + } + + while (match && (reloc_iter != abs32_locations_.end())) { + if (section_relocs_iter->r_info != R_ARM_RELATIVE || + section_relocs_iter->r_offset != *reloc_iter) + match = false; + + section_relocs_iter++; + reloc_iter++; + file_offset += sizeof(Elf32_Rel); + } + + if (match) { + // Skip over relocation tables + if (!program->EmitElfARMRelocationInstruction()) + return false; + } } return ParseSimpleRegion(file_offset, section_end, program); |