| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "courgette/disassembler_elf_32_x86.h" | 5 #include "courgette/disassembler_elf_32_x86.h" |
| 6 | 6 |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <algorithm> | |
| 11 #include <string> | |
| 12 #include <vector> | 7 #include <vector> |
| 13 | 8 |
| 14 #include "base/logging.h" | 9 #include "base/logging.h" |
| 15 | 10 #include "base/memory/scoped_ptr.h" |
| 16 #include "courgette/assembly_program.h" | 11 #include "courgette/assembly_program.h" |
| 17 #include "courgette/courgette.h" | 12 #include "courgette/courgette.h" |
| 18 #include "courgette/encoded_program.h" | |
| 19 | 13 |
| 20 namespace courgette { | 14 namespace courgette { |
| 21 | 15 |
| 22 DisassemblerElf32X86::DisassemblerElf32X86(const void* start, size_t length) | 16 CheckBool DisassemblerElf32X86::TypedRVAX86::ComputeRelativeTarget( |
| 23 : DisassemblerElf32(start, length) { | 17 const uint8_t* op_pointer) { |
| 18 set_relative_target(Read32LittleEndian(op_pointer) + 4); |
| 19 return true; |
| 24 } | 20 } |
| 25 | 21 |
| 26 // Convert an ELF relocation struction into an RVA | 22 CheckBool DisassemblerElf32X86::TypedRVAX86::EmitInstruction( |
| 23 AssemblyProgram* program, |
| 24 RVA target_rva) { |
| 25 return program->EmitRel32(program->FindOrMakeRel32Label(target_rva)); |
| 26 } |
| 27 |
| 28 uint16_t DisassemblerElf32X86::TypedRVAX86::op_size() const { |
| 29 return 4; |
| 30 } |
| 31 |
| 32 DisassemblerElf32X86::DisassemblerElf32X86(const void* start, size_t length) |
| 33 : DisassemblerElf32(start, length) { |
| 34 } |
| 35 |
| 36 // Convert an ELF relocation struction into an RVA. |
| 27 CheckBool DisassemblerElf32X86::RelToRVA(Elf32_Rel rel, RVA* result) const { | 37 CheckBool DisassemblerElf32X86::RelToRVA(Elf32_Rel rel, RVA* result) const { |
| 38 // The rightmost byte of r_info is the type. |
| 39 elf32_rel_386_type_values type = |
| 40 static_cast<elf32_rel_386_type_values>(rel.r_info & 0xFF); |
| 28 | 41 |
| 29 // The rightmost byte of r_info is the type... | 42 // The other 3 bytes of r_info are the symbol. |
| 30 elf32_rel_386_type_values type = | |
| 31 (elf32_rel_386_type_values)(unsigned char)rel.r_info; | |
| 32 | |
| 33 // The other 3 bytes of r_info are the symbol | |
| 34 uint32_t symbol = rel.r_info >> 8; | 43 uint32_t symbol = rel.r_info >> 8; |
| 35 | 44 |
| 36 switch(type) | 45 switch(type) { |
| 37 { | |
| 38 case R_386_NONE: | 46 case R_386_NONE: |
| 39 case R_386_32: | 47 case R_386_32: |
| 40 case R_386_PC32: | 48 case R_386_PC32: |
| 41 case R_386_GOT32: | 49 case R_386_GOT32: |
| 42 case R_386_PLT32: | 50 case R_386_PLT32: |
| 43 case R_386_COPY: | 51 case R_386_COPY: |
| 44 case R_386_GLOB_DAT: | 52 case R_386_GLOB_DAT: |
| 45 case R_386_JMP_SLOT: | 53 case R_386_JMP_SLOT: |
| 46 return false; | 54 return false; |
| 47 | 55 |
| 48 case R_386_RELATIVE: | 56 case R_386_RELATIVE: |
| 49 if (symbol != 0) | 57 if (symbol != 0) |
| 50 return false; | 58 return false; |
| 51 | 59 |
| 52 // This is a basic ABS32 relocation address | 60 // This is a basic ABS32 relocation address. |
| 53 *result = rel.r_offset; | 61 *result = rel.r_offset; |
| 54 return true; | 62 return true; |
| 55 | 63 |
| 56 case R_386_GOTOFF: | 64 case R_386_GOTOFF: |
| 57 case R_386_GOTPC: | 65 case R_386_GOTPC: |
| 58 case R_386_TLS_TPOFF: | 66 case R_386_TLS_TPOFF: |
| 59 return false; | 67 return false; |
| 60 } | 68 } |
| 61 | 69 |
| 62 return false; | 70 return false; |
| 63 } | 71 } |
| 64 | 72 |
| 65 CheckBool DisassemblerElf32X86::ParseRelocationSection( | 73 CheckBool DisassemblerElf32X86::ParseRelocationSection( |
| 66 const Elf32_Shdr *section_header, | 74 const Elf32_Shdr* section_header, |
| 67 AssemblyProgram* program) { | 75 AssemblyProgram* program) { |
| 68 // We can reproduce the R_386_RELATIVE entries in one of the relocation | 76 // We can reproduce the R_386_RELATIVE entries in one of the relocation table |
| 69 // table based on other information in the patch, given these | 77 // based on other information in the patch, given these conditions: |
| 70 // conditions.... | |
| 71 // | 78 // |
| 72 // All R_386_RELATIVE entries are: | 79 // All R_386_RELATIVE entries are: |
| 73 // 1) In the same relocation table | 80 // 1) In the same relocation table |
| 74 // 2) Are consecutive | 81 // 2) Are consecutive |
| 75 // 3) Are sorted in memory address order | 82 // 3) Are sorted in memory address order |
| 76 // | 83 // |
| 77 // Happily, this is normally the case, but it's not required by spec | 84 // Happily, this is normally the case, but it's not required by spec, so we |
| 78 // so we check, and just don't do it if we don't match up. | 85 // check, and just don't do it if we don't match up. |
| 79 | 86 |
| 80 // The expectation is that one relocation section will contain | 87 // The expectation is that one relocation section will contain all of our |
| 81 // all of our R_386_RELATIVE entries in the expected order followed | 88 // R_386_RELATIVE entries in the expected order followed by assorted other |
| 82 // by assorted other entries we can't use special handling for. | 89 // entries we can't use special handling for. |
| 83 | 90 |
| 84 bool match = true; | 91 bool match = true; |
| 85 | 92 |
| 86 // Walk all the bytes in the section, matching relocation table or not | 93 // Walk all the bytes in the section, matching relocation table or not. |
| 87 size_t file_offset = section_header->sh_offset; | 94 FileOffset file_offset = section_header->sh_offset; |
| 88 size_t section_end = section_header->sh_offset + section_header->sh_size; | 95 FileOffset section_end = file_offset + section_header->sh_size; |
| 89 | 96 |
| 90 Elf32_Rel *section_relocs_iter = | 97 const Elf32_Rel* section_relocs_iter = reinterpret_cast<const Elf32_Rel*>( |
| 91 (Elf32_Rel *)OffsetToPointer(section_header->sh_offset); | 98 FileOffsetToPointer(section_header->sh_offset)); |
| 92 | 99 |
| 93 uint32_t section_relocs_count = | 100 uint32_t section_relocs_count = |
| 94 section_header->sh_size / section_header->sh_entsize; | 101 section_header->sh_size / section_header->sh_entsize; |
| 95 | 102 |
| 96 if (abs32_locations_.empty()) | 103 if (abs32_locations_.empty()) |
| 97 match = false; | 104 match = false; |
| 98 | 105 |
| 99 if (abs32_locations_.size() > section_relocs_count) | 106 if (abs32_locations_.size() > section_relocs_count) |
| 100 match = false; | 107 match = false; |
| 101 | 108 |
| 102 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); | 109 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); |
| 103 | 110 |
| 104 while (match && (reloc_iter != abs32_locations_.end())) { | 111 while (match && (reloc_iter != abs32_locations_.end())) { |
| 105 if (section_relocs_iter->r_info != R_386_RELATIVE || | 112 if (section_relocs_iter->r_info != R_386_RELATIVE || |
| 106 section_relocs_iter->r_offset != *reloc_iter) | 113 section_relocs_iter->r_offset != *reloc_iter) |
| 107 match = false; | 114 match = false; |
| 108 section_relocs_iter++; | 115 ++section_relocs_iter; |
| 109 reloc_iter++; | 116 ++reloc_iter; |
| 110 } | 117 } |
| 111 | 118 |
| 112 if (match) { | 119 if (match) { |
| 113 // Skip over relocation tables | 120 // Skip over relocation tables. |
| 114 if (!program->EmitElfRelocationInstruction()) | 121 if (!program->EmitElfRelocationInstruction()) |
| 115 return false; | 122 return false; |
| 116 file_offset += sizeof(Elf32_Rel) * abs32_locations_.size(); | 123 file_offset += sizeof(Elf32_Rel) * abs32_locations_.size(); |
| 117 } | 124 } |
| 118 | 125 |
| 119 return ParseSimpleRegion(file_offset, section_end, program); | 126 return ParseSimpleRegion(file_offset, section_end, program); |
| 120 } | 127 } |
| 121 | 128 |
| 129 // TODO(huangs): Detect and avoid overlap with abs32 addresses. |
| 122 CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSection( | 130 CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSection( |
| 123 const Elf32_Shdr* section_header) { | 131 const Elf32_Shdr* section_header) { |
| 124 uint32_t start_file_offset = section_header->sh_offset; | 132 FileOffset start_file_offset = section_header->sh_offset; |
| 125 uint32_t end_file_offset = start_file_offset + section_header->sh_size; | 133 FileOffset end_file_offset = start_file_offset + section_header->sh_size; |
| 126 | 134 |
| 127 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); | 135 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset); |
| 128 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); | 136 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset); |
| 129 | 137 |
| 130 // Quick way to convert from Pointer to RVA within a single Section is to | 138 // Quick way to convert from Pointer to RVA within a single Section is to |
| 131 // subtract 'pointer_to_rva'. | 139 // subtract |pointer_to_rva|. |
| 132 const uint8_t* const adjust_pointer_to_rva = | 140 const uint8_t* const adjust_pointer_to_rva = |
| 133 start_pointer - section_header->sh_addr; | 141 start_pointer - section_header->sh_addr; |
| 134 | 142 |
| 135 // Find the rel32 relocations. | 143 // Find the rel32 relocations. |
| 136 const uint8_t* p = start_pointer; | 144 const uint8_t* p = start_pointer; |
| 137 while (p < end_pointer) { | 145 while (p < end_pointer) { |
| 138 //RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); | |
| 139 | |
| 140 // Heuristic discovery of rel32 locations in instruction stream: are the | 146 // Heuristic discovery of rel32 locations in instruction stream: are the |
| 141 // next few bytes the start of an instruction containing a rel32 | 147 // next few bytes the start of an instruction containing a rel32 |
| 142 // addressing mode? | 148 // addressing mode? |
| 143 const uint8_t* rel32 = NULL; | 149 const uint8_t* rel32 = nullptr; |
| 144 | 150 |
| 145 if (p + 5 <= end_pointer) { | 151 if (p + 5 <= end_pointer) { |
| 146 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 | 152 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 |
| 147 rel32 = p + 1; | 153 rel32 = p + 1; |
| 148 } | 154 } |
| 149 } | 155 } |
| 150 if (p + 6 <= end_pointer) { | 156 if (p + 6 <= end_pointer) { |
| 151 if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form | 157 if (*p == 0x0F && (p[1] & 0xF0) == 0x80) { // Jcc long form |
| 152 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely | 158 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely |
| 153 rel32 = p + 2; | 159 rel32 = p + 2; |
| 154 } | 160 } |
| 155 } | 161 } |
| 156 if (rel32) { | 162 if (rel32) { |
| 157 RVA rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); | 163 RVA rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); |
| 158 TypedRVAX86* rel32_rva = new TypedRVAX86(rva); | 164 scoped_ptr<TypedRVAX86> rel32_rva(new TypedRVAX86(rva)); |
| 159 | 165 |
| 160 if (!rel32_rva->ComputeRelativeTarget(rel32)) { | 166 if (!rel32_rva->ComputeRelativeTarget(rel32)) |
| 161 delete rel32_rva; | |
| 162 return false; | 167 return false; |
| 163 } | |
| 164 | 168 |
| 165 RVA target_rva = rel32_rva->rva() + rel32_rva->relative_target(); | 169 RVA target_rva = rel32_rva->rva() + rel32_rva->relative_target(); |
| 166 // To be valid, rel32 target must be within image, and within this | 170 if (IsValidTargetRVA(target_rva)) { |
| 167 // section. | 171 rel32_locations_.push_back(rel32_rva.release()); |
| 168 if (IsValidRVA(target_rva)) { | |
| 169 rel32_locations_.push_back(rel32_rva); | |
| 170 #if COURGETTE_HISTOGRAM_TARGETS | 172 #if COURGETTE_HISTOGRAM_TARGETS |
| 171 ++rel32_target_rvas_[target_rva]; | 173 ++rel32_target_rvas_[target_rva]; |
| 172 #endif | 174 #endif |
| 173 p = rel32 + 4; | 175 p = rel32 + 4; |
| 174 continue; | 176 continue; |
| 175 } else { | |
| 176 delete rel32_rva; | |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 p += 1; | 179 p += 1; |
| 180 } | 180 } |
| 181 | 181 |
| 182 return true; | 182 return true; |
| 183 } | 183 } |
| 184 | 184 |
| 185 } // namespace courgette | 185 } // namespace courgette |
| OLD | NEW |