summaryrefslogtreecommitdiffstats
path: root/courgette
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-23 21:56:39 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-23 21:56:39 +0000
commit83c3cb14a4a8629df75b509e926e3c06438391d1 (patch)
tree8426eadd3e93a53532fb54ccfb33d42c840377c1 /courgette
parent968f98483f3b025fd56b31f5942c91271b464e03 (diff)
downloadchromium_src-83c3cb14a4a8629df75b509e926e3c06438391d1.zip
chromium_src-83c3cb14a4a8629df75b509e926e3c06438391d1.tar.gz
chromium_src-83c3cb14a4a8629df75b509e926e3c06438391d1.tar.bz2
Revert 224789 "Add PE64 support to courgette"
Caused failures: http://build.chromium.org/p/chromium.win/builders/Win7%20Tests%20%28dbg%29%281%29/builds/23037/steps/courgette_unittests/logs/stdio > Add PE64 support to courgette > > Add tests for PE64 > > BUG=38784 > > Review URL: https://chromiumcodereview.appspot.com/23600063 TBR=wfh@chromium.org Review URL: https://codereview.chromium.org/23591065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224806 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette')
-rw-r--r--courgette/assembly_program.cc2
-rw-r--r--courgette/courgette.gyp3
-rw-r--r--courgette/courgette.h1
-rw-r--r--courgette/courgette_tool.cc5
-rw-r--r--courgette/disassembler.cc11
-rw-r--r--courgette/disassembler.h4
-rw-r--r--courgette/disassembler_elf_32_arm.cc6
-rw-r--r--courgette/disassembler_elf_32_arm.h4
-rw-r--r--courgette/disassembler_elf_32_x86.h4
-rw-r--r--courgette/disassembler_win32_x64.cc732
-rw-r--r--courgette/disassembler_win32_x64.h160
-rw-r--r--courgette/disassembler_win32_x64_unittest.cc98
-rw-r--r--courgette/disassembler_win32_x86.cc6
-rw-r--r--courgette/disassembler_win32_x86.h4
-rw-r--r--courgette/encode_decode_unittest.cc5
-rw-r--r--courgette/encoded_program.cc40
-rw-r--r--courgette/encoded_program.h6
-rw-r--r--courgette/ensemble_apply.cc3
-rw-r--r--courgette/ensemble_create.cc9
-rw-r--r--courgette/ensemble_unittest.cc56
-rw-r--r--courgette/patch_generator_x86_32.h5
-rw-r--r--courgette/patcher_x86_32.h3
-rw-r--r--courgette/testdata/chrome64-1-2.v1.patch0
-rwxr-xr-xcourgette/testdata/chrome64_1.exe0
-rwxr-xr-xcourgette/testdata/chrome64_2.exe0
-rwxr-xr-xcourgette/testdata/en-US-64.dll0
-rw-r--r--courgette/types_elf.h32
-rw-r--r--courgette/versioning_unittest.cc2
28 files changed, 53 insertions, 1148 deletions
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc
index bfdf6ef..021de59 100644
--- a/courgette/assembly_program.cc
+++ b/courgette/assembly_program.cc
@@ -450,7 +450,7 @@ EncodedProgram* AssemblyProgram::Encode() const {
break;
}
case MAKEPERELOCS: {
- if (!encoded->AddPeMakeRelocs(kind_))
+ if (!encoded->AddPeMakeRelocs())
return NULL;
break;
}
diff --git a/courgette/courgette.gyp b/courgette/courgette.gyp
index 9de536f..03ab825 100644
--- a/courgette/courgette.gyp
+++ b/courgette/courgette.gyp
@@ -30,8 +30,6 @@
'disassembler_elf_32_x86.h',
'disassembler_win32_x86.cc',
'disassembler_win32_x86.h',
- 'disassembler_win32_x64.cc',
- 'disassembler_win32_x64.h',
'encoded_program.cc',
'encoded_program.h',
'ensemble.cc',
@@ -101,7 +99,6 @@
'difference_estimator_unittest.cc',
'disassembler_elf_32_x86_unittest.cc',
'disassembler_win32_x86_unittest.cc',
- 'disassembler_win32_x64_unittest.cc',
'encoded_program_unittest.cc',
'encode_decode_unittest.cc',
'ensemble_unittest.cc',
diff --git a/courgette/courgette.h b/courgette/courgette.h
index bf6c925..542c43f 100644
--- a/courgette/courgette.h
+++ b/courgette/courgette.h
@@ -58,7 +58,6 @@ enum ExecutableType {
EXE_WIN_32_X86 = 1,
EXE_ELF_32_X86 = 2,
EXE_ELF_32_ARM = 3,
- EXE_WIN_32_X64 = 4,
};
class SinkStream;
diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc
index a487ce9..3b231f8 100644
--- a/courgette/courgette_tool.cc
+++ b/courgette/courgette_tool.cc
@@ -140,11 +140,6 @@ bool Supported(const base::FilePath& input_file) {
format = "ELF 32 ARM";
result = true;
break;
-
- case courgette::EXE_WIN_32_X64:
- format = "Windows 64 PE";
- result = true;
- break;
}
printf("%s Executable\n", format.c_str());
diff --git a/courgette/disassembler.cc b/courgette/disassembler.cc
index 1b7b16e..798a367 100644
--- a/courgette/disassembler.cc
+++ b/courgette/disassembler.cc
@@ -15,10 +15,13 @@
#include "courgette/courgette.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"
#include "courgette/encoded_program.h"
+// COURGETTE_HISTOGRAM_TARGETS prints out a histogram of how frequently
+// different target addresses are referenced. Purely for debugging.
+#define COURGETTE_HISTOGRAM_TARGETS 0
+
namespace courgette {
////////////////////////////////////////////////////////////////////////////////
@@ -32,12 +35,6 @@ Disassembler* DetectDisassembler(const void* buffer, size_t length) {
else
delete disassembler;
- disassembler = new DisassemblerWin32X64(buffer, length);
- if (disassembler->ParseHeader())
- return disassembler;
- else
- delete disassembler;
-
disassembler = new DisassemblerElf32X86(buffer, length);
if (disassembler->ParseHeader())
return disassembler;
diff --git a/courgette/disassembler.h b/courgette/disassembler.h
index 3532b8b..8f6deb1 100644
--- a/courgette/disassembler.h
+++ b/courgette/disassembler.h
@@ -9,10 +9,6 @@
#include "courgette/courgette.h"
-// COURGETTE_HISTOGRAM_TARGETS prints out a histogram of how frequently
-// different target addresses are referenced. Purely for debugging.
-#define COURGETTE_HISTOGRAM_TARGETS 0
-
namespace courgette {
class AssemblyProgram;
diff --git a/courgette/disassembler_elf_32_arm.cc b/courgette/disassembler_elf_32_arm.cc
index 3633061..d367716 100644
--- a/courgette/disassembler_elf_32_arm.cc
+++ b/courgette/disassembler_elf_32_arm.cc
@@ -106,8 +106,8 @@ CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type, uint32 arm_op, RVA rva,
}
case ARM_OFF21: {
uint32 temp = 0;
- temp |= (arm_op & 0x000007FF) << 1; // imm11
- temp |= (arm_op & 0x003F0000) >> 4; // imm6
+ temp |= (arm_op & 0x000007FF) << 1; // imm11
+ temp |= (arm_op & 0x003F0000) >> 4; // imm6
uint32 S = (arm_op & (1 << 26)) >> 26;
uint32 j2 = (arm_op & (1 << 11)) >> 11;
@@ -115,7 +115,7 @@ CheckBool DisassemblerElf32ARM::Compress(ARM_RVA type, uint32 arm_op, RVA rva,
temp |= (S << 20) | (j1 << 19) | (j2 << 18);
- if (temp & 0x00100000) // sign extension
+ if (temp & 0x00100000) // sign extension
temp |= 0xFFE00000;
temp += 4;
(*addr) = temp;
diff --git a/courgette/disassembler_elf_32_arm.h b/courgette/disassembler_elf_32_arm.h
index 8a64766..08b8db8 100644
--- a/courgette/disassembler_elf_32_arm.h
+++ b/courgette/disassembler_elf_32_arm.h
@@ -70,10 +70,6 @@ class DisassemblerElf32ARM : public DisassemblerElf32 {
virtual CheckBool ParseRel32RelocsFromSection(
const Elf32_Shdr* section) WARN_UNUSED_RESULT;
-#if COURGETTE_HISTOGRAM_TARGETS
- std::map<RVA, int> rel32_target_rvas_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32ARM);
};
diff --git a/courgette/disassembler_elf_32_x86.h b/courgette/disassembler_elf_32_x86.h
index 043cf83..72d7e31 100644
--- a/courgette/disassembler_elf_32_x86.h
+++ b/courgette/disassembler_elf_32_x86.h
@@ -51,10 +51,6 @@ class DisassemblerElf32X86 : public DisassemblerElf32 {
virtual CheckBool ParseRel32RelocsFromSection(
const Elf32_Shdr* section) WARN_UNUSED_RESULT;
-#if COURGETTE_HISTOGRAM_TARGETS
- std::map<RVA, int> rel32_target_rvas_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32X86);
};
diff --git a/courgette/disassembler_win32_x64.cc b/courgette/disassembler_win32_x64.cc
deleted file mode 100644
index 1da5951..0000000
--- a/courgette/disassembler_win32_x64.cc
+++ /dev/null
@@ -1,732 +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_win32_x64.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-
-#include "courgette/assembly_program.h"
-#include "courgette/courgette.h"
-#include "courgette/encoded_program.h"
-
-namespace courgette {
-
-DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length)
- : Disassembler(start, length),
- incomplete_disassembly_(false),
- is_PE32_plus_(false),
- optional_header_(NULL),
- size_of_optional_header_(0),
- offset_of_data_directories_(0),
- machine_type_(0),
- number_of_sections_(0),
- sections_(NULL),
- has_text_section_(false),
- size_of_code_(0),
- size_of_initialized_data_(0),
- size_of_uninitialized_data_(0),
- base_of_code_(0),
- base_of_data_(0),
- image_base_(0),
- size_of_image_(0),
- number_of_data_directories_(0) {
-}
-
-// ParseHeader attempts to match up the buffer with the Windows data
-// structures that exist within a Windows 'Portable Executable' format file.
-// Returns 'true' if the buffer matches, and 'false' if the data looks
-// suspicious. Rather than try to 'map' the buffer to the numerous windows
-// structures, we extract the information we need into the courgette::PEInfo
-// structure.
-//
-bool DisassemblerWin32X64::ParseHeader() {
- if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
- return Bad("Too small");
-
- // Have 'MZ' magic for a DOS header?
- if (start()[0] != 'M' || start()[1] != 'Z')
- return Bad("Not MZ");
-
- // offset from DOS header to PE header is stored in DOS header.
- uint32 offset = ReadU32(start(),
- kOffsetOfFileAddressOfNewExeHeader);
-
- if (offset >= length())
- return Bad("Bad offset to PE header");
-
- const uint8* const pe_header = OffsetToPointer(offset);
- const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
- if (pe_header <= start() ||
- pe_header >= end() - kMinPEHeaderSize)
- return Bad("Bad offset to PE header");
-
- if (offset % 8 != 0)
- return Bad("Misaligned PE header");
-
- // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H.
- // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
- //
- // The first field of the IMAGE_NT_HEADERS is the signature.
- if (!(pe_header[0] == 'P' &&
- pe_header[1] == 'E' &&
- pe_header[2] == 0 &&
- pe_header[3] == 0))
- return Bad("no PE signature");
-
- // The second field of the IMAGE_NT_HEADERS is the COFF header.
- // The COFF header is also called an IMAGE_FILE_HEADER
- // http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx
- const uint8* const coff_header = pe_header + 4;
- machine_type_ = ReadU16(coff_header, 0);
- number_of_sections_ = ReadU16(coff_header, 2);
- size_of_optional_header_ = ReadU16(coff_header, 16);
-
- // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64)
- const uint8* const optional_header = coff_header + kSizeOfCoffHeader;
- optional_header_ = optional_header;
-
- if (optional_header + size_of_optional_header_ >= end())
- return Bad("optional header past end of file");
-
- // Check we can read the magic.
- if (size_of_optional_header_ < 2)
- return Bad("optional header no magic");
-
- uint16 magic = ReadU16(optional_header, 0);
-
- if (magic == kImageNtOptionalHdr32Magic) {
- is_PE32_plus_ = false;
- offset_of_data_directories_ =
- kOffsetOfDataDirectoryFromImageOptionalHeader32;
- } else if (magic == kImageNtOptionalHdr64Magic) {
- is_PE32_plus_ = true;
- offset_of_data_directories_ =
- kOffsetOfDataDirectoryFromImageOptionalHeader64;
- } else {
- return Bad("unrecognized magic");
- }
-
- // Check that we can read the rest of the the fixed fields. Data directories
- // directly follow the fixed fields of the IMAGE_OPTIONAL_HEADER.
- if (size_of_optional_header_ < offset_of_data_directories_)
- return Bad("optional header too short");
-
- // The optional header is either an IMAGE_OPTIONAL_HEADER32 or
- // IMAGE_OPTIONAL_HEADER64
- // http://msdn.microsoft.com/en-us/library/ms680339(VS.85).aspx
- //
- // Copy the fields we care about.
- size_of_code_ = ReadU32(optional_header, 4);
- size_of_initialized_data_ = ReadU32(optional_header, 8);
- size_of_uninitialized_data_ = ReadU32(optional_header, 12);
- base_of_code_ = ReadU32(optional_header, 20);
- if (is_PE32_plus_) {
- base_of_data_ = 0;
- image_base_ = ReadU64(optional_header, 24);
- } else {
- base_of_data_ = ReadU32(optional_header, 24);
- image_base_ = ReadU32(optional_header, 28);
- }
- size_of_image_ = ReadU32(optional_header, 56);
- number_of_data_directories_ =
- ReadU32(optional_header, (is_PE32_plus_ ? 108 : 92));
-
- if (size_of_code_ >= length() ||
- size_of_initialized_data_ >= length() ||
- size_of_code_ + size_of_initialized_data_ >= length()) {
- // This validation fires on some perfectly fine executables.
- // return Bad("code or initialized data too big");
- }
-
- // TODO(sra): we can probably get rid of most of the data directories.
- bool b = true;
- // 'b &= ...' could be short circuit 'b = b && ...' but it is not necessary
- // for correctness and it compiles smaller this way.
- b &= ReadDataDirectory(0, &export_table_);
- b &= ReadDataDirectory(1, &import_table_);
- b &= ReadDataDirectory(2, &resource_table_);
- b &= ReadDataDirectory(3, &exception_table_);
- b &= ReadDataDirectory(5, &base_relocation_table_);
- b &= ReadDataDirectory(11, &bound_import_table_);
- b &= ReadDataDirectory(12, &import_address_table_);
- b &= ReadDataDirectory(13, &delay_import_descriptor_);
- b &= ReadDataDirectory(14, &clr_runtime_header_);
- if (!b) {
- return Bad("malformed data directory");
- }
-
- // Sections follow the optional header.
- sections_ =
- reinterpret_cast<const Section*>(optional_header +
- size_of_optional_header_);
- size_t detected_length = 0;
-
- for (int i = 0; i < number_of_sections_; ++i) {
- const Section* section = &sections_[i];
-
- // TODO(sra): consider using the 'characteristics' field of the section
- // header to see if the section contains instructions.
- if (memcmp(section->name, ".text", 6) == 0)
- has_text_section_ = true;
-
- uint32 section_end =
- section->file_offset_of_raw_data + section->size_of_raw_data;
- if (section_end > detected_length)
- detected_length = section_end;
- }
-
- // Pretend our in-memory copy is only as long as our detected length.
- ReduceLength(detected_length);
-
- if (is_32bit()) {
- return Bad("32 bit executables are not supported by this disassembler");
- }
-
- if (!has_text_section()) {
- return Bad("Resource-only executables are not yet supported");
- }
-
- return Good();
-}
-
-bool DisassemblerWin32X64::Disassemble(AssemblyProgram* target) {
- if (!ok())
- return false;
-
- target->set_image_base(image_base());
-
- if (!ParseAbs32Relocs())
- return false;
-
- ParseRel32RelocsFromSections();
-
- if (!ParseFile(target))
- return false;
-
- target->DefaultAssignIndexes();
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool DisassemblerWin32X64::ParseRelocs(std::vector<RVA> *relocs) {
- relocs->clear();
-
- size_t relocs_size = base_relocation_table_.size_;
- if (relocs_size == 0)
- return true;
-
- // The format of the base relocation table is a sequence of variable sized
- // IMAGE_BASE_RELOCATION blocks. Search for
- // "The format of the base relocation data is somewhat quirky"
- // at http://msdn.microsoft.com/en-us/library/ms809762.aspx
-
- const uint8* relocs_start = RVAToPointer(base_relocation_table_.address_);
- const uint8* relocs_end = relocs_start + relocs_size;
-
- // Make sure entire base relocation table is within the buffer.
- if (relocs_start < start() ||
- relocs_start >= end() ||
- relocs_end <= start() ||
- relocs_end > end()) {
- return Bad(".relocs outside image");
- }
-
- const uint8* block = relocs_start;
-
- // Walk the variable sized blocks.
- while (block + 8 < relocs_end) {
- RVA page_rva = ReadU32(block, 0);
- uint32 size = ReadU32(block, 4);
- if (size < 8 || // Size includes header ...
- size % 4 != 0) // ... and is word aligned.
- return Bad("unreasonable relocs block");
-
- const uint8* end_entries = block + size;
-
- if (end_entries <= block ||
- end_entries <= start() ||
- end_entries > end())
- return Bad(".relocs block outside image");
-
- // Walk through the two-byte entries.
- for (const uint8* p = block + 8; p < end_entries; p += 2) {
- uint16 entry = ReadU16(p, 0);
- int type = entry >> 12;
- int offset = entry & 0xFFF;
-
- RVA rva = page_rva + offset;
- if (type == 10) { // IMAGE_REL_BASED_DIR64
- relocs->push_back(rva);
- } else if (type == 0) { // IMAGE_REL_BASED_ABSOLUTE
- // Ignore, used as padding.
- } else {
- // Does not occur in Windows x64 executables.
- return Bad("unknown type of reloc");
- }
- }
-
- block += size;
- }
-
- std::sort(relocs->begin(), relocs->end());
-
- return true;
-}
-
-const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const {
- for (int i = 0; i < number_of_sections_; i++) {
- const Section* section = &sections_[i];
- uint32 offset = rva - section->virtual_address;
- if (offset < section->virtual_size) {
- return section;
- }
- }
- return NULL;
-}
-
-int DisassemblerWin32X64::RVAToFileOffset(RVA rva) const {
- const Section* section = RVAToSection(rva);
- if (section) {
- uint32 offset = rva - section->virtual_address;
- if (offset < section->size_of_raw_data) {
- return section->file_offset_of_raw_data + offset;
- } else {
- return kNoOffset; // In section but not in file (e.g. uninit data).
- }
- }
-
- // Small RVA values point into the file header in the loaded image.
- // RVA 0 is the module load address which Windows uses as the module handle.
- // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
- // DOS header.
- if (rva == 0 || rva == 2)
- return rva;
-
- NOTREACHED();
- return kNoOffset;
-}
-
-const uint8* DisassemblerWin32X64::RVAToPointer(RVA rva) const {
- int file_offset = RVAToFileOffset(rva);
- if (file_offset == kNoOffset)
- return NULL;
- else
- return OffsetToPointer(file_offset);
-}
-
-std::string DisassemblerWin32X64::SectionName(const Section* section) {
- if (section == NULL)
- return "<none>";
- char name[9];
- memcpy(name, section->name, 8);
- name[8] = '\0'; // Ensure termination.
- return name;
-}
-
-CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) {
- // Walk all the bytes in the file, whether or not in a section.
- uint32 file_offset = 0;
- while (file_offset < length()) {
- const Section* section = FindNextSection(file_offset);
- if (section == NULL) {
- // No more sections. There should not be extra stuff following last
- // section.
- // ParseNonSectionFileRegion(file_offset, pe_info().length(), program);
- break;
- }
- if (file_offset < section->file_offset_of_raw_data) {
- uint32 section_start_offset = section->file_offset_of_raw_data;
- if(!ParseNonSectionFileRegion(file_offset, section_start_offset,
- program))
- return false;
-
- file_offset = section_start_offset;
- }
- uint32 end = file_offset + section->size_of_raw_data;
- if (!ParseFileRegion(section, file_offset, end, program))
- return false;
- file_offset = end;
- }
-
-#if COURGETTE_HISTOGRAM_TARGETS
- HistogramTargets("abs32 relocs", abs32_target_rvas_);
- HistogramTargets("rel32 relocs", rel32_target_rvas_);
-#endif
-
- return true;
-}
-
-bool DisassemblerWin32X64::ParseAbs32Relocs() {
- abs32_locations_.clear();
- if (!ParseRelocs(&abs32_locations_))
- return false;
-
- std::sort(abs32_locations_.begin(), abs32_locations_.end());
-
-#if COURGETTE_HISTOGRAM_TARGETS
- for (size_t i = 0; i < abs32_locations_.size(); ++i) {
- RVA rva = abs32_locations_[i];
- // The 4 bytes at the relocation are a reference to some address.
- uint32 target_address = Read32LittleEndian(RVAToPointer(rva));
- ++abs32_target_rvas_[target_address - image_base()];
- }
-#endif
- return true;
-}
-
-void DisassemblerWin32X64::ParseRel32RelocsFromSections() {
- uint32 file_offset = 0;
- while (file_offset < length()) {
- const Section* section = FindNextSection(file_offset);
- if (section == NULL)
- break;
- if (file_offset < section->file_offset_of_raw_data)
- file_offset = section->file_offset_of_raw_data;
- ParseRel32RelocsFromSection(section);
- file_offset += section->size_of_raw_data;
- }
- std::sort(rel32_locations_.begin(), rel32_locations_.end());
-
-#if COURGETTE_HISTOGRAM_TARGETS
- VLOG(1) << "abs32_locations_ " << abs32_locations_.size()
- << "\nrel32_locations_ " << rel32_locations_.size()
- << "\nabs32_target_rvas_ " << abs32_target_rvas_.size()
- << "\nrel32_target_rvas_ " << rel32_target_rvas_.size();
-
- int common = 0;
- std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin();
- std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin();
- while (abs32_iter != abs32_target_rvas_.end() &&
- rel32_iter != rel32_target_rvas_.end()) {
- if (abs32_iter->first < rel32_iter->first)
- ++abs32_iter;
- else if (rel32_iter->first < abs32_iter->first)
- ++rel32_iter;
- else {
- ++common;
- ++abs32_iter;
- ++rel32_iter;
- }
- }
- VLOG(1) << "common " << common;
-#endif
-}
-
-void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) {
- // TODO(sra): use characteristic.
- bool isCode = strcmp(section->name, ".text") == 0;
- if (!isCode)
- return;
-
- uint32 start_file_offset = section->file_offset_of_raw_data;
- uint32 end_file_offset = start_file_offset + section->size_of_raw_data;
- RVA relocs_start_rva = base_relocation_table().address_;
-
- const uint8* start_pointer = OffsetToPointer(start_file_offset);
- const uint8* end_pointer = OffsetToPointer(end_file_offset);
-
- RVA start_rva = FileOffsetToRVA(start_file_offset);
- RVA end_rva = start_rva + section->virtual_size;
-
- // Quick way to convert from Pointer to RVA within a single Section is to
- // subtract 'pointer_to_rva'.
- const uint8* const adjust_pointer_to_rva = start_pointer - start_rva;
-
- std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
-
- // Find the rel32 relocations.
- const uint8* p = start_pointer;
- while (p < end_pointer) {
- RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
- if (current_rva == relocs_start_rva) {
- uint32 relocs_size = base_relocation_table().size_;
- if (relocs_size) {
- p += relocs_size;
- continue;
- }
- }
-
- //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
- // ++abs32_pos;
-
- // Heuristic discovery of rel32 locations in instruction stream: are the
- // next few bytes the start of an instruction containing a rel32
- // addressing mode?
- const uint8* rel32 = NULL;
-
- if (p + 5 <= end_pointer) {
- if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32
- rel32 = p + 1;
- }
- }
- if (p + 6 <= end_pointer) {
- if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form
- if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely
- rel32 = p + 2;
- }
- }
- if (rel32) {
- RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva);
-
- // Is there an abs32 reloc overlapping the candidate?
- while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3)
- ++abs32_pos;
- // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte
- // region that could overlap rel32_rva.
- if (abs32_pos != abs32_locations_.end()) {
- if (*abs32_pos < rel32_rva + 4) {
- // Beginning of abs32 reloc is before end of rel32 reloc so they
- // overlap. Skip four bytes past the abs32 reloc.
- p += (*abs32_pos + 4) - current_rva;
- continue;
- }
- }
-
- RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32);
- // To be valid, rel32 target must be within image, and within this
- // section.
- if (IsValidRVA(target_rva) &&
- start_rva <= target_rva && target_rva < end_rva) {
- rel32_locations_.push_back(rel32_rva);
-#if COURGETTE_HISTOGRAM_TARGETS
- ++rel32_target_rvas_[target_rva];
-#endif
- p = rel32 + 4;
- continue;
- }
- }
- p += 1;
- }
-}
-
-CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion(
- uint32 start_file_offset,
- uint32 end_file_offset,
- AssemblyProgram* program) {
- if (incomplete_disassembly_)
- return true;
-
- const uint8* start = OffsetToPointer(start_file_offset);
- const uint8* end = OffsetToPointer(end_file_offset);
-
- const uint8* p = start;
-
- while (p < end) {
- if (!program->EmitByteInstruction(*p))
- return false;
- ++p;
- }
-
- return true;
-}
-
-CheckBool DisassemblerWin32X64::ParseFileRegion(
- const Section* section,
- uint32 start_file_offset, uint32 end_file_offset,
- AssemblyProgram* program) {
- RVA relocs_start_rva = base_relocation_table().address_;
-
- const uint8* start_pointer = OffsetToPointer(start_file_offset);
- const uint8* end_pointer = OffsetToPointer(end_file_offset);
-
- RVA start_rva = FileOffsetToRVA(start_file_offset);
- RVA end_rva = start_rva + section->virtual_size;
-
- // Quick way to convert from Pointer to RVA within a single Section is to
- // subtract 'pointer_to_rva'.
- const uint8* const adjust_pointer_to_rva = start_pointer - start_rva;
-
- std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin();
- std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
-
- if (!program->EmitOriginInstruction(start_rva))
- return false;
-
- const uint8* p = start_pointer;
-
- while (p < end_pointer) {
- RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
-
- // The base relocation table is usually in the .relocs section, but it could
- // actually be anywhere. Make sure we skip it because we will regenerate it
- // during assembly.
- if (current_rva == relocs_start_rva) {
- if (!program->EmitPeRelocsInstruction())
- return false;
- uint32 relocs_size = base_relocation_table().size_;
- if (relocs_size) {
- p += relocs_size;
- continue;
- }
- }
-
- while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
- ++abs32_pos;
-
- if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) {
- uint32 target_address = Read32LittleEndian(p);
- RVA target_rva = target_address - image_base();
- // TODO(sra): target could be Label+offset. It is not clear how to guess
- // which it might be. We assume offset==0.
- if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
- return false;
- p += 4;
- continue;
- }
-
- while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva)
- ++rel32_pos;
-
- if (rel32_pos != rel32_locations_.end() && *rel32_pos == current_rva) {
- RVA target_rva = current_rva + 4 + Read32LittleEndian(p);
- if (!program->EmitRel32(program->FindOrMakeRel32Label(target_rva)))
- return false;
- p += 4;
- continue;
- }
-
- if (incomplete_disassembly_) {
- if ((abs32_pos == abs32_locations_.end() || end_rva <= *abs32_pos) &&
- (rel32_pos == rel32_locations_.end() || end_rva <= *rel32_pos) &&
- (end_rva <= relocs_start_rva || current_rva >= relocs_start_rva)) {
- // No more relocs in this section, don't bother encoding bytes.
- break;
- }
- }
-
- if (!program->EmitByteInstruction(*p))
- return false;
- p += 1;
- }
-
- return true;
-}
-
-#if COURGETTE_HISTOGRAM_TARGETS
-// Histogram is printed to std::cout. It is purely for debugging the algorithm
-// and is only enabled manually in 'exploration' builds. I don't want to add
-// command-line configuration for this feature because this code has to be
-// small, which means compiled-out.
-void DisassemblerWin32X64::HistogramTargets(const char* kind,
- const std::map<RVA, int>& map) {
- int total = 0;
- std::map<int, std::vector<RVA> > h;
- for (std::map<RVA, int>::const_iterator p = map.begin();
- p != map.end();
- ++p) {
- h[p->second].push_back(p->first);
- total += p->second;
- }
-
- std::cout << total << " " << kind << " to "
- << map.size() << " unique targets" << std::endl;
-
- std::cout << "indegree: #targets-with-indegree (example)" << std::endl;
- const int kFirstN = 15;
- bool someSkipped = false;
- int index = 0;
- for (std::map<int, std::vector<RVA> >::reverse_iterator p = h.rbegin();
- p != h.rend();
- ++p) {
- ++index;
- if (index <= kFirstN || p->first <= 3) {
- if (someSkipped) {
- std::cout << "..." << std::endl;
- }
- size_t count = p->second.size();
- std::cout << std::dec << p->first << ": " << count;
- if (count <= 2) {
- for (size_t i = 0; i < count; ++i)
- std::cout << " " << DescribeRVA(p->second[i]);
- }
- std::cout << std::endl;
- someSkipped = false;
- } else {
- someSkipped = true;
- }
- }
-}
-#endif // COURGETTE_HISTOGRAM_TARGETS
-
-
-// DescribeRVA is for debugging only. I would put it under #ifdef DEBUG except
-// that during development I'm finding I need to call it when compiled in
-// Release mode. Hence:
-// TODO(sra): make this compile only for debug mode.
-std::string DisassemblerWin32X64::DescribeRVA(RVA rva) const {
- const Section* section = RVAToSection(rva);
- std::ostringstream s;
- s << std::hex << rva;
- if (section) {
- s << " (";
- s << SectionName(section) << "+"
- << std::hex << (rva - section->virtual_address)
- << ")";
- }
- return s.str();
-}
-
-const Section* DisassemblerWin32X64::FindNextSection(uint32 fileOffset) const {
- const Section* best = 0;
- for (int i = 0; i < number_of_sections_; i++) {
- const Section* section = &sections_[i];
- if (section->size_of_raw_data > 0) { // i.e. has data in file.
- if (fileOffset <= section->file_offset_of_raw_data) {
- if (best == 0 ||
- section->file_offset_of_raw_data < best->file_offset_of_raw_data) {
- best = section;
- }
- }
- }
- }
- return best;
-}
-
-RVA DisassemblerWin32X64::FileOffsetToRVA(uint32 file_offset) const {
- for (int i = 0; i < number_of_sections_; i++) {
- const Section* section = &sections_[i];
- uint32 offset = file_offset - section->file_offset_of_raw_data;
- if (offset < section->size_of_raw_data) {
- return section->virtual_address + offset;
- }
- }
- return 0;
-}
-
-bool DisassemblerWin32X64::ReadDataDirectory(
- int index,
- ImageDataDirectory* directory) {
-
- if (index < number_of_data_directories_) {
- size_t offset = index * 8 + offset_of_data_directories_;
- if (offset >= size_of_optional_header_)
- return Bad("number of data directories inconsistent");
- const uint8* data_directory = optional_header_ + offset;
- if (data_directory < start() ||
- data_directory + 8 >= end())
- return Bad("data directory outside image");
- RVA rva = ReadU32(data_directory, 0);
- size_t size = ReadU32(data_directory, 4);
- if (size > size_of_image_)
- return Bad("data directory size too big");
-
- // TODO(sra): validate RVA.
- directory->address_ = rva;
- directory->size_ = static_cast<uint32>(size);
- return true;
- } else {
- directory->address_ = 0;
- directory->size_ = 0;
- return true;
- }
-}
-
-} // namespace courgette
diff --git a/courgette/disassembler_win32_x64.h b/courgette/disassembler_win32_x64.h
deleted file mode 100644
index bce4802..0000000
--- a/courgette/disassembler_win32_x64.h
+++ /dev/null
@@ -1,160 +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_WIN32_X64_H_
-#define COURGETTE_DISASSEMBLER_WIN32_X64_H_
-
-#include "base/basictypes.h"
-#include "courgette/disassembler.h"
-#include "courgette/memory_allocator.h"
-#include "courgette/types_win_pe.h"
-
-#ifdef COURGETTE_HISTOGRAM_TARGETS
-#include <map>
-#endif
-
-namespace courgette {
-
-class AssemblyProgram;
-
-class DisassemblerWin32X64 : public Disassembler {
- public:
- explicit DisassemblerWin32X64(const void* start, size_t length);
-
- virtual ExecutableType kind() { return EXE_WIN_32_X64; }
-
- // Returns 'true' if the buffer appears to point to a Windows 32 bit
- // executable, 'false' otherwise. If ParseHeader() succeeds, other member
- // functions may be called.
- virtual bool ParseHeader();
-
- virtual bool Disassemble(AssemblyProgram* target);
-
- //
- // Exposed for test purposes
- //
-
- bool has_text_section() const { return has_text_section_; }
- uint32 size_of_code() const { return size_of_code_; }
- bool is_32bit() const { return !is_PE32_plus_; }
-
- // Returns 'true' if the base relocation table can be parsed.
- // Output is a vector of the RVAs corresponding to locations within executable
- // that are listed in the base relocation table.
- bool ParseRelocs(std::vector<RVA> *addresses);
-
- // Returns Section containing the relative virtual address, or NULL if none.
- const Section* RVAToSection(RVA rva) const;
-
- static const int kNoOffset = -1;
- // Returns kNoOffset if there is no file offset corresponding to 'rva'.
- int RVAToFileOffset(RVA rva) const;
-
- // Returns same as FileOffsetToPointer(RVAToFileOffset(rva)) except that NULL
- // is returned if there is no file offset corresponding to 'rva'.
- const uint8* RVAToPointer(RVA rva) const;
-
- static std::string SectionName(const Section* section);
-
- protected:
- CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT;
- bool ParseAbs32Relocs();
- void ParseRel32RelocsFromSections();
- void ParseRel32RelocsFromSection(const Section* section);
-
- CheckBool ParseNonSectionFileRegion(uint32 start_file_offset,
- uint32 end_file_offset, AssemblyProgram* program) WARN_UNUSED_RESULT;
- CheckBool ParseFileRegion(const Section* section,
- uint32 start_file_offset, uint32 end_file_offset,
- AssemblyProgram* program) WARN_UNUSED_RESULT;
-
-#if COURGETTE_HISTOGRAM_TARGETS
- void HistogramTargets(const char* kind, const std::map<RVA, int>& map);
-#endif
-
- // Most addresses are represented as 32-bit RVAs. The one address we can't
- // do this with is the image base address. 'image_base' is valid only for
- // 32-bit executables. 'image_base_64' is valid for 32- and 64-bit executable.
- uint64 image_base() const { return image_base_; }
-
- const ImageDataDirectory& base_relocation_table() const {
- return base_relocation_table_;
- }
-
- bool IsValidRVA(RVA rva) const { return rva < size_of_image_; }
-
- // Returns description of the RVA, e.g. ".text+0x1243". For debugging only.
- std::string DescribeRVA(RVA rva) const;
-
- // Finds the first section at file_offset or above. Does not return sections
- // that have no raw bytes in the file.
- const Section* FindNextSection(uint32 file_offset) const;
-
- // There are 2 'coordinate systems' for reasoning about executables.
- // FileOffset - the the offset within a single .EXE or .DLL *file*.
- // RVA - relative virtual address (offset within *loaded image*)
- // FileOffsetToRVA and RVAToFileOffset convert between these representations.
-
- RVA FileOffsetToRVA(uint32 offset) const;
-
-
- private:
-
- bool ReadDataDirectory(int index, ImageDataDirectory* dir);
-
- bool incomplete_disassembly_; // 'true' if can leave out 'uninteresting' bits
-
- std::vector<RVA> abs32_locations_;
- std::vector<RVA> rel32_locations_;
-
- //
- // Fields that are always valid.
- //
-
- //
- // Information that is valid after successful ParseHeader.
- //
- bool is_PE32_plus_; // PE32_plus is for 64 bit executables.
-
- // Location and size of IMAGE_OPTIONAL_HEADER in the buffer.
- const uint8 *optional_header_;
- uint16 size_of_optional_header_;
- uint16 offset_of_data_directories_;
-
- uint16 machine_type_;
- uint16 number_of_sections_;
- const Section *sections_;
- bool has_text_section_;
-
- uint32 size_of_code_;
- uint32 size_of_initialized_data_;
- uint32 size_of_uninitialized_data_;
- RVA base_of_code_;
- RVA base_of_data_;
-
- uint64 image_base_;
- uint32 size_of_image_;
- int number_of_data_directories_;
-
- ImageDataDirectory export_table_;
- ImageDataDirectory import_table_;
- ImageDataDirectory resource_table_;
- ImageDataDirectory exception_table_;
- ImageDataDirectory base_relocation_table_;
- ImageDataDirectory bound_import_table_;
- ImageDataDirectory import_address_table_;
- ImageDataDirectory delay_import_descriptor_;
- ImageDataDirectory clr_runtime_header_;
-
-#if COURGETTE_HISTOGRAM_TARGETS
- std::map<RVA, int> abs32_target_rvas_;
- std::map<RVA, int> rel32_target_rvas_;
-#endif
-
-
- DISALLOW_COPY_AND_ASSIGN(DisassemblerWin32X64);
-};
-
-} // namespace courgette
-#endif // COURGETTE_DISASSEMBLER_WIN32_X64_H_
diff --git a/courgette/disassembler_win32_x64_unittest.cc b/courgette/disassembler_win32_x64_unittest.cc
deleted file mode 100644
index 345d416..0000000
--- a/courgette/disassembler_win32_x64_unittest.cc
+++ /dev/null
@@ -1,98 +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_win32_x64.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "courgette/base_test_unittest.h"
-
-class DisassemblerWin32X64Test : public BaseTest {
- public:
- void TestExe() const;
- void TestExe32() const;
- void TestResourceDll() const;
-};
-
-void DisassemblerWin32X64Test::TestExe() const {
- std::string file1 = FileContents("chrome64_1.exe");
-
- scoped_ptr<courgette::DisassemblerWin32X64> disassembler(
- new courgette::DisassemblerWin32X64(file1.c_str(), file1.length()));
-
- bool can_parse_header = disassembler->ParseHeader();
- EXPECT_TRUE(can_parse_header);
-
- // The executable is the whole file, not 'embedded' with the file
- EXPECT_EQ(file1.length(), disassembler->length());
-
- EXPECT_TRUE(disassembler->ok());
- EXPECT_TRUE(disassembler->has_text_section());
- EXPECT_EQ(488448U, disassembler->size_of_code());
- EXPECT_FALSE(disassembler->is_32bit());
- EXPECT_EQ(courgette::DisassemblerWin32X64::SectionName(
- disassembler->RVAToSection(0x00401234 - 0x00400000)),
- std::string(".text"));
-
- EXPECT_EQ(0, disassembler->RVAToFileOffset(0));
- EXPECT_EQ(1024, disassembler->RVAToFileOffset(4096));
- EXPECT_EQ(46928, disassembler->RVAToFileOffset(50000));
-
- std::vector<courgette::RVA> relocs;
- bool can_parse_relocs = disassembler->ParseRelocs(&relocs);
- EXPECT_TRUE(can_parse_relocs);
-
- const uint8* offset_p = disassembler->OffsetToPointer(0);
- EXPECT_EQ(reinterpret_cast<const void*>(file1.c_str()),
- reinterpret_cast<const void*>(offset_p));
- EXPECT_EQ('M', offset_p[0]);
- EXPECT_EQ('Z', offset_p[1]);
-
- const uint8* rva_p = disassembler->RVAToPointer(0);
- EXPECT_EQ(reinterpret_cast<const void*>(file1.c_str()),
- reinterpret_cast<const void*>(rva_p));
- EXPECT_EQ('M', rva_p[0]);
- EXPECT_EQ('Z', rva_p[1]);
-}
-
-void DisassemblerWin32X64Test::TestExe32() const {
- std::string file1 = FileContents("setup1.exe");
-
- scoped_ptr<courgette::DisassemblerWin32X64> disassembler(
- new courgette::DisassemblerWin32X64(file1.c_str(), file1.length()));
-
- bool can_parse_header = disassembler->ParseHeader();
- EXPECT_FALSE(can_parse_header);
-
- // The executable is the whole file, not 'embedded' with the file
- EXPECT_EQ(file1.length(), disassembler->length());
-
- EXPECT_FALSE(disassembler->ok());
- EXPECT_TRUE(disassembler->has_text_section());
- EXPECT_EQ(449536U, disassembler->size_of_code());
- EXPECT_TRUE(disassembler->is_32bit());
-}
-
-void DisassemblerWin32X64Test::TestResourceDll() const {
- std::string file1 = FileContents("en-US-64.dll");
-
- scoped_ptr<courgette::DisassemblerWin32X64> disassembler(
- new courgette::DisassemblerWin32X64(file1.c_str(), file1.length()));
-
- bool can_parse_header = disassembler->ParseHeader();
- EXPECT_FALSE(can_parse_header);
-
- // The executable is the whole file, not 'embedded' with the file
- EXPECT_EQ(file1.length(), disassembler->length());
-
- EXPECT_FALSE(disassembler->ok());
- EXPECT_FALSE(disassembler->has_text_section());
- EXPECT_EQ(0U, disassembler->size_of_code());
- EXPECT_FALSE(disassembler->is_32bit());
-}
-
-TEST_F(DisassemblerWin32X64Test, All) {
- TestExe();
- TestExe32();
- TestResourceDll();
-}
diff --git a/courgette/disassembler_win32_x86.cc b/courgette/disassembler_win32_x86.cc
index eeb17ec..f182062 100644
--- a/courgette/disassembler_win32_x86.cc
+++ b/courgette/disassembler_win32_x86.cc
@@ -15,6 +15,10 @@
#include "courgette/courgette.h"
#include "courgette/encoded_program.h"
+// COURGETTE_HISTOGRAM_TARGETS prints out a histogram of how frequently
+// different target addresses are referenced. Purely for debugging.
+#define COURGETTE_HISTOGRAM_TARGETS 0
+
namespace courgette {
DisassemblerWin32X86::DisassemblerWin32X86(const void* start, size_t length)
@@ -185,7 +189,7 @@ bool DisassemblerWin32X86::ParseHeader() {
ReduceLength(detected_length);
if (!is_32bit()) {
- return Bad("64 bit executables are not supported by this disassembler");
+ return Bad("64 bit executables are not yet supported");
}
if (!has_text_section()) {
diff --git a/courgette/disassembler_win32_x86.h b/courgette/disassembler_win32_x86.h
index dec339f..59914277 100644
--- a/courgette/disassembler_win32_x86.h
+++ b/courgette/disassembler_win32_x86.h
@@ -10,10 +10,6 @@
#include "courgette/memory_allocator.h"
#include "courgette/types_win_pe.h"
-#ifdef COURGETTE_HISTOGRAM_TARGETS
-#include <map>
-#endif
-
namespace courgette {
class AssemblyProgram;
diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc
index 0e121d6..20f0e16 100644
--- a/courgette/encode_decode_unittest.cc
+++ b/courgette/encode_decode_unittest.cc
@@ -73,11 +73,6 @@ TEST_F(EncodeDecodeTest, PE) {
TestAssembleToStreamDisassemble(file, 971850);
}
-TEST_F(EncodeDecodeTest, PE64) {
- std::string file = FileContents("chrome64_1.exe");
- TestAssembleToStreamDisassemble(file, 814709);
-}
-
TEST_F(EncodeDecodeTest, Elf_Small) {
std::string file = FileContents("elf-32-1");
TestAssembleToStreamDisassemble(file, 135988);
diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc
index 8d45d72..c619c6a 100644
--- a/courgette/encoded_program.cc
+++ b/courgette/encoded_program.cc
@@ -248,10 +248,8 @@ CheckBool EncodedProgram::AddRel32ARM(uint16 op, int label_index) {
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);
- return ops_.push_back(MAKE_PE64_RELOCATION_TABLE);
+CheckBool EncodedProgram::AddPeMakeRelocs() {
+ return ops_.push_back(MAKE_PE_RELOCATION_TABLE);
}
CheckBool EncodedProgram::AddElfMakeRelocs() {
@@ -530,7 +528,6 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
RVA current_rva = 0;
bool pending_pe_relocation_table = false;
- uint8 pending_pe_relocation_table_type = 0x03; // IMAGE_REL_BASED_HIGHLOW
Elf32_Word pending_elf_relocation_table_type = 0;
SinkStream bytes_following_relocation_table;
@@ -616,8 +613,9 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
// 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_pe_relocation_table)
- return false; // Can't have two base relocation tables.
+ if (pending_pe_relocation_table) // Can't have two base relocation
+ // tables.
+ return false;
pending_pe_relocation_table = true;
output = &bytes_following_relocation_table;
@@ -632,22 +630,13 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
// emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE.
}
- case MAKE_PE64_RELOCATION_TABLE: {
- if (pending_pe_relocation_table)
- return false; // Can't have two base relocation tables.
-
- pending_pe_relocation_table = true;
- pending_pe_relocation_table_type = 0x0A; // IMAGE_REL_BASED_DIR64
- output = &bytes_following_relocation_table;
- 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.
+ if (pending_elf_relocation_table_type) // Can't have two relocation
+ // tables.
+ return false;
pending_elf_relocation_table_type = R_ARM_RELATIVE;
output = &bytes_following_relocation_table;
@@ -658,8 +647,9 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
// 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.
+ if (pending_elf_relocation_table_type) // Can't have two relocation
+ // tables.
+ return false;
pending_elf_relocation_table_type = R_386_RELATIVE;
output = &bytes_following_relocation_table;
@@ -669,8 +659,7 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
}
if (pending_pe_relocation_table) {
- if (!GeneratePeRelocations(final_buffer,
- pending_pe_relocation_table_type) ||
+ if (!GeneratePeRelocations(final_buffer) ||
!final_buffer->Append(&bytes_following_relocation_table))
return false;
}
@@ -732,8 +721,7 @@ class RelocBlock {
RelocBlockPOD pod;
};
-CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer,
- uint8 type) {
+CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) {
std::sort(abs32_relocs_.begin(), abs32_relocs_.end());
RelocBlock block;
@@ -747,7 +735,7 @@ CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer,
block.pod.page_rva = page_rva;
}
if (ok)
- block.Add(((static_cast<uint16>(type)) << 12 ) | (rva & 0xFFF));
+ block.Add(0x3000 | (rva & 0xFFF));
}
ok &= block.Flush(buffer);
return ok;
diff --git a/courgette/encoded_program.h b/courgette/encoded_program.h
index a370e3a..3eca364 100644
--- a/courgette/encoded_program.h
+++ b/courgette/encoded_program.h
@@ -45,7 +45,7 @@ class EncodedProgram {
CheckBool AddRel32(int label_index) WARN_UNUSED_RESULT;
CheckBool AddRel32ARM(uint16 op, int label_index) WARN_UNUSED_RESULT;
CheckBool AddAbs32(int label_index) WARN_UNUSED_RESULT;
- CheckBool AddPeMakeRelocs(ExecutableType kind) WARN_UNUSED_RESULT;
+ CheckBool AddPeMakeRelocs() WARN_UNUSED_RESULT;
CheckBool AddElfMakeRelocs() WARN_UNUSED_RESULT;
CheckBool AddElfARMMakeRelocs() WARN_UNUSED_RESULT;
@@ -75,7 +75,6 @@ class EncodedProgram {
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
- MAKE_PE64_RELOCATION_TABLE = 8, // Emit PE64 base relocation table blocks.
// ARM reserves 0x1000-LAST_ARM, bits 13-16 define the opcode
// subset, and 1-12 are the compressed ARM op.
REL32ARM8 = 0x1000,
@@ -92,8 +91,7 @@ class EncodedProgram {
typedef NoThrowBuffer<OP> OPVector;
void DebuggingSummary();
- CheckBool GeneratePeRelocations(SinkStream *buffer,
- uint8 type) WARN_UNUSED_RESULT;
+ CheckBool GeneratePeRelocations(SinkStream *buffer) WARN_UNUSED_RESULT;
CheckBool GenerateElfRelocations(Elf32_Word pending_elf_relocation_table,
SinkStream *buffer) WARN_UNUSED_RESULT;
CheckBool DefineLabelCommon(RvaVector*, int, RVA) WARN_UNUSED_RESULT;
diff --git a/courgette/ensemble_apply.cc b/courgette/ensemble_apply.cc
index be3618b..7c7cca8 100644
--- a/courgette/ensemble_apply.cc
+++ b/courgette/ensemble_apply.cc
@@ -148,9 +148,6 @@ Status EnsemblePatchApplication::ReadInitialParameters(
case EXE_ELF_32_ARM:
patcher = new PatcherX86_32(base_region_);
break;
- case EXE_WIN_32_X64:
- patcher = new PatcherX86_32(base_region_);
- break;
}
if (patcher)
diff --git a/courgette/ensemble_create.cc b/courgette/ensemble_create.cc
index ea5873c..550f0ad 100644
--- a/courgette/ensemble_create.cc
+++ b/courgette/ensemble_create.cc
@@ -94,15 +94,6 @@ TransformationPatchGenerator* MakeGenerator(Element* old_element,
EXE_ELF_32_ARM);
return generator;
}
- case EXE_WIN_32_X64: {
- TransformationPatchGenerator* generator =
- new PatchGeneratorX86_32(
- old_element,
- new_element,
- new PatcherX86_32(old_element->region()),
- EXE_WIN_32_X64);
- return generator;
- }
}
LOG(WARNING) << "Unexpected Element::Kind " << old_element->kind();
diff --git a/courgette/ensemble_unittest.cc b/courgette/ensemble_unittest.cc
index e2f1198..d35622f 100644
--- a/courgette/ensemble_unittest.cc
+++ b/courgette/ensemble_unittest.cc
@@ -12,8 +12,6 @@ class EnsembleTest : public BaseTest {
void TestEnsemble(std::string src_bytes, std::string tgt_bytes) const;
void PeEnsemble() const;
- void Pe64Ensemble() const;
- void Elf32Ensemble() const;
};
void EnsembleTest::TestEnsemble(std::string src_bytes,
@@ -46,52 +44,18 @@ void EnsembleTest::TestEnsemble(std::string src_bytes,
target.OriginalLength()));
}
-void EnsembleTest::Elf32Ensemble() const {
- std::list<std::string> src_ensemble;
- std::list<std::string> tgt_ensemble;
-
- src_ensemble.push_back("elf-32-1");
-
- tgt_ensemble.push_back("elf-32-2");
-
- std::string src_bytes = FilesContents(src_ensemble);
- std::string tgt_bytes = FilesContents(tgt_ensemble);
-
- src_bytes = "aaabbbccc" + src_bytes + "dddeeefff";
- tgt_bytes = "aaagggccc" + tgt_bytes + "dddeeefff";
-
- TestEnsemble(src_bytes, tgt_bytes);
-}
-
void EnsembleTest::PeEnsemble() const {
std::list<std::string> src_ensemble;
std::list<std::string> tgt_ensemble;
src_ensemble.push_back("en-US.dll");
src_ensemble.push_back("setup1.exe");
+ src_ensemble.push_back("elf-32-1");
+ src_ensemble.push_back("pe-64.exe");
tgt_ensemble.push_back("en-US.dll");
tgt_ensemble.push_back("setup2.exe");
-
- std::string src_bytes = FilesContents(src_ensemble);
- std::string tgt_bytes = FilesContents(tgt_ensemble);
-
- src_bytes = "aaabbbccc" + src_bytes + "dddeeefff";
- tgt_bytes = "aaagggccc" + tgt_bytes + "dddeeefff";
-
- TestEnsemble(src_bytes, tgt_bytes);
-}
-
-void EnsembleTest::Pe64Ensemble() const {
- std::list<std::string> src_ensemble;
- std::list<std::string> tgt_ensemble;
-
- src_ensemble.push_back("en-US-64.dll");
- src_ensemble.push_back("chrome64_1.exe");
- src_ensemble.push_back("pe-64.exe");
-
- tgt_ensemble.push_back("en-US-64.dll");
- tgt_ensemble.push_back("chrome64_2.exe");
+ tgt_ensemble.push_back("elf-32-2");
tgt_ensemble.push_back("pe-64.exe");
std::string src_bytes = FilesContents(src_ensemble);
@@ -103,17 +67,7 @@ void EnsembleTest::Pe64Ensemble() const {
TestEnsemble(src_bytes, tgt_bytes);
}
-// Ensemble tests still take too long on Windows so disabling for now
-// TODO(dgarrett) http://code.google.com/p/chromium/issues/detail?id=101614
-
-TEST_F(EnsembleTest, DISABLED_PE) {
+TEST_F(EnsembleTest, DISABLED_All) {
+ // TODO(dgarrett) http://code.google.com/p/chromium/issues/detail?id=101614
PeEnsemble();
}
-
-TEST_F(EnsembleTest, DISABLED_PE64) {
- Pe64Ensemble();
-}
-
-TEST_F(EnsembleTest, DISABLED_Elf32) {
- Elf32Ensemble();
-}
diff --git a/courgette/patch_generator_x86_32.h b/courgette/patch_generator_x86_32.h
index 4a29a75..084bdc3 100644
--- a/courgette/patch_generator_x86_32.h
+++ b/courgette/patch_generator_x86_32.h
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// This is the transformation and adjustment for Windows X86 executables.
-// The same code can be used for Windows X64 executables.
#ifndef COURGETTE_WIN32_X86_GENERATOR_H_
#define COURGETTE_WIN32_X86_GENERATOR_H_
@@ -67,7 +66,7 @@ class PatchGeneratorX86_32 : public TransformationPatchGenerator {
old_element_->region().length(),
&old_program);
if (old_parse_status != C_OK) {
- LOG(ERROR) << "Cannot parse as WinPE " << old_element_->Name();
+ LOG(ERROR) << "Cannot parse as Win32X86PE " << old_element_->Name();
return old_parse_status;
}
@@ -78,7 +77,7 @@ class PatchGeneratorX86_32 : public TransformationPatchGenerator {
&new_program);
if (new_parse_status != C_OK) {
DeleteAssemblyProgram(old_program);
- LOG(ERROR) << "Cannot parse as WinPE " << new_element_->Name();
+ LOG(ERROR) << "Cannot parse as Win32X86PE " << new_element_->Name();
return new_parse_status;
}
diff --git a/courgette/patcher_x86_32.h b/courgette/patcher_x86_32.h
index 5625395..9488270 100644
--- a/courgette/patcher_x86_32.h
+++ b/courgette/patcher_x86_32.h
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// This is the transformation for Windows X86 executables.
-// The same patcher can be used for Windows X64 executables.
#ifndef COURGETTE_WIN32_X86_PATCHER_H_
#define COURGETTE_WIN32_X86_PATCHER_H_
@@ -13,7 +12,7 @@
namespace courgette {
// Courgette32X86Patcher is a TransformationPatcher for Windows 32-bit
-// and 64-bit executables. We can use the same patcher for both.
+// executables.
//
class PatcherX86_32 : public TransformationPatcher {
public:
diff --git a/courgette/testdata/chrome64-1-2.v1.patch b/courgette/testdata/chrome64-1-2.v1.patch
deleted file mode 100644
index e69de29..0000000
--- a/courgette/testdata/chrome64-1-2.v1.patch
+++ /dev/null
diff --git a/courgette/testdata/chrome64_1.exe b/courgette/testdata/chrome64_1.exe
deleted file mode 100755
index e69de29..0000000
--- a/courgette/testdata/chrome64_1.exe
+++ /dev/null
diff --git a/courgette/testdata/chrome64_2.exe b/courgette/testdata/chrome64_2.exe
deleted file mode 100755
index e69de29..0000000
--- a/courgette/testdata/chrome64_2.exe
+++ /dev/null
diff --git a/courgette/testdata/en-US-64.dll b/courgette/testdata/en-US-64.dll
deleted file mode 100755
index e69de29..0000000
--- a/courgette/testdata/en-US-64.dll
+++ /dev/null
diff --git a/courgette/types_elf.h b/courgette/types_elf.h
index eb054ee..f7fce71 100644
--- a/courgette/types_elf.h
+++ b/courgette/types_elf.h
@@ -10,11 +10,11 @@
// related to using them.
//
-typedef uint32 Elf32_Addr; // Unsigned program address
-typedef uint16 Elf32_Half; // Unsigned medium integer
-typedef uint32 Elf32_Off; // Unsigned file offset
-typedef int32 Elf32_Sword; // Signed large integer
-typedef uint32 Elf32_Word; // Unsigned large integer
+typedef uint32 Elf32_Addr; // Unsigned program address
+typedef uint16 Elf32_Half; // Unsigned medium integer
+typedef uint32 Elf32_Off; // Unsigned file offset
+typedef int32 Elf32_Sword; // Signed large integer
+typedef uint32 Elf32_Word; // Unsigned large integer
// The header at the top of the file
@@ -37,21 +37,21 @@ struct Elf32_Ehdr {
// values for header->e_type
enum e_type_values {
- ET_NONE = 0, // No file type
- ET_REL = 1, // Relocatable file
- ET_EXEC = 2, // Executable file
- ET_DYN = 3, // Shared object file
- ET_CORE = 4, // Core file
- ET_LOPROC = 0xff00, // Processor-specific
- ET_HIPROC = 0xfff // Processor-specific
+ ET_NONE = 0, // No file type
+ ET_REL = 1, // Relocatable file
+ ET_EXEC = 2, // Executable file
+ ET_DYN = 3, // Shared object file
+ ET_CORE = 4, // Core file
+ ET_LOPROC = 0xff00, // Processor-specific
+ ET_HIPROC = 0xfff // Processor-specific
};
// values for header->e_machine
enum e_machine_values {
- EM_NONE = 0, // No machine
- EM_386 = 3, // Intel Architecture
- EM_ARM = 40, // ARM Architecture
- EM_x86_64 = 62, // Intel x86-64 Architecture
+ EM_NONE = 0, // No machine
+ EM_386 = 3, // Intel Architecture
+ EM_ARM = 40, // ARM Architecture
+ EM_x86_64 = 62, // Intel x86-64 Architecture
// Other values skipped
};
diff --git a/courgette/versioning_unittest.cc b/courgette/versioning_unittest.cc
index 5313b8b..5332592 100644
--- a/courgette/versioning_unittest.cc
+++ b/courgette/versioning_unittest.cc
@@ -50,8 +50,6 @@ void VersioningTest::TestApplyingOldPatch(const char* src_file,
TEST_F(VersioningTest, All) {
TestApplyingOldPatch("setup1.exe", "setup1-setup2.v1.patch", "setup2.exe");
- TestApplyingOldPatch("chrome64_1.exe", "chrome64-1-2.v1.patch",
- "chrome64_2.exe");
// We also need a way to test that newly generated patches are appropriately
// applicable by older clients... not sure of the best way to do that.