summaryrefslogtreecommitdiffstats
path: root/courgette/disassembler_elf_32_arm.cc
diff options
context:
space:
mode:
authorpaulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-18 22:07:53 +0000
committerpaulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-18 22:07:53 +0000
commita8e80416be9ccd606ce54f7f192b91133bb23b98 (patch)
tree0972d2fe6b393a5e07e7a1267be5b616643b7eec /courgette/disassembler_elf_32_arm.cc
parentba79a799579a5417511d472071e3f8fc5e2b67a5 (diff)
downloadchromium_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.cc61
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);