diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn index 63a00fa51106fa..fec22382d2e142 100644 --- a/courgette/BUILD.gn +++ b/courgette/BUILD.gn @@ -22,8 +22,6 @@ static_library("courgette_lib") { "disassembler.h", "disassembler_elf_32.cc", "disassembler_elf_32.h", - "disassembler_elf_32_arm.cc", - "disassembler_elf_32_arm.h", "disassembler_elf_32_x86.cc", "disassembler_elf_32_x86.h", "disassembler_win32.cc", diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc index 58c16b4a0235fa..fd73612799182b 100644 --- a/courgette/assembly_program.cc +++ b/courgette/assembly_program.cc @@ -31,7 +31,6 @@ class LabelReceptor : public InstructionReceptor { // InstructionReceptor: CheckBool EmitPeRelocs() override { return true; } CheckBool EmitElfRelocation() override { return true; } - CheckBool EmitElfARMRelocation() override { return true; } CheckBool EmitOrigin(RVA rva) override { return true; } CheckBool EmitSingleByte(uint8_t byte) override { return true; } CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override { @@ -41,13 +40,6 @@ class LabelReceptor : public InstructionReceptor { rel32_vector_.push_back(label); return true; } - CheckBool EmitRel32ARM(uint16_t op, - Label* label, - const uint8_t* arm_op, - uint16_t op_size) override { - rel32_vector_.push_back(label); - return true; - } CheckBool EmitAbs32(Label* label) override { abs32_vector_.push_back(label); return true; @@ -75,7 +67,8 @@ void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, RvaVisitor* rel32_visitor) { abs32_label_manager_.Read(abs32_visitor); rel32_label_manager_.Read(rel32_visitor); - TrimLabels(); + // TrimLabels() should be called here if used. Previously this was used only + // for ARM binaries, but ARM support has been deprecated. } // Chosen empirically to give the best reduction in payload size for @@ -83,10 +76,6 @@ void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, const int AssemblyProgram::kLabelLowerLimit = 5; void AssemblyProgram::TrimLabels() { - // For now only trim for ARM binaries. - if (kind() != EXE_ELF_32_ARM) - return; - int lower_limit = kLabelLowerLimit; VLOG(1) << "TrimLabels: threshold " << lower_limit; diff --git a/courgette/courgette.h b/courgette/courgette.h index 533756659a1126..a95fbd59fc5f07 100644 --- a/courgette/courgette.h +++ b/courgette/courgette.h @@ -57,7 +57,7 @@ enum ExecutableType { EXE_UNKNOWN = 0, EXE_WIN_32_X86 = 1, EXE_ELF_32_X86 = 2, - EXE_ELF_32_ARM = 3, + // EXE_ELF_32_ARM_DEPRECATED = 3, // DEPRECATED. EXE_WIN_32_X64 = 4, }; diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc index 383a92dcd0d969..9d904a5048536a 100644 --- a/courgette/courgette_tool.cc +++ b/courgette/courgette_tool.cc @@ -135,11 +135,6 @@ bool Supported(const base::FilePath& input_file) { result = true; break; - case courgette::EXE_ELF_32_ARM: - format = "ELF 32 ARM"; - result = true; - break; - case courgette::EXE_WIN_32_X64: format = "Windows 64 PE"; result = true; diff --git a/courgette/description.html b/courgette/description.html index 8fe4538bc5139f..e4854d345a83a6 100644 --- a/courgette/description.html +++ b/courgette/description.html @@ -41,7 +41,6 @@

Disassemble

  • The Disassembler replaces the relocation table with a Courgette instruction that can regenerate the relocation table.

  • diff --git a/courgette/description.md b/courgette/description.md index f79f99e6e65eea..533d4c396f0b52 100644 --- a/courgette/description.md +++ b/courgette/description.md @@ -46,8 +46,6 @@ Patch Generation - disassembler\_elf\_32\_x86.h defines the ELF 32-bit x86 disassembler - - disassembler\_elf\_32\_arm.h defines the ELF 32-bit arm disassembler - - The Disassembler replaces the relocation table with a Courgette instruction that can regenerate the relocation table. diff --git a/courgette/disassembler_elf_32_arm.cc b/courgette/disassembler_elf_32_arm.cc deleted file mode 100644 index b4fbf3f08e2179..00000000000000 --- a/courgette/disassembler_elf_32_arm.cc +++ /dev/null @@ -1,538 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "courgette/disassembler_elf_32_arm.h" - -#include -#include -#include - -#include "base/logging.h" -#include "courgette/assembly_program.h" -#include "courgette/courgette.h" - -namespace courgette { - -CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type, - uint32_t arm_op, - RVA rva, - uint16_t* c_op, - uint32_t* addr) { - // Notation for bit ranges in comments: - // - Listing bits from highest to lowest. - // - A-Z or (j1), (j2), etc.: single bit in source. - // - a-z: multiple, consecutive bits in source. - switch (type) { - case ARM_OFF8: { - // Encoding T1. - // The offset is given by lower 8 bits of the op. It is a 9-bit offset, - // shifted right 1 bit, and signed extended. - // arm_op = aaaaaaaa Snnnnnnn - // *addr := SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100 - // *c_op := 00010000 aaaaaaaa - uint32_t temp = (arm_op & 0x00FF) << 1; - if (temp & 0x0100) - temp |= 0xFFFFFE00; - temp += 4; // Offset from _next_ PC. - - (*addr) = temp; - (*c_op) = static_cast(arm_op >> 8) | 0x1000; - break; - } - case ARM_OFF11: { - // Encoding T2. - // The offset is given by lower 11 bits of the op, and is a 12-bit offset, - // shifted right 1 bit, and sign extended. - // arm_op = aaaaaSnn nnnnnnnn - // *addr := SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100 - // *c_op := 00100000 000aaaaa - uint32_t temp = (arm_op & 0x07FF) << 1; - if (temp & 0x00000800) - temp |= 0xFFFFF000; - temp += 4; // Offset from _next_ PC. - - (*addr) = temp; - (*c_op) = static_cast(arm_op >> 11) | 0x2000; - break; - } - case ARM_OFF24: { - // The offset is given by the lower 24-bits of the op, shifted - // left 2 bits, and sign extended. - // arm_op = aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn - // *addr := SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000 - // *c_op := 00110000 aaaaaaaa - uint32_t temp = (arm_op & 0x00FFFFFF) << 2; - if (temp & 0x02000000) - temp |= 0xFC000000; - temp += 8; - - (*addr) = temp; - (*c_op) = (arm_op >> 24) | 0x3000; - break; - } - case ARM_OFF25: { - // Encoding T4. - // arm_op = aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn - // where CD is in {01, 10, 11} - // i1 := ~(j1 ^ S) - // i2 := ~(j2 ^ S) - // If CD == 10: - // pppp := (rva % 4 == 0) ? 0100 : 0010 - // Else: - // pppp := 0100 - // *addr := SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp - // *c_op := 0100pppp aaaaaBCD - // TODO(huangs): aaaaa = 11110 and B = 1 always? Investigate and fix. - uint32_t temp = 0; - temp |= (arm_op & 0x000007FF) << 1; // imm11 - temp |= (arm_op & 0x03FF0000) >> 4; // imm10 - - uint32_t S = (arm_op & (1 << 26)) >> 26; - uint32_t j2 = (arm_op & (1 << 11)) >> 11; - uint32_t j1 = (arm_op & (1 << 13)) >> 13; - bool bit12 = ((arm_op & (1 << 12)) >> 12) != 0; // D - bool bit14 = ((arm_op & (1 << 14)) >> 14) != 0; // C - - uint32_t i2 = ~(j2 ^ S) & 1; - uint32_t i1 = ~(j1 ^ S) & 1; - bool toARM = bit14 && !bit12; - - temp |= (S << 24) | (i1 << 23) | (i2 << 22); - - if (temp & 0x01000000) // sign extension - temp |= 0xFE000000; - uint32_t prefetch; - if (toARM) { - // Align PC on 4-byte boundary. - uint32_t align4byte = (rva % 4) ? 2 : 4; - prefetch = align4byte; - } else { - prefetch = 4; - } - temp += prefetch; - (*addr) = temp; - - uint32_t temp2 = 0x4000; - temp2 |= (arm_op & (1 << 12)) >> 12; // .......D - temp2 |= (arm_op & (1 << 14)) >> 13; // ......C. - temp2 |= (arm_op & (1 << 15)) >> 13; // .....B.. - temp2 |= (arm_op & 0xF8000000) >> 24; // aaaaa... - temp2 |= (prefetch & 0x0000000F) << 8; - (*c_op) = static_cast(temp2); - break; - } - case ARM_OFF21: { - // Encoding T3. - // arm_op = 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn - // *addr := SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100 - // *c_op := 01010000 0000cccc - uint32_t temp = 0; - temp |= (arm_op & 0x000007FF) << 1; // imm11 - temp |= (arm_op & 0x003F0000) >> 4; // imm6 - - uint32_t S = (arm_op & (1 << 26)) >> 26; - // TODO(huangs): Check with docs: Perhaps j1, j2 should swap? - uint32_t j2 = (arm_op & (1 << 11)) >> 11; - uint32_t j1 = (arm_op & (1 << 13)) >> 13; - - temp |= (S << 20) | (j1 << 19) | (j2 << 18); - - if (temp & 0x00100000) // sign extension - temp |= 0xFFE00000; - temp += 4; - (*addr) = temp; - - uint32_t temp2 = 0x5000; - temp2 |= (arm_op & 0x03C00000) >> 22; // just save the cond - (*c_op) = static_cast(temp2); - break; - } - default: - return false; - } - return true; -} - -CheckBool DisassemblerElf32ARM::Decompress(ARM_RVA type, - uint16_t c_op, - uint32_t addr, - uint32_t* arm_op) { - switch (type) { - case ARM_OFF8: - // addr = SSSSSSSS SSSSSSSS SSSSSSSS nnnnnnn0 + 100 - // c_op = 00010000 aaaaaaaa - // *arm_op := aaaaaaaa Snnnnnnn - (*arm_op) = ((c_op & 0x0FFF) << 8) | (((addr - 4) >> 1) & 0x000000FF); - break; - case ARM_OFF11: - // addr = SSSSSSSS SSSSSSSS SSSSSnnn nnnnnnn0 + 100 - // c_op = 00100000 000aaaaa - // *arm_op := aaaaaSnn nnnnnnnn - (*arm_op) = ((c_op & 0x0FFF) << 11) | (((addr - 4) >> 1) & 0x000007FF); - break; - case ARM_OFF24: - // addr = SSSSSSSn nnnnnnnn nnnnnnnn nnnnnn00 + 1000 - // c_op = 00110000 aaaaaaaa - // *arm_op := aaaaaaaa Snnnnnnn nnnnnnnn nnnnnnnn - (*arm_op) = ((c_op & 0x0FFF) << 24) | (((addr - 8) >> 2) & 0x00FFFFFF); - break; - case ARM_OFF25: { - // addr = SSSSSSSS (i1)(i2)mmmmmm mmmmnnnn nnnnnnn0 + pppp - // c_op = 0100pppp aaaaaBCD - // j1 := ~i1 ^ S - // j2 := ~i2 ^ S - // *arm_op := aaaaaSmm mmmmmmmm BC(j1)D(j2)nnn nnnnnnnn - uint32_t temp = 0; - temp |= (c_op & (1 << 0)) << 12; - temp |= (c_op & (1 << 1)) << 13; - temp |= (c_op & (1 << 2)) << 13; - temp |= (c_op & (0xF8000000 >> 24)) << 24; - - uint32_t prefetch = (c_op & 0x0F00) >> 8; - addr -= prefetch; - - addr &= 0x01FFFFFF; - - uint32_t S = (addr & (1 << 24)) >> 24; - uint32_t i1 = (addr & (1 << 23)) >> 23; - uint32_t i2 = (addr & (1 << 22)) >> 22; - - uint32_t j1 = ((~i1) ^ S) & 1; - uint32_t j2 = ((~i2) ^ S) & 1; - - temp |= S << 26; - temp |= j2 << 11; - temp |= j1 << 13; - - temp |= (addr & (0x000007FF << 1)) >> 1; - temp |= (addr & (0x03FF0000 >> 4)) << 4; - - (*arm_op) = temp; - break; - } - case ARM_OFF21: { - // addr = SSSSSSSS SSSS(j1)(j2)mm mmmmnnnn nnnnnnn0 + 100 - // c_op = 01010000 0000cccc - // *arm_op := 11110Scc ccmmmmmm 10(j1)0(j2)nnn nnnnnnnn - uint32_t temp = 0xF0008000; - temp |= (c_op & (0x03C00000 >> 22)) << 22; - - addr -= 4; - addr &= 0x001FFFFF; - - uint32_t S = (addr & (1 << 20)) >> 20; - uint32_t j1 = (addr & (1 << 19)) >> 19; - uint32_t j2 = (addr & (1 << 18)) >> 18; - - temp |= S << 26; - temp |= j2 << 11; - temp |= j1 << 13; - - temp |= (addr & (0x000007FF << 1)) >> 1; - temp |= (addr & (0x003F0000 >> 4)) << 4; - - (*arm_op) = temp; - break; - } - default: - return false; - } - return true; -} - -uint16_t DisassemblerElf32ARM::TypedRVAARM::op_size() const { - switch (type_) { - case ARM_OFF8: - return 2; - case ARM_OFF11: - return 2; - case ARM_OFF24: - return 4; - case ARM_OFF25: - return 4; - case ARM_OFF21: - return 4; - default: - return 0xFFFF; - } -} - -CheckBool DisassemblerElf32ARM::TypedRVAARM::ComputeRelativeTarget( - const uint8_t* op_pointer) { - arm_op_ = op_pointer; - switch (type_) { - case ARM_OFF8: // Falls through. - case ARM_OFF11: { - RVA relative_target; - CheckBool ret = Compress(type_, - Read16LittleEndian(op_pointer), - rva(), - &c_op_, - &relative_target); - set_relative_target(relative_target); - return ret; - } - case ARM_OFF24: { - RVA relative_target; - CheckBool ret = Compress(type_, - Read32LittleEndian(op_pointer), - rva(), - &c_op_, - &relative_target); - set_relative_target(relative_target); - return ret; - } - case ARM_OFF25: // Falls through. - case ARM_OFF21: { - // A thumb-2 op is 32 bits stored as two 16-bit words - uint32_t pval = (Read16LittleEndian(op_pointer) << 16) | - Read16LittleEndian(op_pointer + 2); - RVA relative_target; - CheckBool ret = Compress(type_, pval, rva(), &c_op_, &relative_target); - set_relative_target(relative_target); - return ret; - } - default: - return false; - } -} - -CheckBool DisassemblerElf32ARM::TypedRVAARM::EmitInstruction( - Label* label, - InstructionReceptor* receptor) { - return receptor->EmitRel32ARM(c_op(), label, arm_op_, op_size()); -} - -DisassemblerElf32ARM::DisassemblerElf32ARM(const uint8_t* start, size_t length) - : DisassemblerElf32(start, length) {} - -// Convert an ELF relocation struction into an RVA. -CheckBool DisassemblerElf32ARM::RelToRVA(Elf32_Rel rel, RVA* result) const { - // The rightmost byte of r_info is the type. - elf32_rel_arm_type_values type = - static_cast(rel.r_info & 0xFF); - - // The other 3 bytes of r_info are the symbol. - uint32_t symbol = rel.r_info >> 8; - - switch (type) { - case R_ARM_RELATIVE: - if (symbol != 0) - return false; - - // This is a basic ABS32 relocation address. - *result = rel.r_offset; - return true; - - default: - return false; - } -} - -CheckBool DisassemblerElf32ARM::ParseRelocationSection( - const Elf32_Shdr* section_header, - InstructionReceptor* receptor) const { - // 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_ARM_RELATIVE entries in the expected order followed by assorted other - // entries we can't use special handling for. - - bool match = true; - - // Walk all the bytes in the section, matching relocation table or not. - FileOffset file_offset = section_header->sh_offset; - FileOffset section_end = section_header->sh_offset + section_header->sh_size; - - const Elf32_Rel* section_relocs_iter = reinterpret_cast( - FileOffsetToPointer(section_header->sh_offset)); - - uint32_t section_relocs_count = - section_header->sh_size / section_header->sh_entsize; - - if (abs32_locations_.size() > section_relocs_count) - match = false; - - if (match && !abs32_locations_.empty()) { - std::vector::const_iterator reloc_iter = abs32_locations_.begin(); - - // Look for the first reloc unit matching |abs32_locations_[0]|. - size_t section_relocs_remaining = section_relocs_count; - for (; section_relocs_remaining > 0; --section_relocs_remaining) { - if (section_relocs_iter->r_info == R_ARM_RELATIVE && - section_relocs_iter->r_offset == *reloc_iter) { - break; - } - - if (!ParseSimpleRegion(file_offset, file_offset + sizeof(Elf32_Rel), - receptor)) { - return false; - } - - file_offset += sizeof(Elf32_Rel); - ++section_relocs_iter; - } - - // If there aren't enough reloc units left then don't bother matching. This - // can happen if the reloc units are not sorted. - if (abs32_locations_.size() > section_relocs_remaining) - match = false; - - // Try to match successive reloc units with (sorted) |abs32_locations_|. - 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) { - // Success: Emit relocation table. - if (!receptor->EmitElfARMRelocation()) - return false; - } - } - - return ParseSimpleRegion(file_offset, section_end, receptor); -} - -// TODO(huangs): Detect and avoid overlap with abs32 addresses. -CheckBool DisassemblerElf32ARM::ParseRel32RelocsFromSection( - const Elf32_Shdr* section_header) { - FileOffset start_file_offset = section_header->sh_offset; - FileOffset end_file_offset = start_file_offset + section_header->sh_size; - - const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset); - const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset); - - // Quick way to convert from Pointer to RVA within a single Section is to - // subtract |pointer_to_rva|. - const uint8_t* const adjust_pointer_to_rva = - start_pointer - section_header->sh_addr; - - // Find the rel32 relocations. - const uint8_t* p = start_pointer; - bool on_32bit = 1; // 32-bit ARM ops appear on 32-bit boundaries, so track it - while (p < end_pointer) { - // Heuristic discovery of rel32 locations in instruction stream: are the - // next few bytes the start of an instruction containing a rel32 - // addressing mode? - std::unique_ptr rel32_rva; - RVA target_rva = 0; - bool found = false; - - // 16-bit thumb ops - if (!found && p + 3 <= end_pointer) { - uint16_t pval = Read16LittleEndian(p); - if ((pval & 0xF000) == 0xD000) { - RVA rva = static_cast(p - adjust_pointer_to_rva); - - rel32_rva.reset(new TypedRVAARM(ARM_OFF8, rva)); - if (!rel32_rva->ComputeRelativeTarget(p)) - return false; - - target_rva = rel32_rva->rva() + rel32_rva->relative_target(); - found = true; - } else if ((pval & 0xF800) == 0xE000) { - RVA rva = static_cast(p - adjust_pointer_to_rva); - - rel32_rva.reset(new TypedRVAARM(ARM_OFF11, rva)); - if (!rel32_rva->ComputeRelativeTarget(p)) - return false; - - target_rva = rel32_rva->rva() + rel32_rva->relative_target(); - found = true; - } - } - - // thumb-2 ops comprised of two 16-bit words. - if (!found && p + 5 <= end_pointer) { - // This is really two 16-bit words, not one 32-bit word. - uint32_t pval = (Read16LittleEndian(p) << 16) | Read16LittleEndian(p + 2); - if ((pval & 0xF8008000) == 0xF0008000) { - // Covers thumb-2's 32-bit conditional/unconditional branches - if ((pval & (1 << 14)) || (pval & (1 << 12))) { - // A branch, with link, or with link and exchange. - RVA rva = static_cast(p - adjust_pointer_to_rva); - - rel32_rva.reset(new TypedRVAARM(ARM_OFF25, rva)); - if (!rel32_rva->ComputeRelativeTarget(p)) - return false; - - target_rva = rel32_rva->rva() + rel32_rva->relative_target(); - found = true; - - } else { - // TODO(paulgazz) make sure cond is not 111 - // A conditional branch instruction - RVA rva = static_cast(p - adjust_pointer_to_rva); - - rel32_rva.reset(new TypedRVAARM(ARM_OFF21, rva)); - if (!rel32_rva->ComputeRelativeTarget(p)) - return false; - - target_rva = rel32_rva->rva() + rel32_rva->relative_target(); - found = true; - } - } - } - - // 32-bit ARM ops. - if (!found && on_32bit && (p + 5) <= end_pointer) { - uint32_t pval = Read32LittleEndian(p); - if ((pval & 0x0E000000) == 0x0A000000) { - // Covers both 0x0A 0x0B ARM relative branches - RVA rva = static_cast(p - adjust_pointer_to_rva); - - rel32_rva.reset(new TypedRVAARM(ARM_OFF24, rva)); - if (!rel32_rva->ComputeRelativeTarget(p)) - return false; - - target_rva = rel32_rva->rva() + rel32_rva->relative_target(); - found = true; - } - } - - if (found && IsValidTargetRVA(target_rva)) { - uint16_t op_size = rel32_rva->op_size(); - rel32_locations_.push_back(std::move(rel32_rva)); -#if COURGETTE_HISTOGRAM_TARGETS - ++rel32_target_rvas_[target_rva]; -#endif - p += op_size; - - // A tricky way to update the on_32bit flag. Here is the truth table: - // on_32bit | on_32bit size is 4 - // ---------+--------------------- - // 1 | 0 0 - // 0 | 0 1 - // 0 | 1 0 - // 1 | 1 1 - on_32bit = (on_32bit == (op_size == 4)); - } else { - // Move 2 bytes at a time, but track 32-bit boundaries - p += 2; - on_32bit = ((on_32bit + 1) % 2) != 0; - } - } - - return true; -} - -} // namespace courgette diff --git a/courgette/disassembler_elf_32_arm.h b/courgette/disassembler_elf_32_arm.h deleted file mode 100644 index 1203806160829a..00000000000000 --- a/courgette/disassembler_elf_32_arm.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COURGETTE_DISASSEMBLER_ELF_32_ARM_H_ -#define COURGETTE_DISASSEMBLER_ELF_32_ARM_H_ - -#include -#include - -#include - -#include "base/macros.h" -#include "courgette/disassembler_elf_32.h" -#include "courgette/types_elf.h" - -namespace courgette { - -class InstructionReceptor; - -enum ARM_RVA { - ARM_OFF8, - ARM_OFF11, - ARM_OFF24, - ARM_OFF25, - ARM_OFF21, -}; - -class DisassemblerElf32ARM : public DisassemblerElf32 { - public: - // Returns true if a valid executable is detected using only quick checks. - static bool QuickDetect(const uint8_t* start, size_t length) { - return DisassemblerElf32::QuickDetect(start, length, EM_ARM); - } - - class TypedRVAARM : public TypedRVA { - public: - TypedRVAARM(ARM_RVA type, RVA rva) : TypedRVA(rva), type_(type) { } - ~TypedRVAARM() override { } - - // TypedRVA interfaces. - CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) override; - CheckBool EmitInstruction(Label* label, - InstructionReceptor* receptor) override; - uint16_t op_size() const override; - - uint16_t c_op() const { return c_op_; } - - private: - ARM_RVA type_; - uint16_t c_op_; // Set by ComputeRelativeTarget(). - const uint8_t* arm_op_; - }; - - DisassemblerElf32ARM(const uint8_t* start, size_t length); - - ~DisassemblerElf32ARM() override { } - - // DisassemblerElf32 interfaces. - ExecutableType kind() const override { return EXE_ELF_32_ARM; } - e_machine_values ElfEM() const override { return EM_ARM; } - - // Takes an ARM or thumb opcode |arm_op| of specified |type| and located at - // |rva|, extracts the instruction-relative target RVA into |*addr| and - // encodes the corresponding Courgette opcode as |*c_op|. - // - // Details on ARM opcodes, and target RVA extraction are taken from - // "ARM Architecture Reference Manual", section A4.1.5 and - // "Thumb-2 supplement", section 4.6.12. - // ARM_OFF24 is for the ARM opcode. The rest are for thumb opcodes. - static CheckBool Compress(ARM_RVA type, - uint32_t arm_op, - RVA rva, - uint16_t* c_op /* out */, - uint32_t* addr /* out */); - - // Inverse for Compress(). Takes Courgette op |c_op| and relative address - // |addr| to reconstruct the original ARM or thumb op |*arm_op|. - static CheckBool Decompress(ARM_RVA type, - uint16_t c_op, - uint32_t addr, - uint32_t* arm_op /* out */); - - protected: - // DisassemblerElf32 interfaces. - CheckBool RelToRVA(Elf32_Rel rel, - RVA* result) const override WARN_UNUSED_RESULT; - CheckBool ParseRelocationSection(const Elf32_Shdr* section_header, - InstructionReceptor* receptor) const override - WARN_UNUSED_RESULT; - CheckBool ParseRel32RelocsFromSection(const Elf32_Shdr* section) - override WARN_UNUSED_RESULT; - -#if COURGETTE_HISTOGRAM_TARGETS - std::map rel32_target_rvas_; -#endif - - private: - DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32ARM); -}; - -} // namespace courgette - -#endif // COURGETTE_DISASSEMBLER_ELF_32_ARM_H_ diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc index a07baf398c4e54..2d0e40c96ee4c3 100644 --- a/courgette/encode_decode_unittest.cc +++ b/courgette/encode_decode_unittest.cc @@ -109,9 +109,4 @@ TEST_F(EncodeDecodeTest, Elf_HighBSS) { TestAssembleToStreamDisassemble(file, 7308); } -TEST_F(EncodeDecodeTest, Elf_Arm) { - std::string file = FileContents("elf-armv7"); - TestAssembleToStreamDisassemble(file, 8531); -} - } // namespace courgette diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc index c1f82bd724bb06..859f3d965af794 100644 --- a/courgette/encoded_program.cc +++ b/courgette/encoded_program.cc @@ -19,7 +19,6 @@ #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "courgette/disassembler_elf_32_arm.h" #include "courgette/label_manager.h" #include "courgette/streams.h" @@ -144,9 +143,6 @@ class InstructionStoreReceptor : public InstructionReceptor { CheckBool EmitElfRelocation() override { return encoded_->AddElfMakeRelocs(); } - CheckBool EmitElfARMRelocation() override { - return encoded_->AddElfARMMakeRelocs(); - } CheckBool EmitOrigin(RVA rva) override { return encoded_->AddOrigin(rva); } CheckBool EmitSingleByte(uint8_t byte) override { return encoded_->AddCopy(1, &byte); @@ -157,12 +153,6 @@ class InstructionStoreReceptor : public InstructionReceptor { CheckBool EmitRel32(Label* label) override { return encoded_->AddRel32(label->index_); } - CheckBool EmitRel32ARM(uint16_t op, - Label* label, - const uint8_t* arm_op, - uint16_t op_size) override { - return encoded_->AddRel32ARM(op, label->index_); - } CheckBool EmitAbs32(Label* label) override { return encoded_->AddAbs32(label->index_); } @@ -254,11 +244,6 @@ CheckBool EncodedProgram::AddRel32(int label_index) { return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); } -CheckBool EncodedProgram::AddRel32ARM(uint16_t op, int label_index) { - return ops_.push_back(static_cast(op)) && - rel32_ix_.push_back(label_index); -} - CheckBool EncodedProgram::AddPeMakeRelocs(ExecutableType kind) { if (kind == EXE_WIN_32_X86) return ops_.push_back(MAKE_PE_RELOCATION_TABLE); @@ -269,10 +254,6 @@ CheckBool EncodedProgram::AddElfMakeRelocs() { return ops_.push_back(MAKE_ELF_RELOCATION_TABLE); } -CheckBool EncodedProgram::AddElfARMMakeRelocs() { - return ops_.push_back(MAKE_ELF_ARM_RELOCATION_TABLE); -} - void EncodedProgram::DebuggingSummary() { VLOG(1) << "EncodedProgram Summary" << "\n image base " << image_base_ @@ -419,117 +400,6 @@ bool VectorAt(const V& v, size_t index, T* output) { return true; } -CheckBool EncodedProgram::EvaluateRel32ARM(OP op, - size_t* ix_rel32_ix, - RVA* current_rva, - SinkStream* output) { - switch (op & 0x0000F000) { - case REL32ARM8: { - uint32_t index; - if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index)) - return false; - ++(*ix_rel32_ix); - RVA rva; - if (!VectorAt(rel32_rva_, index, &rva)) - return false; - uint32_t decompressed_op; - if (!DisassemblerElf32ARM::Decompress( - ARM_OFF8, static_cast(op), - static_cast(rva - *current_rva), &decompressed_op)) { - return false; - } - uint16_t op16 = static_cast(decompressed_op); - if (!output->Write(&op16, 2)) - return false; - *current_rva += 2; - break; - } - case REL32ARM11: { - uint32_t index; - if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index)) - return false; - ++(*ix_rel32_ix); - RVA rva; - if (!VectorAt(rel32_rva_, index, &rva)) - return false; - uint32_t decompressed_op; - if (!DisassemblerElf32ARM::Decompress(ARM_OFF11, (uint16_t)op, - (uint32_t)(rva - *current_rva), - &decompressed_op)) { - return false; - } - uint16_t op16 = static_cast(decompressed_op); - if (!output->Write(&op16, 2)) - return false; - *current_rva += 2; - break; - } - case REL32ARM24: { - uint32_t index; - if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index)) - return false; - ++(*ix_rel32_ix); - RVA rva; - if (!VectorAt(rel32_rva_, index, &rva)) - return false; - uint32_t decompressed_op; - if (!DisassemblerElf32ARM::Decompress(ARM_OFF24, (uint16_t)op, - (uint32_t)(rva - *current_rva), - &decompressed_op)) { - return false; - } - if (!output->Write(&decompressed_op, 4)) - return false; - *current_rva += 4; - break; - } - case REL32ARM25: { - uint32_t index; - if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index)) - return false; - ++(*ix_rel32_ix); - RVA rva; - if (!VectorAt(rel32_rva_, index, &rva)) - return false; - uint32_t decompressed_op; - if (!DisassemblerElf32ARM::Decompress(ARM_OFF25, (uint16_t)op, - (uint32_t)(rva - *current_rva), - &decompressed_op)) { - return false; - } - uint32_t words = (decompressed_op << 16) | (decompressed_op >> 16); - if (!output->Write(&words, 4)) - return false; - *current_rva += 4; - break; - } - case REL32ARM21: { - uint32_t index; - if (!VectorAt(rel32_ix_, *ix_rel32_ix, &index)) - return false; - ++(*ix_rel32_ix); - RVA rva; - if (!VectorAt(rel32_rva_, index, &rva)) - return false; - uint32_t decompressed_op; - if (!DisassemblerElf32ARM::Decompress(ARM_OFF21, (uint16_t)op, - (uint32_t)(rva - *current_rva), - &decompressed_op)) { - return false; - } - uint32_t words = (decompressed_op << 16) | (decompressed_op >> 16); - if (!output->Write(&words, 4)) - return false; - *current_rva += 4; - break; - } - default: - return false; - } - - return true; -} - CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { // For the most part, the assembly process walks the various tables. // ix_mumble is the index into the mumble table. @@ -553,9 +423,7 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { switch (op) { default: - if (!EvaluateRel32ARM(op, &ix_rel32_ix, ¤t_rva, output)) - return false; - break; + return false; case ORIGIN: { RVA section_rva; @@ -670,18 +538,6 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { break; } - case MAKE_ELF_ARM_RELOCATION_TABLE: { - // We can see the base relocation anywhere, but we only have the - // information to generate it at the very end. So we divert the bytes - // we are generating to a temporary stream. - if (pending_elf_relocation_table_type) - return false; // Can't have two base relocation tables. - - pending_elf_relocation_table_type = R_ARM_RELATIVE; - output = &bytes_following_relocation_table; - break; - } - case MAKE_ELF_RELOCATION_TABLE: { // We can see the base relocation anywhere, but we only have the // information to generate it at the very end. So we divert the bytes diff --git a/courgette/encoded_program.h b/courgette/encoded_program.h index 39051460619139..b814cbbe534d8c 100644 --- a/courgette/encoded_program.h +++ b/courgette/encoded_program.h @@ -63,12 +63,10 @@ class EncodedProgram { CheckBool AddOrigin(RVA rva) WARN_UNUSED_RESULT; CheckBool AddCopy(size_t count, const void* bytes) WARN_UNUSED_RESULT; CheckBool AddRel32(int label_index) WARN_UNUSED_RESULT; - CheckBool AddRel32ARM(uint16_t op, int label_index) WARN_UNUSED_RESULT; CheckBool AddAbs32(int label_index) WARN_UNUSED_RESULT; CheckBool AddAbs64(int label_index) WARN_UNUSED_RESULT; CheckBool AddPeMakeRelocs(ExecutableType kind) WARN_UNUSED_RESULT; CheckBool AddElfMakeRelocs() WARN_UNUSED_RESULT; - CheckBool AddElfARMMakeRelocs() WARN_UNUSED_RESULT; // (3) Serialize binary assembly language tables to a set of streams. CheckBool WriteTo(SinkStreamSet* streams) WARN_UNUSED_RESULT; @@ -94,23 +92,16 @@ class EncodedProgram { COPY = 1, // COPY - copy bytes to output. COPY1 = 2, // COPY1 - same as COPY 1 . REL32 = 3, // REL32 - emit rel32 encoded reference to address at - // address table offset + // address table offset . ABS32 = 4, // ABS32 - emit abs32 encoded reference to address at - // address table offset - MAKE_PE_RELOCATION_TABLE = 5, // Emit PE base relocation table blocks. - MAKE_ELF_RELOCATION_TABLE = 6, // Emit Elf relocation table for X86 - MAKE_ELF_ARM_RELOCATION_TABLE = 7, // Emit Elf relocation table for ARM + // address table offset . + MAKE_PE_RELOCATION_TABLE = 5, // Emit PE base relocation table blocks. + MAKE_ELF_RELOCATION_TABLE = 6, // Emit ELF relocation table for X86. + // DEPCREATED: ELF relocation table for ARM. + // MAKE_ELF_ARM_RELOCATION_TABLE_DEPRECATED = 7, MAKE_PE64_RELOCATION_TABLE = 8, // Emit PE64 base relocation table blocks. ABS64 = 9, // ABS64 - emit abs64 encoded reference to address at - // address table offset - // ARM reserves 0x1000-LAST_ARM, bits 13-16 define the opcode - // subset, and 1-12 are the compressed ARM op. - REL32ARM8 = 0x1000, - REL32ARM11 = 0x2000, - REL32ARM24 = 0x3000, - REL32ARM25 = 0x4000, - REL32ARM21 = 0x5000, - LAST_ARM = 0x5FFF, + // address table offset . }; typedef NoThrowBuffer RvaVector; @@ -133,12 +124,6 @@ class EncodedProgram { CheckBool GenerateElfRelocations(Elf32_Word pending_elf_relocation_table, SinkStream* buffer) WARN_UNUSED_RESULT; - // Decodes and evaluates courgette ops for ARM rel32 addresses. - CheckBool EvaluateRel32ARM(OP op, - size_t* ix_rel32_ix, - RVA* current_rva, - SinkStream* output); - // Binary assembly language tables. uint64_t image_base_ = 0; RvaVector rel32_rva_; diff --git a/courgette/ensemble_apply.cc b/courgette/ensemble_apply.cc index 9f4ec54bfabc23..918e62107cfbdb 100644 --- a/courgette/ensemble_apply.cc +++ b/courgette/ensemble_apply.cc @@ -141,7 +141,6 @@ Status EnsemblePatchApplication::ReadInitialParameters( switch (kind) { case EXE_WIN_32_X86: // Fall through. case EXE_ELF_32_X86: - case EXE_ELF_32_ARM: case EXE_WIN_32_X64: patcher.reset(new PatcherX86_32(base_region_)); break; diff --git a/courgette/ensemble_create.cc b/courgette/ensemble_create.cc index c439fac7eb86d4..4e5b7f3688aba7 100644 --- a/courgette/ensemble_create.cc +++ b/courgette/ensemble_create.cc @@ -85,15 +85,6 @@ TransformationPatchGenerator* MakeGenerator(Element* old_element, EXE_ELF_32_X86); return generator; } - case EXE_ELF_32_ARM: { - TransformationPatchGenerator* generator = - new PatchGeneratorX86_32( - old_element, - new_element, - new PatcherX86_32(old_element->region()), - EXE_ELF_32_ARM); - return generator; - } case EXE_WIN_32_X64: { TransformationPatchGenerator* generator = new PatchGeneratorX86_32( diff --git a/courgette/instruction_utils.h b/courgette/instruction_utils.h index 32287a9ed95ee5..9b201dce7f1047 100644 --- a/courgette/instruction_utils.h +++ b/courgette/instruction_utils.h @@ -26,9 +26,6 @@ class InstructionReceptor { // Generates an ELF style relocation table for X86. virtual CheckBool EmitElfRelocation() = 0; - // Generates an ELF style relocation table for ARM. - virtual CheckBool EmitElfARMRelocation() = 0; - // Following instruction will be assembled at address 'rva'. virtual CheckBool EmitOrigin(RVA rva) = 0; @@ -41,12 +38,6 @@ class InstructionReceptor { // Generates a 4-byte relative reference to address of 'label'. virtual CheckBool EmitRel32(Label* label) = 0; - // Generates a 4-byte relative reference to address of 'label' for ARM. - virtual CheckBool EmitRel32ARM(uint16_t op, - Label* label, - const uint8_t* arm_op, - uint16_t op_size) = 0; - // Generates a 4-byte absolute reference to address of 'label'. virtual CheckBool EmitAbs32(Label* label) = 0; diff --git a/courgette/program_detector.cc b/courgette/program_detector.cc index 12461f9b530bb9..cb4dfde2fac2db 100644 --- a/courgette/program_detector.cc +++ b/courgette/program_detector.cc @@ -5,7 +5,6 @@ #include "courgette/program_detector.h" #include "courgette/disassembler.h" -#include "courgette/disassembler_elf_32_arm.h" #include "courgette/disassembler_elf_32_x86.h" #include "courgette/disassembler_win32_x64.h" #include "courgette/disassembler_win32_x86.h" @@ -31,11 +30,6 @@ std::unique_ptr DetectDisassembler(const uint8_t* buffer, if (disassembler->ParseHeader()) return disassembler; } - if (DisassemblerElf32ARM::QuickDetect(buffer, length)) { - disassembler.reset(new DisassemblerElf32ARM(buffer, length)); - if (disassembler->ParseHeader()) - return disassembler; - } return nullptr; } diff --git a/courgette/program_detector_unittest.cc b/courgette/program_detector_unittest.cc index 82c6fdb563f2e5..ce1e6ea761fda0 100644 --- a/courgette/program_detector_unittest.cc +++ b/courgette/program_detector_unittest.cc @@ -9,7 +9,6 @@ #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" #include "courgette/disassembler.h" -#include "courgette/disassembler_elf_32_arm.h" #include "courgette/disassembler_elf_32_x86.h" #include "courgette/disassembler_win32_x64.h" #include "courgette/disassembler_win32_x86.h" @@ -41,10 +40,6 @@ void ProgramDetectorTest::TestQuickDetect(const std::string& test_data, DisassemblerElf32X86::QuickDetect( reinterpret_cast(test_data.data()), test_data.size())); - EXPECT_EQ(expected_type == EXE_ELF_32_ARM, - DisassemblerElf32ARM::QuickDetect( - reinterpret_cast(test_data.data()), - test_data.size())); } void ProgramDetectorTest::TestDetectDisassembler( @@ -62,17 +57,14 @@ TEST_F(ProgramDetectorTest, All) { std::string win32_x86 = FileContents("setup1.exe"); std::string win32_x64 = FileContents("chrome64_1.exe"); std::string elf_32 = FileContents("elf-32-1"); - std::string elf_arm = FileContents("elf-armv7"); TestQuickDetect(win32_x86, EXE_WIN_32_X86); TestQuickDetect(win32_x64, EXE_WIN_32_X64); TestQuickDetect(elf_32, EXE_ELF_32_X86); - TestQuickDetect(elf_arm, EXE_ELF_32_ARM); TestDetectDisassembler(win32_x86, EXE_WIN_32_X86); TestDetectDisassembler(win32_x64, EXE_WIN_32_X64); TestDetectDisassembler(elf_32, EXE_ELF_32_X86); - TestDetectDisassembler(elf_arm, EXE_ELF_32_ARM); } } // namespace diff --git a/courgette/typedrva_unittest.cc b/courgette/typedrva_unittest.cc index d0ad833deb4398..5dd65a44b8c504 100644 --- a/courgette/typedrva_unittest.cc +++ b/courgette/typedrva_unittest.cc @@ -5,7 +5,6 @@ #include #include "courgette/base_test_unittest.h" -#include "courgette/disassembler_elf_32_arm.h" #include "courgette/disassembler_elf_32_x86.h" #include "courgette/image_utils.h" @@ -14,15 +13,6 @@ class TypedRVATest : public BaseTest { void TestRelativeTargetX86(courgette::RVA word, courgette::RVA expected) const; - void TestRelativeTargetARM(courgette::ARM_RVA arm_rva, - courgette::RVA rva, - uint32_t op, - courgette::RVA expected) const; - - void TestARMOPEncode(courgette::ARM_RVA arm_rva, - courgette::RVA rva, - uint32_t op, - courgette::RVA expected) const; }; void TypedRVATest::TestRelativeTargetX86(courgette::RVA word, @@ -41,126 +31,6 @@ uint32_t Read32LittleEndian(const void* address) { return *reinterpret_cast(address); } -void TypedRVATest::TestRelativeTargetARM(courgette::ARM_RVA arm_rva, - courgette::RVA rva, - uint32_t op, - courgette::RVA expected) const { - courgette::DisassemblerElf32ARM::TypedRVAARM* typed_rva - = new courgette::DisassemblerElf32ARM::TypedRVAARM(arm_rva, rva); - uint8_t* op_pointer = reinterpret_cast(&op); - - EXPECT_TRUE(typed_rva->ComputeRelativeTarget(op_pointer)); - EXPECT_EQ(rva + typed_rva->relative_target(), expected); - - delete typed_rva; -} - -void TypedRVATest::TestARMOPEncode(courgette::ARM_RVA arm_rva, - courgette::RVA rva, - uint32_t op, - courgette::RVA expected) const { - uint16_t c_op; - uint32_t addr; - EXPECT_TRUE(courgette::DisassemblerElf32ARM::Compress(arm_rva, op, rva, - &c_op, &addr)); - EXPECT_EQ(rva + addr, expected); - - uint32_t new_op; - EXPECT_TRUE(courgette::DisassemblerElf32ARM::Decompress(arm_rva, c_op, addr, - &new_op)); - EXPECT_EQ(new_op, op); -} - TEST_F(TypedRVATest, TestX86) { TestRelativeTargetX86(0x0, 0x4); } - -// ARM opcodes taken from and tested against the output of -// "arm-linux-gnueabi-objdump -d daisy_3701.98.0/bin/ls" - -TEST_F(TypedRVATest, TestARM_OFF8_PREFETCH) { - TestRelativeTargetARM(courgette::ARM_OFF8, 0x0, 0x0, 0x4); -} - -TEST_F(TypedRVATest, TestARM_OFF8_FORWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec); - TestRelativeTargetARM(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776); -} - -TEST_F(TypedRVATest, TestARM_OFF8_BACKWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764); -} - -TEST_F(TypedRVATest, TestARM_OFF11_PREFETCH) { - TestRelativeTargetARM(courgette::ARM_OFF11, 0x0, 0x0, 0x4); -} - -TEST_F(TypedRVATest, TestARM_OFF11_FORWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8); -} - -TEST_F(TypedRVATest, TestARM_OFF11_BACKWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e); - TestRelativeTargetARM(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8); -} - -TEST_F(TypedRVATest, TestARM_OFF24_PREFETCH) { - TestRelativeTargetARM(courgette::ARM_OFF24, 0x0, 0x0, 0x8); -} - -TEST_F(TypedRVATest, TestARM_OFF24_FORWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874); - TestRelativeTargetARM(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8); - TestRelativeTargetARM(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468); -} - -TEST_F(TypedRVATest, TestARM_OFF24_BACKWARDS) { - // TODO(paulgazz): find a real-world example of an non-thumb ARM - // branch op that jumps backwards. -} - -TEST_F(TypedRVATest, TestARM_OFF25_FORWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bf4, 0xfe06f008, 0xb804); - TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c58, 0xfeacf005, 0x89b4); -} - -TEST_F(TypedRVATest, TestARM_OFF25_BACKWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd2, 0xeb9ef7ff, 0x2310); - TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd8, 0xeb8ef7ff, 0x22f8); - TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c3e, 0xea2ef7ff, 0x209c); -} - -TEST_F(TypedRVATest, TestARM_OFF21_FORWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bc6, 0x84c7f000, 0x3558); - TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bde, 0x871df000, 0x3a1c); - TestRelativeTargetARM(courgette::ARM_OFF21, 0x2c5e, 0x86c1f2c0, 0x39e4); -} - -TEST_F(TypedRVATest, TestARM_OFF21_BACKWARDS) { - TestRelativeTargetARM(courgette::ARM_OFF21, 0x67e4, 0xaee9f43f, 0x65ba); - TestRelativeTargetARM(courgette::ARM_OFF21, 0x67ee, 0xaee4f47f, 0x65ba); -} - -TEST_F(TypedRVATest, TestARMOPEncode) { - TestARMOPEncode(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec); - TestARMOPEncode(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776); - TestARMOPEncode(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764); - TestARMOPEncode(courgette::ARM_OFF11, 0x0, 0x0, 0x4); - TestARMOPEncode(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8); - TestARMOPEncode(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e); - TestARMOPEncode(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8); - TestARMOPEncode(courgette::ARM_OFF24, 0x0, 0x0, 0x8); - TestARMOPEncode(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874); - TestARMOPEncode(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8); - TestARMOPEncode(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468); - TestARMOPEncode(courgette::ARM_OFF25, 0x2bf4, 0xf008fe06, 0xb804); - TestARMOPEncode(courgette::ARM_OFF25, 0x2c58, 0xf005feac, 0x89b4); - TestARMOPEncode(courgette::ARM_OFF25, 0x2bd2, 0xf7ffeb9e, 0x2310); - TestARMOPEncode(courgette::ARM_OFF25, 0x2bd8, 0xf7ffeb8e, 0x22f8); - TestARMOPEncode(courgette::ARM_OFF25, 0x2c3e, 0xf7ffea2e, 0x209c); - TestARMOPEncode(courgette::ARM_OFF21, 0x2bc6, 0xf00084c7, 0x3558); - TestARMOPEncode(courgette::ARM_OFF21, 0x2bde, 0xf000871d, 0x3a1c); - TestARMOPEncode(courgette::ARM_OFF21, 0x2c5e, 0xf2c086c1, 0x39e4); - TestARMOPEncode(courgette::ARM_OFF21, 0x67e4, 0xf43faee9, 0x65ba); - TestARMOPEncode(courgette::ARM_OFF21, 0x67ee, 0xf47faee4, 0x65ba); -} diff --git a/courgette/types_elf.h b/courgette/types_elf.h index d45a10e4362c7c..78c67a07d9463c 100644 --- a/courgette/types_elf.h +++ b/courgette/types_elf.h @@ -173,8 +173,4 @@ enum elf32_rel_386_type_values { R_386_TLS_TPOFF = 14, }; -enum elf32_rel_arm_type_values { - R_ARM_RELATIVE = 23, -}; - #endif // COURGETTE_ELF_TYPES_H_