From 83c3cb14a4a8629df75b509e926e3c06438391d1 Mon Sep 17 00:00:00 2001 From: "piman@chromium.org" Date: Mon, 23 Sep 2013 21:56:39 +0000 Subject: 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 --- courgette/assembly_program.cc | 2 +- courgette/courgette.gyp | 3 - courgette/courgette.h | 1 - courgette/courgette_tool.cc | 5 - courgette/disassembler.cc | 11 +- courgette/disassembler.h | 4 - courgette/disassembler_elf_32_arm.cc | 6 +- courgette/disassembler_elf_32_arm.h | 4 - courgette/disassembler_elf_32_x86.h | 4 - courgette/disassembler_win32_x64.cc | 732 --------------------------- courgette/disassembler_win32_x64.h | 160 ------ courgette/disassembler_win32_x64_unittest.cc | 98 ---- courgette/disassembler_win32_x86.cc | 6 +- courgette/disassembler_win32_x86.h | 4 - courgette/encode_decode_unittest.cc | 5 - courgette/encoded_program.cc | 40 +- courgette/encoded_program.h | 6 +- courgette/ensemble_apply.cc | 3 - courgette/ensemble_create.cc | 9 - courgette/ensemble_unittest.cc | 56 +- courgette/patch_generator_x86_32.h | 5 +- courgette/patcher_x86_32.h | 3 +- courgette/testdata/chrome64-1-2.v1.patch | 0 courgette/testdata/chrome64_1.exe | 0 courgette/testdata/chrome64_2.exe | 0 courgette/testdata/en-US-64.dll | 0 courgette/types_elf.h | 32 +- courgette/versioning_unittest.cc | 2 - 28 files changed, 53 insertions(+), 1148 deletions(-) delete mode 100644 courgette/disassembler_win32_x64.cc delete mode 100644 courgette/disassembler_win32_x64.h delete mode 100644 courgette/disassembler_win32_x64_unittest.cc delete mode 100644 courgette/testdata/chrome64-1-2.v1.patch delete mode 100755 courgette/testdata/chrome64_1.exe delete mode 100755 courgette/testdata/chrome64_2.exe delete mode 100755 courgette/testdata/en-US-64.dll (limited to 'courgette') 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 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 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 -#include -#include - -#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(optional_header + - size_of_optional_header_); - size_t detected_length = 0; - - for (int i = 0; i < number_of_sections_; ++i) { - const Section* section = §ions_[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 *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 = §ions_[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 ""; - 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::iterator abs32_iter = abs32_target_rvas_.begin(); - std::map::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::iterator abs32_pos = abs32_locations_.begin(); - - // Find the rel32 relocations. - const uint8* p = start_pointer; - while (p < end_pointer) { - RVA current_rva = static_cast(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(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::iterator rel32_pos = rel32_locations_.begin(); - std::vector::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(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& map) { - int total = 0; - std::map > h; - for (std::map::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 >::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 = §ions_[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 = §ions_[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(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 -#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 *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& 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 abs32_locations_; - std::vector 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 abs32_target_rvas_; - std::map 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 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 relocs; - bool can_parse_relocs = disassembler->ParseRelocs(&relocs); - EXPECT_TRUE(can_parse_relocs); - - const uint8* offset_p = disassembler->OffsetToPointer(0); - EXPECT_EQ(reinterpret_cast(file1.c_str()), - reinterpret_cast(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(file1.c_str()), - reinterpret_cast(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 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 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 -#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(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 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 src_ensemble; - std::list 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 src_ensemble; std::list 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 src_ensemble; - std::list 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 diff --git a/courgette/testdata/chrome64_1.exe b/courgette/testdata/chrome64_1.exe deleted file mode 100755 index e69de29..0000000 diff --git a/courgette/testdata/chrome64_2.exe b/courgette/testdata/chrome64_2.exe deleted file mode 100755 index e69de29..0000000 diff --git a/courgette/testdata/en-US-64.dll b/courgette/testdata/en-US-64.dll deleted file mode 100755 index e69de29..0000000 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. -- cgit v1.1