Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: courgette/disassembler_elf_32_x86.cc

Issue 1676683002: [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698