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

Side by Side Diff: courgette/disassembler_elf_32.cc

Issue 1792603006: Revert of [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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.h" 5 #include "courgette/disassembler_elf_32.h"
6 6
7 #include <stddef.h>
8 #include <stdint.h>
9
7 #include <algorithm> 10 #include <algorithm>
11 #include <string>
12 #include <vector>
8 13
9 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_vector.h"
16
10 #include "courgette/assembly_program.h" 17 #include "courgette/assembly_program.h"
11 #include "courgette/courgette.h" 18 #include "courgette/courgette.h"
19 #include "courgette/encoded_program.h"
12 20
13 namespace courgette { 21 namespace courgette {
14 22
15 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) 23 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
16 : Disassembler(start, length), 24 : Disassembler(start, length),
17 header_(nullptr), 25 header_(NULL),
18 section_header_table_(nullptr), 26 section_header_table_(NULL),
19 section_header_table_size_(0), 27 section_header_table_size_(0),
20 program_header_table_(nullptr), 28 program_header_table_(NULL),
21 program_header_table_size_(0), 29 program_header_table_size_(0),
22 default_string_section_(nullptr) { 30 default_string_section_(NULL) {
23 }
24
25 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
26 // File offsets can be 64-bit values, but we are dealing with 32-bit
27 // executables and so only need to support 32-bit file sizes.
28 uint32_t offset32 = static_cast<uint32_t>(offset);
29
30 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
31 ++section_id) {
32 const Elf32_Shdr* section_header = SectionHeader(section_id);
33 // These can appear to have a size in the file, but don't.
34 if (section_header->sh_type == SHT_NOBITS)
35 continue;
36
37 Elf32_Off section_begin = section_header->sh_offset;
38 Elf32_Off section_end = section_begin + section_header->sh_size;
39
40 if (offset32 >= section_begin && offset32 < section_end) {
41 return section_header->sh_addr + (offset32 - section_begin);
42 }
43 }
44
45 return 0;
46 }
47
48 FileOffset DisassemblerElf32::RVAToFileOffset(RVA rva) const {
49 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
50 ++section_id) {
51 const Elf32_Shdr* section_header = SectionHeader(section_id);
52 // These can appear to have a size in the file, but don't.
53 if (section_header->sh_type == SHT_NOBITS)
54 continue;
55 Elf32_Addr begin = section_header->sh_addr;
56 Elf32_Addr end = begin + section_header->sh_size;
57
58 if (rva >= begin && rva < end)
59 return section_header->sh_offset + (rva - begin);
60 }
61 return kNoFileOffset;
62 } 31 }
63 32
64 bool DisassemblerElf32::ParseHeader() { 33 bool DisassemblerElf32::ParseHeader() {
65 if (length() < sizeof(Elf32_Ehdr)) 34 if (length() < sizeof(Elf32_Ehdr))
66 return Bad("Too small"); 35 return Bad("Too small");
67 36
68 header_ = reinterpret_cast<const Elf32_Ehdr*>(start()); 37 header_ = (Elf32_Ehdr *)start();
69 38
70 // Have magic for ELF header? 39 // Have magic for elf header?
71 if (header_->e_ident[0] != 0x7f || 40 if (header_->e_ident[0] != 0x7f ||
72 header_->e_ident[1] != 'E' || 41 header_->e_ident[1] != 'E' ||
73 header_->e_ident[2] != 'L' || 42 header_->e_ident[2] != 'L' ||
74 header_->e_ident[3] != 'F') 43 header_->e_ident[3] != 'F')
75 return Bad("No Magic Number"); 44 return Bad("No Magic Number");
76 45
77 if (header_->e_type != ET_EXEC && 46 if (header_->e_type != ET_EXEC &&
78 header_->e_type != ET_DYN) 47 header_->e_type != ET_DYN)
79 return Bad("Not an executable file or shared library"); 48 return Bad("Not an executable file or shared library");
80 49
81 if (header_->e_machine != ElfEM()) 50 if (header_->e_machine != ElfEM())
82 return Bad("Not a supported architecture"); 51 return Bad("Not a supported architecture");
83 52
84 if (header_->e_version != 1) 53 if (header_->e_version != 1)
85 return Bad("Unknown file version"); 54 return Bad("Unknown file version");
86 55
87 if (header_->e_shentsize != sizeof(Elf32_Shdr)) 56 if (header_->e_shentsize != sizeof(Elf32_Shdr))
88 return Bad("Unexpected section header size"); 57 return Bad("Unexpected section header size");
89 58
90 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr))) 59 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
91 return Bad("Out of bounds section header table"); 60 return Bad("Out of bounds section header table");
92 61
93 section_header_table_ = reinterpret_cast<const Elf32_Shdr*>( 62 section_header_table_ = (Elf32_Shdr *)OffsetToPointer(header_->e_shoff);
94 FileOffsetToPointer(header_->e_shoff));
95 section_header_table_size_ = header_->e_shnum; 63 section_header_table_size_ = header_->e_shnum;
96 64
97 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr))) 65 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
98 return Bad("Out of bounds program header table"); 66 return Bad("Out of bounds program header table");
99 67
100 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>( 68 program_header_table_ = (Elf32_Phdr *)OffsetToPointer(header_->e_phoff);
101 FileOffsetToPointer(header_->e_phoff));
102 program_header_table_size_ = header_->e_phnum; 69 program_header_table_size_ = header_->e_phnum;
103 70
104 if (header_->e_shstrndx >= header_->e_shnum) 71 if (header_->e_shstrndx >= header_->e_shnum)
105 return Bad("Out of bounds string section index"); 72 return Bad("Out of bounds string section index");
106 73
107 default_string_section_ = reinterpret_cast<const char*>( 74 default_string_section_ = (const char *)SectionBody((int)header_->e_shstrndx);
108 SectionBody(static_cast<int>(header_->e_shstrndx)));
109 75
110 if (!UpdateLength()) 76 if (!UpdateLength()) {
111 return Bad("Out of bounds section or segment"); 77 return Bad("Out of bounds section or segment");
78 }
112 79
113 return Good(); 80 return Good();
114 } 81 }
115 82
116 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { 83 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
117 if (!ok()) 84 if (!ok())
118 return false; 85 return false;
119 86
120 // The Image Base is always 0 for ELF Executables 87 // The Image Base is always 0 for ELF Executables
121 target->set_image_base(0); 88 target->set_image_base(0);
122 89
123 if (!ParseAbs32Relocs()) 90 if (!ParseAbs32Relocs())
124 return false; 91 return false;
125 92
126 if (!ParseRel32RelocsFromSections()) 93 if (!ParseRel32RelocsFromSections())
127 return false; 94 return false;
128 95
129 if (!ParseFile(target)) 96 if (!ParseFile(target))
130 return false; 97 return false;
131 98
132 target->DefaultAssignIndexes(); 99 target->DefaultAssignIndexes();
100
133 return true; 101 return true;
134 } 102 }
135 103
136 bool DisassemblerElf32::UpdateLength() { 104 bool DisassemblerElf32::UpdateLength() {
137 Elf32_Off result = 0; 105 Elf32_Off result = 0;
138 106
139 // Find the end of the last section 107 // Find the end of the last section
140 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 108 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) {
141 ++section_id) { 109 const Elf32_Shdr *section_header = SectionHeader(section_id);
142 const Elf32_Shdr* section_header = SectionHeader(section_id);
143 110
144 if (section_header->sh_type == SHT_NOBITS) 111 if (section_header->sh_type == SHT_NOBITS)
145 continue; 112 continue;
146 113
147 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1)) 114 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
148 return false; 115 return false;
149 116
150 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size; 117 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
151 result = std::max(result, section_end); 118 result = std::max(result, section_end);
152 } 119 }
153 120
154 // Find the end of the last segment 121 // Find the end of the last segment
155 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount(); 122 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) {
156 ++segment_id) { 123 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i);
157 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
158 124
159 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1)) 125 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
160 return false; 126 return false;
161 127
162 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz; 128 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
163 result = std::max(result, segment_end); 129 result = std::max(result, segment_end);
164 } 130 }
165 131
166 Elf32_Off section_table_end = 132 Elf32_Off section_table_end = header_->e_shoff +
167 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr)); 133 (header_->e_shnum * sizeof(Elf32_Shdr));
168 result = std::max(result, section_table_end); 134 result = std::max(result, section_table_end);
169 135
170 Elf32_Off segment_table_end = 136 Elf32_Off segment_table_end = header_->e_phoff +
171 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr)); 137 (header_->e_phnum * sizeof(Elf32_Phdr));
172 result = std::max(result, segment_table_end); 138 result = std::max(result, segment_table_end);
173 139
174 ReduceLength(result); 140 ReduceLength(result);
175 return true; 141 return true;
176 } 142 }
177 143
178 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const { 144 CheckBool DisassemblerElf32::IsValidRVA(RVA rva) const {
179 if (rva == kUnassignedRVA) 145 if (rva == kUnassignedRVA)
180 return false; 146 return false;
181 147
182 // It's valid if it's contained in any program segment 148 // It's valid if it's contained in any program segment
183 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount(); 149 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) {
184 ++segment_id) { 150 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i);
185 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
186 151
187 if (segment_header->p_type != PT_LOAD) 152 if (segment_header->p_type != PT_LOAD)
188 continue; 153 continue;
189 154
190 Elf32_Addr begin = segment_header->p_vaddr; 155 Elf32_Addr begin = segment_header->p_vaddr;
191 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz; 156 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
192 157
193 if (rva >= begin && rva < end) 158 if (rva >= begin && rva < end)
194 return true; 159 return true;
195 } 160 }
196 161
197 return false; 162 return false;
198 } 163 }
199 164
200 CheckBool DisassemblerElf32::RVAsToFileOffsets( 165 CheckBool DisassemblerElf32::RVAToFileOffset(RVA rva,
201 const std::vector<RVA>& rvas, 166 size_t* result) const {
202 std::vector<FileOffset>* file_offsets) { 167 for (int i = 0; i < SectionHeaderCount(); i++) {
203 file_offsets->clear(); 168 const Elf32_Shdr *section_header = SectionHeader(i);
204 for (RVA rva : rvas) { 169 // These can appear to have a size in the file, but don't.
205 FileOffset file_offset = RVAToFileOffset(rva); 170 if (section_header->sh_type == SHT_NOBITS)
206 if (file_offset == kNoFileOffset) 171 continue;
172 Elf32_Addr begin = section_header->sh_addr;
173 Elf32_Addr end = begin + section_header->sh_size;
174
175 if (rva >= begin && rva < end) {
176 *result = section_header->sh_offset + (rva - begin);
177 return true;
178 }
179 }
180 return false;
181 }
182
183 RVA DisassemblerElf32::FileOffsetToRVA(size_t offset) const {
184 // File offsets can be 64 bit values, but we are dealing with 32
185 // bit executables and so only need to support 32bit file sizes.
186 uint32_t offset32 = (uint32_t)offset;
187
188 for (int i = 0; i < SectionHeaderCount(); i++) {
189
190 const Elf32_Shdr *section_header = SectionHeader(i);
191
192 // These can appear to have a size in the file, but don't.
193 if (section_header->sh_type == SHT_NOBITS)
194 continue;
195
196 Elf32_Off section_begin = section_header->sh_offset;
197 Elf32_Off section_end = section_begin + section_header->sh_size;
198
199 if (offset32 >= section_begin && offset32 < section_end) {
200 return section_header->sh_addr + (offset32 - section_begin);
201 }
202 }
203
204 return 0;
205 }
206
207 CheckBool DisassemblerElf32::RVAsToOffsets(std::vector<RVA>* rvas,
208 std::vector<size_t>* offsets) {
209 offsets->clear();
210
211 for (std::vector<RVA>::iterator rva = rvas->begin();
212 rva != rvas->end();
213 rva++) {
214
215 size_t offset;
216
217 if (!RVAToFileOffset(*rva, &offset))
207 return false; 218 return false;
208 file_offsets->push_back(file_offset); 219
220 offsets->push_back(offset);
209 } 221 }
222
210 return true; 223 return true;
211 } 224 }
212 225
213 CheckBool DisassemblerElf32::RVAsToFileOffsets( 226 CheckBool DisassemblerElf32::RVAsToOffsets(ScopedVector<TypedRVA>* rvas) {
214 ScopedVector<TypedRVA>* typed_rvas) { 227 for (ScopedVector<TypedRVA>::iterator rva = rvas->begin();
215 for (TypedRVA* typed_rva : *typed_rvas) { 228 rva != rvas->end();
216 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); 229 rva++) {
217 if (file_offset == kNoFileOffset) 230
231 size_t offset;
232
233 if (!RVAToFileOffset((*rva)->rva(), &offset))
218 return false; 234 return false;
219 typed_rva->set_file_offset(file_offset); 235
236 (*rva)->set_offset(offset);
220 } 237 }
238
221 return true; 239 return true;
222 } 240 }
223 241
224 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { 242 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
225 // Walk all the bytes in the file, whether or not in a section. 243 // Walk all the bytes in the file, whether or not in a section.
226 FileOffset file_offset = 0; 244 uint32_t file_offset = 0;
227 245
228 std::vector<FileOffset> abs_offsets; 246 std::vector<size_t> abs_offsets;
229 247
230 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) 248 if (!RVAsToOffsets(&abs32_locations_, &abs_offsets))
231 return false; 249 return false;
232 250
233 if (!RVAsToFileOffsets(&rel32_locations_)) 251 if (!RVAsToOffsets(&rel32_locations_))
234 return false; 252 return false;
235 253
236 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin(); 254 std::vector<size_t>::iterator current_abs_offset = abs_offsets.begin();
237 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin(); 255 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin();
238 256
239 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end(); 257 std::vector<size_t>::iterator end_abs_offset = abs_offsets.end();
240 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end(); 258 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end();
241 259
242 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 260 for (int section_id = 0;
243 ++section_id) { 261 section_id < SectionHeaderCount();
244 const Elf32_Shdr* section_header = SectionHeader(section_id); 262 section_id++) {
263
264 const Elf32_Shdr *section_header = SectionHeader(section_id);
245 265
246 if (section_header->sh_type == SHT_NOBITS) 266 if (section_header->sh_type == SHT_NOBITS)
247 continue; 267 continue;
248 268
249 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program)) 269 if (!ParseSimpleRegion(file_offset,
270 section_header->sh_offset,
271 program))
250 return false; 272 return false;
251
252 file_offset = section_header->sh_offset; 273 file_offset = section_header->sh_offset;
253 274
254 switch (section_header->sh_type) { 275 switch (section_header->sh_type) {
255 case SHT_REL: 276 case SHT_REL:
256 if (!ParseRelocationSection(section_header, program)) 277 if (!ParseRelocationSection(section_header, program))
257 return false; 278 return false;
258 file_offset = section_header->sh_offset + section_header->sh_size; 279 file_offset = section_header->sh_offset + section_header->sh_size;
259 break; 280 break;
260 case SHT_PROGBITS: 281 case SHT_PROGBITS:
261 if (!ParseProgbitsSection(section_header, 282 if (!ParseProgbitsSection(section_header,
262 &current_abs_offset, 283 &current_abs_offset, end_abs_offset,
263 end_abs_offset, 284 &current_rel, end_rel,
264 &current_rel, 285 program))
265 end_rel,
266 program)) {
267 return false; 286 return false;
268 }
269 file_offset = section_header->sh_offset + section_header->sh_size; 287 file_offset = section_header->sh_offset + section_header->sh_size;
270 break; 288 break;
271 case SHT_INIT_ARRAY: 289 case SHT_INIT_ARRAY:
272 // Fall through 290 // Fall through
273 case SHT_FINI_ARRAY: 291 case SHT_FINI_ARRAY:
274 while (current_abs_offset != end_abs_offset && 292 while (current_abs_offset != end_abs_offset &&
275 *current_abs_offset >= section_header->sh_offset && 293 *current_abs_offset >= section_header->sh_offset &&
276 *current_abs_offset < 294 *current_abs_offset <
277 section_header->sh_offset + section_header->sh_size) { 295 (section_header->sh_offset + section_header->sh_size)) {
278 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section 296 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
279 VLOG(1) << "Skipping relocation entry for unsupported section: " 297 VLOG(1) << "Skipping relocation entry for unsupported section: " <<
280 << section_header->sh_type; 298 section_header->sh_type;
281 ++current_abs_offset; 299 current_abs_offset++;
282 } 300 }
283 break; 301 break;
284 default: 302 default:
285 if (current_abs_offset != end_abs_offset && 303 if (current_abs_offset != end_abs_offset &&
286 *current_abs_offset >= section_header->sh_offset && 304 *current_abs_offset >= section_header->sh_offset &&
287 *current_abs_offset < 305 *current_abs_offset <
288 section_header->sh_offset + section_header->sh_size) { 306 (section_header->sh_offset + section_header->sh_size))
289 VLOG(1) << "Relocation address in unrecognized ELF section: " 307 VLOG(1) << "Relocation address in unrecognized ELF section: " << \
290 << section_header->sh_type; 308 section_header->sh_type;
291 } 309 break;
292 break;
293 } 310 }
294 } 311 }
295 312
296 // Rest of the file past the last section 313 // Rest of the file past the last section
297 if (!ParseSimpleRegion(file_offset, length(), program)) 314 if (!ParseSimpleRegion(file_offset,
315 length(),
316 program))
298 return false; 317 return false;
299 318
300 // Make certain we consume all of the relocations as expected 319 // Make certain we consume all of the relocations as expected
301 return (current_abs_offset == end_abs_offset); 320 return (current_abs_offset == end_abs_offset);
302 } 321 }
303 322
304 CheckBool DisassemblerElf32::ParseProgbitsSection( 323 CheckBool DisassemblerElf32::ParseProgbitsSection(
305 const Elf32_Shdr* section_header, 324 const Elf32_Shdr *section_header,
306 std::vector<FileOffset>::iterator* current_abs_offset, 325 std::vector<size_t>::iterator* current_abs_offset,
307 std::vector<FileOffset>::iterator end_abs_offset, 326 std::vector<size_t>::iterator end_abs_offset,
308 ScopedVector<TypedRVA>::iterator* current_rel, 327 ScopedVector<TypedRVA>::iterator* current_rel,
309 ScopedVector<TypedRVA>::iterator end_rel, 328 ScopedVector<TypedRVA>::iterator end_rel,
310 AssemblyProgram* program) { 329 AssemblyProgram* program) {
330
311 // Walk all the bytes in the file, whether or not in a section. 331 // Walk all the bytes in the file, whether or not in a section.
312 FileOffset file_offset = section_header->sh_offset; 332 size_t file_offset = section_header->sh_offset;
313 FileOffset section_end = section_header->sh_offset + section_header->sh_size; 333 size_t section_end = section_header->sh_offset + section_header->sh_size;
314 334
315 Elf32_Addr origin = section_header->sh_addr; 335 Elf32_Addr origin = section_header->sh_addr;
316 FileOffset origin_offset = section_header->sh_offset; 336 size_t origin_offset = section_header->sh_offset;
317 if (!program->EmitOriginInstruction(origin)) 337 if (!program->EmitOriginInstruction(origin))
318 return false; 338 return false;
319 339
320 while (file_offset < section_end) { 340 while (file_offset < section_end) {
341
321 if (*current_abs_offset != end_abs_offset && 342 if (*current_abs_offset != end_abs_offset &&
322 file_offset > **current_abs_offset) 343 file_offset > **current_abs_offset)
323 return false; 344 return false;
324 345
325 while (*current_rel != end_rel && 346 while (*current_rel != end_rel &&
326 file_offset > (**current_rel)->file_offset()) { 347 file_offset > (**current_rel)->get_offset()) {
327 ++(*current_rel); 348 (*current_rel)++;
328 } 349 }
329 350
330 FileOffset next_relocation = section_end; 351 size_t next_relocation = section_end;
331 352
332 if (*current_abs_offset != end_abs_offset && 353 if (*current_abs_offset != end_abs_offset &&
333 next_relocation > **current_abs_offset) 354 next_relocation > **current_abs_offset)
334 next_relocation = **current_abs_offset; 355 next_relocation = **current_abs_offset;
335 356
336 // Rel offsets are heuristically derived, and might (incorrectly) overlap 357 // Rel offsets are heuristically derived, and might (incorrectly) overlap
337 // an Abs value, or the end of the section, so +3 to make sure there is 358 // an Abs value, or the end of the section, so +3 to make sure there is
338 // room for the full 4 byte value. 359 // room for the full 4 byte value.
339 if (*current_rel != end_rel && 360 if (*current_rel != end_rel &&
340 next_relocation > ((**current_rel)->file_offset() + 3)) 361 next_relocation > ((**current_rel)->get_offset() + 3))
341 next_relocation = (**current_rel)->file_offset(); 362 next_relocation = (**current_rel)->get_offset();
342 363
343 if (next_relocation > file_offset) { 364 if (next_relocation > file_offset) {
344 if (!ParseSimpleRegion(file_offset, next_relocation, program)) 365 if (!ParseSimpleRegion(file_offset, next_relocation, program))
345 return false; 366 return false;
346 367
347 file_offset = next_relocation; 368 file_offset = next_relocation;
348 continue; 369 continue;
349 } 370 }
350 371
351 if (*current_abs_offset != end_abs_offset && 372 if (*current_abs_offset != end_abs_offset &&
352 file_offset == **current_abs_offset) { 373 file_offset == **current_abs_offset) {
353 const uint8_t* p = FileOffsetToPointer(file_offset); 374 const uint8_t* p = OffsetToPointer(file_offset);
354 RVA target_rva = Read32LittleEndian(p); 375 RVA target_rva = Read32LittleEndian(p);
355 376
356 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) 377 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
357 return false; 378 return false;
358 file_offset += sizeof(RVA); 379 file_offset += sizeof(RVA);
359 ++(*current_abs_offset); 380 (*current_abs_offset)++;
360 continue; 381 continue;
361 } 382 }
362 383
363 if (*current_rel != end_rel && 384 if (*current_rel != end_rel &&
364 file_offset == (**current_rel)->file_offset()) { 385 file_offset == (**current_rel)->get_offset()) {
365 uint32_t relative_target = (**current_rel)->relative_target(); 386 uint32_t relative_target = (**current_rel)->relative_target();
366 // This cast is for 64 bit systems, and is only safe because we 387 // This cast is for 64 bit systems, and is only safe because we
367 // are working on 32 bit executables. 388 // are working on 32 bit executables.
368 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + 389 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
369 relative_target); 390 relative_target);
370 391
371 if (!(**current_rel)->EmitInstruction(program, target_rva)) 392 if (! (**current_rel)->EmitInstruction(program, target_rva))
372 return false; 393 return false;
373 file_offset += (**current_rel)->op_size(); 394 file_offset += (**current_rel)->op_size();
374 ++(*current_rel); 395 (*current_rel)++;
375 continue; 396 continue;
376 } 397 }
377 } 398 }
378 399
379 // Rest of the section (if any) 400 // Rest of the section (if any)
380 return ParseSimpleRegion(file_offset, section_end, program); 401 return ParseSimpleRegion(file_offset, section_end, program);
381 } 402 }
382 403
383 CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset, 404 CheckBool DisassemblerElf32::ParseSimpleRegion(
384 FileOffset end_file_offset, 405 size_t start_file_offset,
385 AssemblyProgram* program) { 406 size_t end_file_offset,
407 AssemblyProgram* program) {
386 // Callers don't guarantee start < end 408 // Callers don't guarantee start < end
387 if (start_file_offset >= end_file_offset) 409 if (start_file_offset >= end_file_offset) return true;
388 return true;
389 410
390 const size_t len = end_file_offset - start_file_offset; 411 const size_t len = end_file_offset - start_file_offset;
391 412
392 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset), 413 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), len))
393 len)) {
394 return false; 414 return false;
395 }
396 415
397 return true; 416 return true;
398 } 417 }
399 418
400 CheckBool DisassemblerElf32::ParseAbs32Relocs() { 419 CheckBool DisassemblerElf32::ParseAbs32Relocs() {
401 abs32_locations_.clear(); 420 abs32_locations_.clear();
402 421
403 // Loop through sections for relocation sections 422 // Loop through sections for relocation sections
404 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 423 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) {
405 ++section_id) { 424 const Elf32_Shdr *section_header = SectionHeader(section_id);
406 const Elf32_Shdr* section_header = SectionHeader(section_id);
407 425
408 if (section_header->sh_type == SHT_REL) { 426 if (section_header->sh_type == SHT_REL) {
409 const Elf32_Rel* relocs_table = 427
410 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id)); 428 Elf32_Rel *relocs_table = (Elf32_Rel *)SectionBody(section_id);
411 429
412 int relocs_table_count = section_header->sh_size / 430 int relocs_table_count = section_header->sh_size /
413 section_header->sh_entsize; 431 section_header->sh_entsize;
414 432
415 // Elf32_Word relocation_section_id = section_header->sh_info; 433 // Elf32_Word relocation_section_id = section_header->sh_info;
416 434
417 // Loop through relocation objects in the relocation section 435 // Loop through relocation objects in the relocation section
418 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) { 436 for (int rel_id = 0; rel_id < relocs_table_count; rel_id++) {
419 RVA rva; 437 RVA rva;
420 438
421 // Quite a few of these conversions fail, and we simply skip 439 // Quite a few of these conversions fail, and we simply skip
422 // them, that's okay. 440 // them, that's okay.
423 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva)) 441 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
424 abs32_locations_.push_back(rva); 442 abs32_locations_.push_back(rva);
425 } 443 }
426 } 444 }
427 } 445 }
428 446
429 std::sort(abs32_locations_.begin(), abs32_locations_.end()); 447 std::sort(abs32_locations_.begin(), abs32_locations_.end());
430 DCHECK(abs32_locations_.empty() || 448 DCHECK(abs32_locations_.empty() ||
431 abs32_locations_.back() != kUnassignedRVA); 449 abs32_locations_.back() != kUnassignedRVA);
432 return true; 450 return true;
433 } 451 }
434 452
435 CheckBool DisassemblerElf32::CheckSection(RVA rva) { 453 CheckBool DisassemblerElf32::CheckSection(RVA rva) {
436 FileOffset file_offset = RVAToFileOffset(rva); 454 size_t offset;
437 if (file_offset == kNoFileOffset) 455
456 if (!RVAToFileOffset(rva, &offset)) {
438 return false; 457 return false;
458 }
439 459
440 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 460 for (int section_id = 0;
441 ++section_id) { 461 section_id < SectionHeaderCount();
442 const Elf32_Shdr* section_header = SectionHeader(section_id); 462 section_id++) {
443 463
444 if (file_offset >= section_header->sh_offset && 464 const Elf32_Shdr *section_header = SectionHeader(section_id);
445 file_offset < (section_header->sh_offset + section_header->sh_size)) { 465
466 if (offset >= section_header->sh_offset &&
467 offset < (section_header->sh_offset + section_header->sh_size)) {
446 switch (section_header->sh_type) { 468 switch (section_header->sh_type) {
447 case SHT_REL: // Falls through. 469 case SHT_REL:
470 // Fall-through
448 case SHT_PROGBITS: 471 case SHT_PROGBITS:
449 return true; 472 return true;
450 } 473 }
451 } 474 }
452 } 475 }
453 476
454 return false; 477 return false;
455 } 478 }
456 479
457 CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() { 480 CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
481
458 rel32_locations_.clear(); 482 rel32_locations_.clear();
459 483
460 // Loop through sections for relocation sections 484 // Loop through sections for relocation sections
461 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 485 for (int section_id = 0;
462 ++section_id) { 486 section_id < SectionHeaderCount();
463 const Elf32_Shdr* section_header = SectionHeader(section_id); 487 section_id++) {
464 488
465 // TODO(huangs): Add better checks to skip non-code sections. 489 const Elf32_Shdr *section_header = SectionHeader(section_id);
490
466 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0. 491 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
467 if (section_header->sh_type != SHT_PROGBITS || 492 if (section_header->sh_type != SHT_PROGBITS ||
468 section_header->sh_addr == 0) 493 section_header->sh_addr == 0)
469 continue; 494 continue;
470 495
471 if (!ParseRel32RelocsFromSection(section_header)) 496 if (!ParseRel32RelocsFromSection(section_header))
472 return false; 497 return false;
473 } 498 }
474 499
475 std::sort(rel32_locations_.begin(), 500 std::sort(rel32_locations_.begin(),
476 rel32_locations_.end(), 501 rel32_locations_.end(),
477 TypedRVA::IsLessThan); 502 TypedRVA::IsLessThan);
478 DCHECK(rel32_locations_.empty() || 503 DCHECK(rel32_locations_.empty() ||
479 rel32_locations_.back()->rva() != kUnassignedRVA); 504 rel32_locations_.back()->rva() != kUnassignedRVA);
480 return true; 505 return true;
481 } 506 }
482 507
483 } // namespace courgette 508 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698