diff options
-rw-r--r-- | courgette/assembly_program.cc | 32 | ||||
-rw-r--r-- | courgette/assembly_program.h | 5 | ||||
-rw-r--r-- | courgette/bsdiff_memory_unittest.cc | 6 | ||||
-rw-r--r-- | courgette/courgette.gyp | 5 | ||||
-rw-r--r-- | courgette/courgette.h | 1 | ||||
-rw-r--r-- | courgette/disassembler.cc | 9 | ||||
-rw-r--r-- | courgette/disassembler.h | 2 | ||||
-rw-r--r-- | courgette/disassembler_elf_32_x86.cc | 602 | ||||
-rw-r--r-- | courgette/disassembler_elf_32_x86.h | 143 | ||||
-rw-r--r-- | courgette/disassembler_elf_32_x86_unittest.cc | 71 | ||||
-rw-r--r-- | courgette/disassembler_win32_x86.cc | 2 | ||||
-rw-r--r-- | courgette/encode_decode_unittest.cc | 29 | ||||
-rw-r--r-- | courgette/encoded_program.cc | 67 | ||||
-rw-r--r-- | courgette/encoded_program.h | 26 | ||||
-rw-r--r-- | courgette/encoded_program_fuzz_unittest.cc | 3 | ||||
-rw-r--r-- | courgette/ensemble_apply.cc | 3 | ||||
-rw-r--r-- | courgette/ensemble_create.cc | 9 | ||||
-rw-r--r-- | courgette/patch_generator_x86_32.h | 6 | ||||
-rw-r--r-- | courgette/types_elf.h | 141 |
19 files changed, 51 insertions, 1111 deletions
diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc index 9225578..f759e16 100644 --- a/courgette/assembly_program.cc +++ b/courgette/assembly_program.cc @@ -22,8 +22,7 @@ namespace courgette { // Opcodes of simple assembly language enum OP { ORIGIN, // ORIGIN <rva> - set current address for assembly. - MAKEPERELOCS, // Generates a base relocation table. - MAKEELFRELOCS, // Generates a base relocation table. + MAKERELOCS, // Generates a base relocation table. DEFBYTE, // DEFBYTE <value> - emit a byte literal. REL32, // REL32 <label> - emit a rel32 encoded reference to 'label'. ABS32, // REL32 <label> - emit am abs32 encoded reference to 'label'. @@ -59,16 +58,10 @@ class OriginInstruction : public Instruction { RVA rva_; }; -// Emits an entire PE base relocation table. -class PeRelocsInstruction : public Instruction { +// Emits an entire base relocation table. +class MakeRelocsInstruction : public Instruction { public: - PeRelocsInstruction() : Instruction(MAKEPERELOCS) {} -}; - -// Emits an ELF relocation table. -class ElfRelocsInstruction : public Instruction { - public: - ElfRelocsInstruction() : Instruction(MAKEELFRELOCS) {} + MakeRelocsInstruction() : Instruction(MAKERELOCS) {} }; // Emits a single byte. @@ -115,12 +108,8 @@ AssemblyProgram::~AssemblyProgram() { DeleteContainedLabels(abs32_labels_); } -CheckBool AssemblyProgram::EmitPeRelocsInstruction() { - return Emit(new(std::nothrow) PeRelocsInstruction()); -} - -CheckBool AssemblyProgram::EmitElfRelocationInstruction() { - return Emit(new(std::nothrow) ElfRelocsInstruction()); +CheckBool AssemblyProgram::EmitMakeRelocsInstruction() { + return Emit(new(std::nothrow) MakeRelocsInstruction()); } CheckBool AssemblyProgram::EmitOriginInstruction(RVA rva) { @@ -368,13 +357,8 @@ EncodedProgram* AssemblyProgram::Encode() const { return NULL; break; } - case MAKEPERELOCS: { - if (!encoded->AddPeMakeRelocs()) - return NULL; - break; - } - case MAKEELFRELOCS: { - if (!encoded->AddElfMakeRelocs()) + case MAKERELOCS: { + if (!encoded->AddMakeRelocs()) return NULL; break; } diff --git a/courgette/assembly_program.h b/courgette/assembly_program.h index 3d231c2..5c6b1b1 100644 --- a/courgette/assembly_program.h +++ b/courgette/assembly_program.h @@ -69,10 +69,7 @@ class AssemblyProgram { // Instructions will be assembled in the order they are emitted. // Generates an entire base relocation table. - CheckBool EmitPeRelocsInstruction() WARN_UNUSED_RESULT; - - // Generates an ELF style relocation table. - CheckBool EmitElfRelocationInstruction() WARN_UNUSED_RESULT; + CheckBool EmitMakeRelocsInstruction() WARN_UNUSED_RESULT; // Following instruction will be assembled at address 'rva'. CheckBool EmitOriginInstruction(RVA rva) WARN_UNUSED_RESULT; diff --git a/courgette/bsdiff_memory_unittest.cc b/courgette/bsdiff_memory_unittest.cc index f1718e2..ce80eb7 100644 --- a/courgette/bsdiff_memory_unittest.cc +++ b/courgette/bsdiff_memory_unittest.cc @@ -117,9 +117,3 @@ TEST_F(BSDiffMemoryTest, TestDifferentExes) { std::string file2 = FileContents("setup2.exe"); GenerateAndTestPatch(file1, file2); } - -TEST_F(BSDiffMemoryTest, TestDifferentElfs) { - std::string file1 = FileContents("elf-32-1"); - std::string file2 = FileContents("elf-32-2"); - GenerateAndTestPatch(file1, file2); -} diff --git a/courgette/courgette.gyp b/courgette/courgette.gyp index 31276ae..6233d77 100644 --- a/courgette/courgette.gyp +++ b/courgette/courgette.gyp @@ -22,8 +22,6 @@ 'difference_estimator.h', 'disassembler.cc', 'disassembler.h', - 'disassembler_elf_32_x86.cc', - 'disassembler_elf_32_x86.h', 'disassembler_win32_x86.cc', 'disassembler_win32_x86.h', 'encoded_program.cc', @@ -39,8 +37,6 @@ 'simple_delta.h', 'streams.cc', 'streams.h', - 'types_elf.h', - 'types_win_pe.h', 'patch_generator_x86_32.h', 'patcher_x86_32.h', ], @@ -93,7 +89,6 @@ 'base_test_unittest.cc', 'base_test_unittest.h', 'difference_estimator_unittest.cc', - 'disassembler_elf_32_x86_unittest.cc', 'disassembler_win32_x86_unittest.cc', 'encoded_program_unittest.cc', 'encode_decode_unittest.cc', diff --git a/courgette/courgette.h b/courgette/courgette.h index a58f16d..20a25ea 100644 --- a/courgette/courgette.h +++ b/courgette/courgette.h @@ -55,7 +55,6 @@ enum Status { enum ExecutableType { EXE_UNKNOWN = 0, EXE_WIN_32_X86 = 1, - EXE_ELF_32_X86 = 2, }; class SinkStream; diff --git a/courgette/disassembler.cc b/courgette/disassembler.cc index 103bbe0..5514be9 100644 --- a/courgette/disassembler.cc +++ b/courgette/disassembler.cc @@ -13,7 +13,6 @@ #include "courgette/assembly_program.h" #include "courgette/courgette.h" -#include "courgette/disassembler_elf_32_x86.h" #include "courgette/disassembler_win32_x86.h" #include "courgette/encoded_program.h" @@ -31,14 +30,8 @@ Disassembler* DetectDisassembler(const void* buffer, size_t length) { disassembler = new DisassemblerWin32X86(buffer, length); if (disassembler->ParseHeader()) return disassembler; - else - delete disassembler; - disassembler = new DisassemblerElf32X86(buffer, length); - if (disassembler->ParseHeader()) - return disassembler; - else - delete disassembler; + delete disassembler; return NULL; } diff --git a/courgette/disassembler.h b/courgette/disassembler.h index 2de67fd..85c0c3d 100644 --- a/courgette/disassembler.h +++ b/courgette/disassembler.h @@ -68,7 +68,7 @@ class Disassembler { } // Reduce the length of the image in memory. Does not actually free - // (or realloc) any memory. Usually only called via ParseHeader() + // (or realloc) any memory. Unusally only called via ParseHeader() void ReduceLength(size_t reduced_length); private: diff --git a/courgette/disassembler_elf_32_x86.cc b/courgette/disassembler_elf_32_x86.cc deleted file mode 100644 index 5f3ba95..0000000 --- a/courgette/disassembler_elf_32_x86.cc +++ /dev/null @@ -1,602 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "courgette/disassembler_elf_32_x86.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 { - -DisassemblerElf32X86::DisassemblerElf32X86(const void* start, size_t length) - : Disassembler(start, length) { -} - -bool DisassemblerElf32X86::ParseHeader() { - if (length() < sizeof(Elf32_Ehdr)) - return Bad("Too small"); - - header_ = (Elf32_Ehdr *)start(); - - // Have magic for elf header? - if (header_->e_ident[0] != 0x7f || - header_->e_ident[1] != 'E' || - header_->e_ident[2] != 'L' || - header_->e_ident[3] != 'F') - return Bad("No Magic Number"); - - if (header_->e_type != ET_EXEC && - header_->e_type != ET_DYN) - return Bad("Not an executable file or shared library"); - - if (header_->e_machine != EM_386) - return Bad("Not a supported architecture"); - - if (header_->e_version != 1) - return Bad("Unknown file version"); - - if (header_->e_shentsize != sizeof(Elf32_Shdr)) - return Bad("Unexpected section header size"); - - if (header_->e_shoff >= length()) - return Bad("Out of bounds section header table offset"); - - section_header_table_ = (Elf32_Shdr *)OffsetToPointer(header_->e_shoff); - section_header_table_size_ = header_->e_shnum; - - if ((header_->e_shoff + header_->e_shnum ) >= length()) - return Bad("Out of bounds section header table"); - - if (header_->e_phoff >= length()) - return Bad("Out of bounds program header table offset"); - - program_header_table_ = (Elf32_Phdr *)OffsetToPointer(header_->e_phoff); - program_header_table_size_ = header_->e_phnum; - - if ((header_->e_phoff + header_->e_phnum) >= length()) - return Bad("Out of bounds program header table"); - - default_string_section_ = (const char *)SectionBody((int)header_->e_shstrndx); - - ReduceLength(DiscoverLength()); - - return Good(); -} - -bool DisassemblerElf32X86::Disassemble(AssemblyProgram* target) { - if (!ok()) - return false; - - // The Image Base is always 0 for ELF Executables - target->set_image_base(0); - - if (!ParseAbs32Relocs()) - return false; - - if (!ParseRel32RelocsFromSections()) - return false; - - if (!ParseFile(target)) - return false; - - target->DefaultAssignIndexes(); - - return true; -} - -uint32 DisassemblerElf32X86::DiscoverLength() { - uint32 result = 0; - - // Find the end of the last section - for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { - const Elf32_Shdr *section_header = SectionHeader(section_id); - - if (section_header->sh_type == SHT_NOBITS) - continue; - - uint32 section_end = section_header->sh_offset + section_header->sh_size; - - if (section_end > result) - result = section_end; - } - - // Find the end of the last segment - for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { - const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); - - uint32 segment_end = segment_header->p_offset + segment_header->p_filesz; - - if (segment_end > result) - result = segment_end; - } - - uint32 section_table_end = header_->e_shoff + - (header_->e_shnum * sizeof(Elf32_Shdr)); - if (section_table_end > result) - result = section_table_end; - - uint32 segment_table_end = header_->e_phoff + - (header_->e_phnum * sizeof(Elf32_Phdr)); - if (segment_table_end > result) - result = segment_table_end; - - return result; -} - -CheckBool DisassemblerElf32X86::IsValidRVA(RVA rva) const { - - // It's valid if it's contained in any program segment - for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { - const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); - - if (segment_header->p_type != PT_LOAD) - continue; - - Elf32_Addr begin = segment_header->p_vaddr; - Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz; - - if (rva >= begin && rva < end) - return true; - } - - return false; -} - -// Convert an ELF relocation struction into an RVA -CheckBool DisassemblerElf32X86::RelToRVA(Elf32_Rel rel, RVA* result) const { - - // The rightmost byte of r_info is the type... - elf32_rel_386_type_values type = - (elf32_rel_386_type_values)(unsigned char)rel.r_info; - - // The other 3 bytes of r_info are the symbol - uint32 symbol = rel.r_info >> 8; - - switch(type) - { - case R_386_NONE: - case R_386_32: - case R_386_PC32: - case R_386_GOT32: - case R_386_PLT32: - case R_386_COPY: - case R_386_GLOB_DAT: - case R_386_JMP_SLOT: - return false; - - case R_386_RELATIVE: - if (symbol != 0) - return false; - - // This is a basic ABS32 relocation address - *result = rel.r_offset; - return true; - - case R_386_GOTOFF: - case R_386_GOTPC: - case R_386_TLS_TPOFF: - return false; - } - - return false; -} - -// Returns RVA for an in memory address, or NULL. -CheckBool DisassemblerElf32X86::RVAToFileOffset(Elf32_Addr addr, - size_t* result) const { - - for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { - Elf32_Addr begin = ProgramSegmentMemoryBegin(i); - Elf32_Addr end = begin + ProgramSegmentMemorySize(i); - - if (addr >= begin && addr < end) { - Elf32_Addr offset = addr - begin; - - if (offset < ProgramSegmentFileSize(i)) { - *result = ProgramSegmentFileOffset(i) + offset; - return true; - } - } - } - - return false; -} - -RVA DisassemblerElf32X86::FileOffsetToRVA(size_t offset) const { - // File offsets can be 64 bit values, but we are dealing with 32 - // bit executables and so only need to support 32bit file sizes. - uint32 offset32 = (uint32)offset; - - for (int i = 0; i < SectionHeaderCount(); i++) { - - const Elf32_Shdr *section_header = SectionHeader(i); - - // These can appear to have a size in the file, but don't. - if (section_header->sh_type == SHT_NOBITS) - continue; - - Elf32_Off section_begin = section_header->sh_offset; - Elf32_Off section_end = section_begin + section_header->sh_size; - - if (offset32 >= section_begin && offset32 < section_end) { - return section_header->sh_addr + (offset32 - section_begin); - } - } - - return 0; -} - -CheckBool DisassemblerElf32X86::RVAsToOffsets(std::vector<RVA>* rvas, - std::vector<size_t>* offsets) { - offsets->clear(); - - for (std::vector<RVA>::iterator rva = rvas->begin(); - rva != rvas->end(); - rva++) { - - size_t offset; - - if (!RVAToFileOffset(*rva, &offset)) - return false; - - offsets->push_back(offset); - } - - return true; -} - -CheckBool DisassemblerElf32X86::ParseFile(AssemblyProgram* program) { - bool ok = true; - - // Walk all the bytes in the file, whether or not in a section. - uint32 file_offset = 0; - - std::vector<size_t> abs_offsets; - std::vector<size_t> rel_offsets; - - if (ok) - ok = RVAsToOffsets(&abs32_locations_, &abs_offsets); - - if (ok) - ok = RVAsToOffsets(&rel32_locations_, &rel_offsets); - - std::vector<size_t>::iterator current_abs_offset = abs_offsets.begin(); - std::vector<size_t>::iterator current_rel_offset = rel_offsets.begin(); - - std::vector<size_t>::iterator end_abs_offset = abs_offsets.end(); - std::vector<size_t>::iterator end_rel_offset = rel_offsets.end(); - - for (int section_id = 0; - ok && (section_id < SectionHeaderCount()); - section_id++) { - - const Elf32_Shdr *section_header = SectionHeader(section_id); - - if (ok) { - ok = ParseSimpleRegion(file_offset, - section_header->sh_offset, - program); - file_offset = section_header->sh_offset; - } - - switch (section_header->sh_type) { - case SHT_REL: - if (ok) { - ok = ParseRelocationSection(section_header, program); - file_offset = section_header->sh_offset + section_header->sh_size; - } - break; - case SHT_PROGBITS: - if (ok) { - ok = ParseProgbitsSection(section_header, - ¤t_abs_offset, end_abs_offset, - ¤t_rel_offset, end_rel_offset, - program); - file_offset = section_header->sh_offset + section_header->sh_size; - } - - break; - default: - break; - } - } - - // Rest of the file past the last section - if (ok) { - ok = ParseSimpleRegion(file_offset, - length(), - program); - } - - // Make certain we consume all of the relocations as expected - ok = ok && (current_abs_offset == end_abs_offset); - - return ok; -} - -CheckBool DisassemblerElf32X86::ParseRelocationSection( - const Elf32_Shdr *section_header, - AssemblyProgram* program) { - // We can reproduce the R_386_RELATIVE entries in one of the relocation - // table based on other information in the patch, given these - // conditions.... - // - // All R_386_RELATIVE entries are: - // 1) In the same relocation table - // 2) Are consecutive - // 3) Are sorted in memory address order - // - // Happily, this is normally the case, but it's not required by spec - // so we check, and just don't do it if we don't match up. - - // The expectation is that one relocation section will contain - // all of our R_386_RELATIVE entries in the expected order followed - // by assorted other entries we can't use special handling for. - - bool ok = true; - bool match = true; - - // Walk all the bytes in the section, matching relocation table or not - size_t file_offset = section_header->sh_offset; - size_t section_end = section_header->sh_offset + section_header->sh_size; - - Elf32_Rel *section_relocs_iter = - (Elf32_Rel *)OffsetToPointer(section_header->sh_offset); - - uint32 section_relocs_count = section_header->sh_size / - section_header->sh_entsize; - - if (abs32_locations_.size() > section_relocs_count) - match = false; - - std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); - - while (match && (reloc_iter != abs32_locations_.end())) { - if (section_relocs_iter->r_info != R_386_RELATIVE || - section_relocs_iter->r_offset != *reloc_iter) - match = false; - section_relocs_iter++; - reloc_iter++; - } - - if (match) { - // Skip over relocation tables - ok = program->EmitElfRelocationInstruction(); - file_offset += sizeof(Elf32_Rel) * abs32_locations_.size(); - } - - if (ok) { - ok = ParseSimpleRegion(file_offset, section_end, program); - } - - return ok; -} - -CheckBool DisassemblerElf32X86::ParseProgbitsSection( - const Elf32_Shdr *section_header, - std::vector<size_t>::iterator* current_abs_offset, - std::vector<size_t>::iterator end_abs_offset, - std::vector<size_t>::iterator* current_rel_offset, - std::vector<size_t>::iterator end_rel_offset, - AssemblyProgram* program) { - - bool ok = true; - - // Walk all the bytes in the file, whether or not in a section. - size_t file_offset = section_header->sh_offset; - size_t section_end = section_header->sh_offset + section_header->sh_size; - - Elf32_Addr origin = section_header->sh_addr; - size_t origin_offset = section_header->sh_offset; - ok = program->EmitOriginInstruction(origin); - - while (ok && file_offset < section_end) { - - if (*current_abs_offset != end_abs_offset && - file_offset > **current_abs_offset) { - ok = false; - } - - while (*current_rel_offset != end_rel_offset && - file_offset > **current_rel_offset) { - (*current_rel_offset)++; - } - - size_t next_relocation = section_end; - - if (*current_abs_offset != end_abs_offset && - next_relocation > **current_abs_offset) - next_relocation = **current_abs_offset; - - // Rel offsets are heuristically derived, and might (incorrectly) overlap - // an Abs value, or the end of the section, so +3 to make sure there is - // room for the full 4 byte value. - if (*current_rel_offset != end_rel_offset && - next_relocation > (**current_rel_offset + 3)) - next_relocation = **current_rel_offset; - - if (ok && (next_relocation > file_offset)) { - ok = ParseSimpleRegion(file_offset, next_relocation, program); - - file_offset = next_relocation; - continue; - } - - if (ok && - *current_abs_offset != end_abs_offset && - file_offset == **current_abs_offset) { - - const uint8* p = OffsetToPointer(file_offset); - RVA target_rva = Read32LittleEndian(p); - - ok = program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)); - file_offset += sizeof(RVA); - (*current_abs_offset)++; - continue; - } - - if (ok && - *current_rel_offset != end_rel_offset && - file_offset == **current_rel_offset) { - - const uint8* p = OffsetToPointer(file_offset); - uint32 relative_target = Read32LittleEndian(p); - // This cast is for 64 bit systems, and is only safe because we - // are working on 32 bit executables. - RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + - 4 + relative_target); - - ok = program->EmitRel32(program->FindOrMakeRel32Label(target_rva)); - file_offset += sizeof(RVA); - (*current_rel_offset)++; - continue; - } - } - - // Rest of the section (if any) - if (ok) { - ok = ParseSimpleRegion(file_offset, section_end, program); - } - - return ok; -} - -CheckBool DisassemblerElf32X86::ParseSimpleRegion( - size_t start_file_offset, - size_t end_file_offset, - AssemblyProgram* program) { - - const uint8* start = OffsetToPointer(start_file_offset); - const uint8* end = OffsetToPointer(end_file_offset); - - const uint8* p = start; - - bool ok = true; - while (p < end && ok) { - ok = program->EmitByteInstruction(*p); - ++p; - } - - return ok; -} - -CheckBool DisassemblerElf32X86::ParseAbs32Relocs() { - abs32_locations_.clear(); - - // Loop through sections for relocation sections - for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { - const Elf32_Shdr *section_header = SectionHeader(section_id); - - if (section_header->sh_type == SHT_REL) { - - Elf32_Rel *relocs_table = (Elf32_Rel *)SectionBody(section_id); - - int relocs_table_count = section_header->sh_size / - section_header->sh_entsize; - - // Elf32_Word relocation_section_id = section_header->sh_info; - - // Loop through relocation objects in the relocation section - for (int rel_id = 0; rel_id < relocs_table_count; rel_id++) { - RVA rva; - - // Quite a few of these conversions fail, and we simply skip - // them, that's okay. - if (RelToRVA(relocs_table[rel_id], &rva)) - abs32_locations_.push_back(rva); - } - } - } - - std::sort(abs32_locations_.begin(), abs32_locations_.end()); - return true; -} - -CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSections() { - - rel32_locations_.clear(); - - // Loop through sections for relocation sections - for (int section_id = 0; - section_id < SectionHeaderCount(); - section_id++) { - - const Elf32_Shdr *section_header = SectionHeader(section_id); - - if (section_header->sh_type != SHT_PROGBITS) - continue; - - if (!ParseRel32RelocsFromSection(section_header)) - return false; - } - - std::sort(rel32_locations_.begin(), rel32_locations_.end()); - return true; -} - -CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSection( - const Elf32_Shdr* section_header) { - - uint32 start_file_offset = section_header->sh_offset; - uint32 end_file_offset = start_file_offset + section_header->sh_size; - - const uint8* start_pointer = OffsetToPointer(start_file_offset); - const uint8* end_pointer = OffsetToPointer(end_file_offset); - - // 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 - - section_header->sh_addr; - - // Find the rel32 relocations. - const uint8* p = start_pointer; - while (p < end_pointer) { - //RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); - - // 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); - - 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)) { - rel32_locations_.push_back(rel32_rva); -#if COURGETTE_HISTOGRAM_TARGETS - ++rel32_target_rvas_[target_rva]; -#endif - p += 4; - continue; - } - } - p += 1; - } - - return true; -} - -} // namespace courgette diff --git a/courgette/disassembler_elf_32_x86.h b/courgette/disassembler_elf_32_x86.h deleted file mode 100644 index c797a8b..0000000 --- a/courgette/disassembler_elf_32_x86.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COURGETTE_DISASSEMBLER_ELF_32_X86_H_ -#define COURGETTE_DISASSEMBLER_ELF_32_X86_H_ - -#include "base/basictypes.h" -#include "courgette/disassembler.h" -#include "courgette/memory_allocator.h" -#include "courgette/types_elf.h" - -namespace courgette { - -class AssemblyProgram; - -class DisassemblerElf32X86 : public Disassembler { - public: - explicit DisassemblerElf32X86(const void* start, size_t length); - - virtual ExecutableType kind() { return EXE_ELF_32_X86; } - - // Returns 'true' if the buffer appears to point to a valid ELF executable - // for X86 32 bitWindows 32 bit. If ParseHeader() succeeds, other member - // functions may be called. - virtual bool ParseHeader(); - - virtual bool Disassemble(AssemblyProgram* target); - - // Public for unittests only - std::vector<RVA> &Abs32Locations() { return abs32_locations_; } - std::vector<RVA> &Rel32Locations() { return rel32_locations_; } - - protected: - - uint32 DiscoverLength(); - - // Misc Section Helpers - - const Elf32_Half SectionHeaderCount() const { - return section_header_table_size_; - } - - const Elf32_Shdr *SectionHeader(int id) const { - assert(id >= 0 && id < SectionHeaderCount()); - return section_header_table_ + id; - } - - const uint8 *SectionBody(int id) const { - return OffsetToPointer(SectionHeader(id)->sh_offset); - } - - const Elf32_Word SectionBodySize(int id) const { - return SectionHeader(id)->sh_size; - } - - // Misc Segment Helpers - - const Elf32_Half ProgramSegmentHeaderCount() const { - return program_header_table_size_; - } - - const Elf32_Phdr *ProgramSegmentHeader(int id) const { - assert(id >= 0 && id < ProgramSegmentHeaderCount()); - return program_header_table_ + id; - } - - // The virtual memory address at which this program segment will be loaded - const Elf32_Addr ProgramSegmentMemoryBegin(int id) const { - return ProgramSegmentHeader(id)->p_vaddr; - } - - // The number of virtual memory bytes for this program segment - const Elf32_Word ProgramSegmentMemorySize(int id) const { - return ProgramSegmentHeader(id)->p_memsz; - } - - // Pointer into the source file for this program segment - const Elf32_Addr ProgramSegmentFileOffset(int id) const { - return ProgramSegmentHeader(id)->p_offset; - } - - // Number of file bytes for this program segment. Is <= ProgramMemorySize. - const Elf32_Word ProgramSegmentFileSize(int id) const { - return ProgramSegmentHeader(id)->p_filesz; - } - - // Misc address space helpers - - CheckBool IsValidRVA(RVA rva) const WARN_UNUSED_RESULT; - - // Convert an ELF relocation struction into an RVA - CheckBool RelToRVA(Elf32_Rel rel, RVA* result) const WARN_UNUSED_RESULT; - - // Returns kNoOffset if there is no file offset corresponding to 'rva'. - CheckBool RVAToFileOffset(RVA rva, size_t* result) const WARN_UNUSED_RESULT; - - RVA FileOffsetToRVA(size_t offset) const WARN_UNUSED_RESULT; - - CheckBool RVAsToOffsets(std::vector<RVA>* rvas /*in*/, - std::vector<size_t>* offsets /*out*/); - - // Parsing Code used to really implement Disassemble - - CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT; - CheckBool ParseRelocationSection( - const Elf32_Shdr *section_header, - AssemblyProgram* program) WARN_UNUSED_RESULT; - CheckBool ParseProgbitsSection( - const Elf32_Shdr *section_header, - std::vector<size_t>::iterator* current_abs_offset, - std::vector<size_t>::iterator end_abs_offset, - std::vector<size_t>::iterator* current_rel_offset, - std::vector<size_t>::iterator end_rel_offset, - AssemblyProgram* program) WARN_UNUSED_RESULT; - CheckBool ParseSimpleRegion(size_t start_file_offset, - size_t end_file_offset, - AssemblyProgram* program) WARN_UNUSED_RESULT; - - CheckBool ParseAbs32Relocs() WARN_UNUSED_RESULT; - CheckBool ParseRel32RelocsFromSections() WARN_UNUSED_RESULT; - CheckBool ParseRel32RelocsFromSection( - const Elf32_Shdr* section) WARN_UNUSED_RESULT; - - Elf32_Ehdr *header_; - Elf32_Shdr *section_header_table_; - Elf32_Half section_header_table_size_; - - Elf32_Phdr *program_header_table_; - Elf32_Half program_header_table_size_; - - // Section header for default - const char *default_string_section_; - - std::vector<RVA> abs32_locations_; - std::vector<RVA> rel32_locations_; - - DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32X86); -}; - -} // namespace courgette - -#endif // COURGETTE_DISASSEMBLER_ELF_32_X86_H_ diff --git a/courgette/disassembler_elf_32_x86_unittest.cc b/courgette/disassembler_elf_32_x86_unittest.cc deleted file mode 100644 index 85c8e26..0000000 --- a/courgette/disassembler_elf_32_x86_unittest.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2011 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/assembly_program.h" -#include "courgette/base_test_unittest.h" -#include "courgette/disassembler_elf_32_x86.h" - -class DisassemblerElf32X86Test : public BaseTest { - public: - - void TestExe(const char* file_name, - size_t expected_abs_count, - size_t expected_rel_count) const; -}; - -void DisassemblerElf32X86Test::TestExe(const char* file_name, - size_t expected_abs_count, - size_t expected_rel_count) const { - std::string file1 = FileContents(file_name); - - scoped_ptr<courgette::DisassemblerElf32X86> disassembler( - new courgette::DisassemblerElf32X86(file1.c_str(), file1.length())); - - bool can_parse_header = disassembler->ParseHeader(); - EXPECT_TRUE(can_parse_header); - EXPECT_TRUE(disassembler->ok()); - - // The length of the disassembled value will be slightly smaller than the - // real file, since trailing debug info is not included - EXPECT_EQ(file1.length(), disassembler->length()); - - const uint8* offset_p = disassembler->OffsetToPointer(0); - EXPECT_EQ(reinterpret_cast<const void*>(file1.c_str()), - reinterpret_cast<const void*>(offset_p)); - EXPECT_EQ(0x7F, offset_p[0]); - EXPECT_EQ('E', offset_p[1]); - EXPECT_EQ('L', offset_p[2]); - EXPECT_EQ('F', offset_p[3]); - - courgette::AssemblyProgram* program = new courgette::AssemblyProgram(); - - EXPECT_TRUE(disassembler->Disassemble(program)); - - EXPECT_EQ(disassembler->Abs32Locations().size(), expected_abs_count); - EXPECT_EQ(disassembler->Rel32Locations().size(), expected_rel_count); - - // Prove that none of the rel32 RVAs overlap with abs32 RVAs - std::set<courgette::RVA> abs(disassembler->Abs32Locations().begin(), - disassembler->Abs32Locations().end()); - std::set<courgette::RVA> rel(disassembler->Rel32Locations().begin(), - disassembler->Rel32Locations().end()); - for (std::vector<courgette::RVA>::iterator rel32 = - disassembler->Rel32Locations().begin(); - rel32 != disassembler->Rel32Locations().end(); - rel32++) { - EXPECT_TRUE(abs.find(*rel32) == abs.end()); - } - - for (std::vector<courgette::RVA>::iterator abs32 = - disassembler->Abs32Locations().begin(); - abs32 != disassembler->Abs32Locations().end(); - abs32++) { - EXPECT_TRUE(rel.find(*abs32) == rel.end()); - } - delete program; -} - -TEST_F(DisassemblerElf32X86Test, All) { - TestExe("elf-32-1", 200, 3441); -} diff --git a/courgette/disassembler_win32_x86.cc b/courgette/disassembler_win32_x86.cc index 39cb695..d09d67d 100644 --- a/courgette/disassembler_win32_x86.cc +++ b/courgette/disassembler_win32_x86.cc @@ -562,7 +562,7 @@ CheckBool DisassemblerWin32X86::ParseFileRegion( // actually be anywhere. Make sure we skip it because we will regenerate it // during assembly. if (current_rva == relocs_start_rva) { - ok = program->EmitPeRelocsInstruction(); + ok = program->EmitMakeRelocsInstruction(); if (!ok) break; uint32 relocs_size = base_relocation_table().size_; diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc index 20f0e16..90f5cd6 100644 --- a/courgette/encode_decode_unittest.cc +++ b/courgette/encode_decode_unittest.cc @@ -8,20 +8,20 @@ class EncodeDecodeTest : public BaseTest { public: - void TestAssembleToStreamDisassemble(std::string file, - size_t expected_encoded_lenth) const; + void TestExe(const char *) const; }; -void EncodeDecodeTest::TestAssembleToStreamDisassemble( - std::string file, - size_t expected_encoded_lenth) const { - const void* original_buffer = file.c_str(); - size_t original_length = file.length(); +void EncodeDecodeTest::TestExe(const char* file_name) const { + // Test top-level Courgette API for converting an a file to a binary + // assembly representation and back. + std::string file1 = FileContents(file_name); + + const void* original_buffer = file1.c_str(); + size_t original_length = file1.size(); courgette::AssemblyProgram* program = NULL; const courgette::Status parse_status = - courgette::ParseDetectedExecutable(original_buffer, - original_length, + courgette::ParseDetectedExecutable(original_buffer, original_length, &program); EXPECT_EQ(courgette::C_OK, parse_status); @@ -45,7 +45,7 @@ void EncodeDecodeTest::TestAssembleToStreamDisassemble( const void* buffer = sink.Buffer(); size_t length = sink.Length(); - EXPECT_EQ(expected_encoded_lenth, length); + EXPECT_EQ(971850U, length); courgette::SourceStreamSet sources; bool can_get_source_streams = sources.Init(buffer, length); @@ -68,12 +68,7 @@ void EncodeDecodeTest::TestAssembleToStreamDisassemble( DeleteEncodedProgram(encoded2); } -TEST_F(EncodeDecodeTest, PE) { - std::string file = FileContents("setup1.exe"); - TestAssembleToStreamDisassemble(file, 971850); -} -TEST_F(EncodeDecodeTest, Elf_Small) { - std::string file = FileContents("elf-32-1"); - TestAssembleToStreamDisassemble(file, 135988); +TEST_F(EncodeDecodeTest, All) { + TestExe("setup1.exe"); } diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc index b5e7310..a675dc2 100644 --- a/courgette/encoded_program.cc +++ b/courgette/encoded_program.cc @@ -16,7 +16,6 @@ #include "base/utf_string_conversions.h" #include "courgette/courgette.h" #include "courgette/streams.h" -#include "courgette/types_elf.h" namespace courgette { @@ -242,12 +241,8 @@ CheckBool EncodedProgram::AddRel32(int label_index) { return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); } -CheckBool EncodedProgram::AddPeMakeRelocs() { - return ops_.push_back(MAKE_PE_RELOCATION_TABLE); -} - -CheckBool EncodedProgram::AddElfMakeRelocs() { - return ops_.push_back(MAKE_ELF_RELOCATION_TABLE); +CheckBool EncodedProgram::AddMakeRelocs() { + return ops_.push_back(MAKE_BASE_RELOCATION_TABLE); } void EncodedProgram::DebuggingSummary() { @@ -404,9 +399,8 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { RVA current_rva = 0; - bool pending_pe_relocation_table = false; - bool pending_elf_relocation_table = false; - SinkStream bytes_following_relocation_table; + bool pending_base_relocation_table = false; + SinkStream bytes_following_base_relocation_table; SinkStream* output = final_buffer; @@ -484,16 +478,16 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { break; } - case MAKE_PE_RELOCATION_TABLE: { + case MAKE_BASE_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_pe_relocation_table) // Can't have two base relocation + if (pending_base_relocation_table) // Can't have two base relocation // tables. return false; - pending_pe_relocation_table = true; - output = &bytes_following_relocation_table; + pending_base_relocation_table = true; + output = &bytes_following_base_relocation_table; break; // There is a potential problem *if* the instruction stream contains // some REL32 relocations following the base relocation and in the same @@ -504,31 +498,12 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { // executable except some padding zero bytes. We could fix this by // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE. } - - case MAKE_ELF_RELOCATION_TABLE: { - // We can see the base relocation anywhere, but we only have the - // information to generate it at the very end. So we divert the bytes - // we are generating to a temporary stream. - if (pending_elf_relocation_table) // Can't have two relocation - // tables. - return false; - - pending_elf_relocation_table = true; - output = &bytes_following_relocation_table; - break; - } } } - if (pending_pe_relocation_table) { - if (!GeneratePeRelocations(final_buffer) || - !final_buffer->Append(&bytes_following_relocation_table)) - return false; - } - - if (pending_elf_relocation_table) { - if (!GenerateElfRelocations(final_buffer) || - !final_buffer->Append(&bytes_following_relocation_table)) + if (pending_base_relocation_table) { + if (!GenerateBaseRelocations(final_buffer) || + !final_buffer->Append(&bytes_following_base_relocation_table)) return false; } @@ -582,7 +557,7 @@ class RelocBlock { RelocBlockPOD pod; }; -CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) { +CheckBool EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) { std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); RelocBlock block; @@ -602,24 +577,6 @@ CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) { return ok; } -CheckBool EncodedProgram::GenerateElfRelocations(SinkStream* buffer) { - std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); - - Elf32_Rel relocation_block; - - // We only handle this specific type of relocation, so far. - relocation_block.r_info = R_386_RELATIVE; - - bool ok = true; - for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { - relocation_block.r_offset = abs32_relocs_[i]; - ok = buffer->Write(&relocation_block, sizeof(Elf32_Rel)); - } - - printf("Emitting size %ld\n", sizeof(Elf32_Rel) * abs32_relocs_.size()); - - return ok; -} //////////////////////////////////////////////////////////////////////////////// Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { diff --git a/courgette/encoded_program.h b/courgette/encoded_program.h index 62f1439..b120353 100644 --- a/courgette/encoded_program.h +++ b/courgette/encoded_program.h @@ -43,8 +43,7 @@ class EncodedProgram { CheckBool AddCopy(uint32 count, const void* bytes) WARN_UNUSED_RESULT; CheckBool AddRel32(int label_index) WARN_UNUSED_RESULT; CheckBool AddAbs32(int label_index) WARN_UNUSED_RESULT; - CheckBool AddPeMakeRelocs() WARN_UNUSED_RESULT; - CheckBool AddElfMakeRelocs() WARN_UNUSED_RESULT; + CheckBool AddMakeRelocs() WARN_UNUSED_RESULT; // (3) Serialize binary assembly language tables to a set of streams. CheckBool WriteTo(SinkStreamSet* streams) WARN_UNUSED_RESULT; @@ -59,18 +58,16 @@ class EncodedProgram { private: // Binary assembly language operations. - // These are part of the patch format. Reusing an existing value will - // break backwards compatibility. enum OP { - ORIGIN = 0, // ORIGIN <rva> - set address for subsequent assembly. - COPY = 1, // COPY <count> <bytes> - copy bytes to output. - COPY1 = 2, // COPY1 <byte> - same as COPY 1 <byte>. - REL32 = 3, // REL32 <index> - emit rel32 encoded reference to address at - // address table offset <index> - ABS32 = 4, // ABS32 <index> - emit abs32 encoded reference to address at - // address table offset <index> - MAKE_PE_RELOCATION_TABLE = 5, // Emit PE base relocation table blocks. - MAKE_ELF_RELOCATION_TABLE = 6, // Emit Elf relocation table. + ORIGIN, // ORIGIN <rva> - set address for subsequent assembly. + COPY, // COPY <count> <bytes> - copy bytes to output. + COPY1, // COPY1 <byte> - same as COPY 1 <byte>. + REL32, // REL32 <index> - emit rel32 encoded reference to address at + // address table offset <index> + ABS32, // ABS32 <index> - emit abs32 encoded reference to address at + // address table offset <index> + MAKE_BASE_RELOCATION_TABLE, // Emit base relocation table blocks. + OP_LAST }; typedef NoThrowBuffer<RVA> RvaVector; @@ -79,8 +76,7 @@ class EncodedProgram { typedef NoThrowBuffer<OP> OPVector; void DebuggingSummary(); - CheckBool GeneratePeRelocations(SinkStream *buffer) WARN_UNUSED_RESULT; - CheckBool GenerateElfRelocations(SinkStream *buffer) WARN_UNUSED_RESULT; + CheckBool GenerateBaseRelocations(SinkStream *buffer) WARN_UNUSED_RESULT; CheckBool DefineLabelCommon(RvaVector*, int, RVA) WARN_UNUSED_RESULT; void FinishLabelsCommon(RvaVector* addresses); diff --git a/courgette/encoded_program_fuzz_unittest.cc b/courgette/encoded_program_fuzz_unittest.cc index 9801fc8..fbf8df7 100644 --- a/courgette/encoded_program_fuzz_unittest.cc +++ b/courgette/encoded_program_fuzz_unittest.cc @@ -36,7 +36,7 @@ void DecodeFuzzTest::FuzzExe(const char* file_name) const { std::string file1 = FileContents(file_name); const void* original_buffer = file1.c_str(); - size_t original_length = file1.length(); + size_t original_length = file1.size(); courgette::AssemblyProgram* program = NULL; const courgette::Status parse_status = @@ -199,7 +199,6 @@ bool DecodeFuzzTest::TryAssemble(const std::string& buffer, TEST_F(DecodeFuzzTest, All) { FuzzExe("setup1.exe"); - FuzzExe("elf-32-1.exe"); } int main(int argc, char** argv) { diff --git a/courgette/ensemble_apply.cc b/courgette/ensemble_apply.cc index 475cdf2..d814264 100644 --- a/courgette/ensemble_apply.cc +++ b/courgette/ensemble_apply.cc @@ -142,9 +142,6 @@ Status EnsemblePatchApplication::ReadInitialParameters( case EXE_WIN_32_X86: patcher = new PatcherX86_32(base_region_); break; - case EXE_ELF_32_X86: - patcher = new PatcherX86_32(base_region_); - break; } if (patcher) diff --git a/courgette/ensemble_create.cc b/courgette/ensemble_create.cc index c098710..a5674ca9 100644 --- a/courgette/ensemble_create.cc +++ b/courgette/ensemble_create.cc @@ -76,15 +76,6 @@ TransformationPatchGenerator* MakeGenerator(Element* old_element, EXE_WIN_32_X86); return generator; } - case EXE_ELF_32_X86: { - TransformationPatchGenerator* generator = - new PatchGeneratorX86_32( - old_element, - new_element, - new PatcherX86_32(old_element->region()), - EXE_ELF_32_X86); - return generator; - } } LOG(WARNING) << "Unexpected Element::Kind " << old_element->kind(); diff --git a/courgette/patch_generator_x86_32.h b/courgette/patch_generator_x86_32.h index 5ac017b..0e3b0a8 100644 --- a/courgette/patch_generator_x86_32.h +++ b/courgette/patch_generator_x86_32.h @@ -17,9 +17,9 @@ namespace courgette { class PatchGeneratorX86_32 : public TransformationPatchGenerator { public: PatchGeneratorX86_32(Element* old_element, - Element* new_element, - PatcherX86_32* patcher, - ExecutableType kind) + Element* new_element, + PatcherX86_32* patcher, + ExecutableType kind) : TransformationPatchGenerator(old_element, new_element, patcher), kind_(kind) { } diff --git a/courgette/types_elf.h b/courgette/types_elf.h deleted file mode 100644 index 707f481..0000000 --- a/courgette/types_elf.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2011 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_ELF_TYPES_H_ -#define COURGETTE_ELF_TYPES_H_ - -// -// This header defines various types from the ELF file spec, but no code -// 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 - - -// The header at the top of the file -struct Elf32_Ehdr { - unsigned char e_ident[16]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -}; - -// 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 -}; - -// values for header->e_machine -enum e_machine_values { - EM_NONE = 0, // No machine - EM_386 = 3, // Intel Architecture - EM_x86_64 = 62, // Intel x86-64 Architecture - // Other values skipped -}; - -// A section header in the section header table -struct Elf32_Shdr { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -}; - -// Values for the section type field in a section header -enum sh_type_values { - SHT_NULL = 0, - SHT_PROGBITS = 1, - SHT_SYMTAB = 2, - SHT_STRTAB = 3, - SHT_RELA = 4, - SHT_HASH = 5, - SHT_DYNAMIC = 6, - SHT_NOTE = 7, - SHT_NOBITS = 8, - SHT_REL = 9, - SHT_SHLIB = 10, - SHT_DYNSYM = 11, - SHT_LOPROC = 0x70000000, - SHT_HIPROC = 0x7fffffff, - SHT_LOUSER = 0x80000000, - SHT_HIUSER = 0xffffffff, -}; - -struct Elf32_Phdr { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -}; - -// Values for the segment type field in a program segment header -enum ph_type_values { - PT_NULL = 0, - PT_LOAD = 1, - PT_DYNAMIC = 2, - PT_INTERP = 3, - PT_NOTE = 4, - PT_SHLIB = 5, - PT_PHDR = 6, - PT_LOPROC = 0x70000000, - PT_HIPROC = 0x7fffffff -}; - -struct Elf32_Rel { - Elf32_Addr r_offset; - Elf32_Word r_info; -}; - -struct Elf32_Rela { - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -}; - -enum elf32_rel_386_type_values { - R_386_NONE = 0, - R_386_32 = 1, - R_386_PC32 = 2, - R_386_GOT32 = 3, - R_386_PLT32 = 4, - R_386_COPY = 5, - R_386_GLOB_DAT = 6, - R_386_JMP_SLOT = 7, - R_386_RELATIVE = 8, - R_386_GOTOFF = 9, - R_386_GOTPC = 10, - R_386_TLS_TPOFF = 14, -}; - -#endif // COURGETTE_ELF_TYPES_H_ |