OLD | NEW |
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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "courgette/assembly_program.h" | 10 #include "courgette/assembly_program.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 auto comp = [&](int idx1, int idx2) { | 26 auto comp = [&](int idx1, int idx2) { |
27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset; | 27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset; |
28 }; | 28 }; |
29 std::stable_sort(order.begin(), order.end(), comp); | 29 std::stable_sort(order.begin(), order.end(), comp); |
30 return order; | 30 return order; |
31 } | 31 } |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 | 34 |
| 35 DisassemblerElf32::Elf32RvaVisitor_Rel32::Elf32RvaVisitor_Rel32( |
| 36 const std::vector<TypedRVA*>& rva_locations) |
| 37 : VectorRvaVisitor<TypedRVA*>(rva_locations) { |
| 38 } |
| 39 |
| 40 RVA DisassemblerElf32::Elf32RvaVisitor_Rel32::Get() const { |
| 41 return (*it_)->rva() + (*it_)->relative_target(); |
| 42 } |
| 43 |
35 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) | 44 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) |
36 : Disassembler(start, length), | 45 : Disassembler(start, length), |
37 header_(nullptr), | 46 header_(nullptr), |
38 section_header_table_size_(0), | 47 section_header_table_size_(0), |
39 program_header_table_(nullptr), | 48 program_header_table_(nullptr), |
40 program_header_table_size_(0), | 49 program_header_table_size_(0), |
41 default_string_section_(nullptr) { | 50 default_string_section_(nullptr) { |
42 } | 51 } |
43 | 52 |
44 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { | 53 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { | 165 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { |
157 if (!ok()) | 166 if (!ok()) |
158 return false; | 167 return false; |
159 | 168 |
160 // The Image Base is always 0 for ELF Executables | 169 // The Image Base is always 0 for ELF Executables |
161 target->set_image_base(0); | 170 target->set_image_base(0); |
162 | 171 |
163 if (!ParseAbs32Relocs()) | 172 if (!ParseAbs32Relocs()) |
164 return false; | 173 return false; |
165 | 174 |
166 if (!ParseRel32RelocsFromSections()) | 175 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations. |
167 return false; | 176 return false; |
168 | 177 |
| 178 PrecomputeLabels(target); |
| 179 RemoveUnusedRel32Locations(target); |
| 180 |
169 if (!ParseFile(target)) | 181 if (!ParseFile(target)) |
170 return false; | 182 return false; |
171 | 183 |
| 184 // Finally sort rel32 locations. |
172 std::sort(rel32_locations_.begin(), | 185 std::sort(rel32_locations_.begin(), |
173 rel32_locations_.end(), | 186 rel32_locations_.end(), |
174 TypedRVA::IsLessThanByRVA); | 187 TypedRVA::IsLessThanByRVA); |
175 DCHECK(rel32_locations_.empty() || | 188 DCHECK(rel32_locations_.empty() || |
176 rel32_locations_.back()->rva() != kUnassignedRVA); | 189 rel32_locations_.back()->rva() != kUnassignedRVA); |
177 | 190 |
178 target->DefaultAssignIndexes(); | 191 target->DefaultAssignIndexes(); |
179 return true; | 192 return true; |
180 } | 193 } |
181 | 194 |
| 195 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const { |
| 196 if (rva == kUnassignedRVA) |
| 197 return false; |
| 198 |
| 199 // |rva| is valid if it's contained in any program segment. |
| 200 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount(); |
| 201 ++segment_id) { |
| 202 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id); |
| 203 |
| 204 if (segment_header->p_type != PT_LOAD) |
| 205 continue; |
| 206 |
| 207 Elf32_Addr begin = segment_header->p_vaddr; |
| 208 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz; |
| 209 |
| 210 if (rva >= begin && rva < end) |
| 211 return true; |
| 212 } |
| 213 |
| 214 return false; |
| 215 } |
| 216 |
182 bool DisassemblerElf32::UpdateLength() { | 217 bool DisassemblerElf32::UpdateLength() { |
183 Elf32_Off result = 0; | 218 Elf32_Off result = 0; |
184 | 219 |
185 // Find the end of the last section | 220 // Find the end of the last section |
186 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); | 221 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); |
187 ++section_id) { | 222 ++section_id) { |
188 const Elf32_Shdr* section_header = SectionHeader(section_id); | 223 const Elf32_Shdr* section_header = SectionHeader(section_id); |
189 | 224 |
190 if (section_header->sh_type == SHT_NOBITS) | 225 if (section_header->sh_type == SHT_NOBITS) |
191 continue; | 226 continue; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 name->clear(); | 265 name->clear(); |
231 } else { | 266 } else { |
232 if (string_pos >= default_string_section_size_) | 267 if (string_pos >= default_string_section_size_) |
233 return false; | 268 return false; |
234 // Safe because string section must terminate with null. | 269 // Safe because string section must terminate with null. |
235 *name = default_string_section_ + string_pos; | 270 *name = default_string_section_ + string_pos; |
236 } | 271 } |
237 return true; | 272 return true; |
238 } | 273 } |
239 | 274 |
240 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const { | |
241 if (rva == kUnassignedRVA) | |
242 return false; | |
243 | |
244 // It's valid if it's contained in any program segment | |
245 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount(); | |
246 ++segment_id) { | |
247 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id); | |
248 | |
249 if (segment_header->p_type != PT_LOAD) | |
250 continue; | |
251 | |
252 Elf32_Addr begin = segment_header->p_vaddr; | |
253 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz; | |
254 | |
255 if (rva >= begin && rva < end) | |
256 return true; | |
257 } | |
258 | |
259 return false; | |
260 } | |
261 | |
262 CheckBool DisassemblerElf32::RVAsToFileOffsets( | 275 CheckBool DisassemblerElf32::RVAsToFileOffsets( |
263 const std::vector<RVA>& rvas, | 276 const std::vector<RVA>& rvas, |
264 std::vector<FileOffset>* file_offsets) { | 277 std::vector<FileOffset>* file_offsets) { |
265 file_offsets->clear(); | 278 file_offsets->clear(); |
| 279 file_offsets->reserve(rvas.size()); |
266 for (RVA rva : rvas) { | 280 for (RVA rva : rvas) { |
267 FileOffset file_offset = RVAToFileOffset(rva); | 281 FileOffset file_offset = RVAToFileOffset(rva); |
268 if (file_offset == kNoFileOffset) | 282 if (file_offset == kNoFileOffset) |
269 return false; | 283 return false; |
270 file_offsets->push_back(file_offset); | 284 file_offsets->push_back(file_offset); |
271 } | 285 } |
272 return true; | 286 return true; |
273 } | 287 } |
274 | 288 |
275 CheckBool DisassemblerElf32::RVAsToFileOffsets( | 289 CheckBool DisassemblerElf32::RVAsToFileOffsets( |
276 ScopedVector<TypedRVA>* typed_rvas) { | 290 ScopedVector<TypedRVA>* typed_rvas) { |
277 for (TypedRVA* typed_rva : *typed_rvas) { | 291 for (TypedRVA* typed_rva : *typed_rvas) { |
278 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); | 292 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); |
279 if (file_offset == kNoFileOffset) | 293 if (file_offset == kNoFileOffset) |
280 return false; | 294 return false; |
281 typed_rva->set_file_offset(file_offset); | 295 typed_rva->set_file_offset(file_offset); |
282 } | 296 } |
283 return true; | 297 return true; |
284 } | 298 } |
285 | 299 |
| 300 RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() { |
| 301 return new RvaVisitor_Abs32(abs32_locations_, *this); |
| 302 } |
| 303 |
| 304 RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() { |
| 305 return new Elf32RvaVisitor_Rel32(rel32_locations_.get()); |
| 306 } |
| 307 |
| 308 void DisassemblerElf32::RemoveUnusedRel32Locations(AssemblyProgram* program) { |
| 309 auto cond = [program](const TypedRVA* typed_rva) -> bool { |
| 310 RVA target_rva = typed_rva->rva() + typed_rva->relative_target(); |
| 311 return program->FindRel32Label(target_rva) == nullptr; |
| 312 }; |
| 313 rel32_locations_.erase( |
| 314 std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond), |
| 315 rel32_locations_.end()); |
| 316 } |
| 317 |
286 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { | 318 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { |
287 // Walk all the bytes in the file, whether or not in a section. | 319 // Walk all the bytes in the file, whether or not in a section. |
288 FileOffset file_offset = 0; | 320 FileOffset file_offset = 0; |
289 | 321 |
290 std::vector<FileOffset> abs_offsets; | 322 std::vector<FileOffset> abs_offsets; |
291 | 323 |
292 // File parsing follows file offset order, and we visit abs32 and rel32 | 324 // File parsing follows file offset order, and we visit abs32 and rel32 |
293 // locations in lockstep. Therefore we need to extract and sort file offsets | 325 // locations in lockstep. Therefore we need to extract and sort file offsets |
294 // of all abs32 and rel32 locations. | 326 // of all abs32 and rel32 locations. |
295 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) | 327 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 447 |
416 file_offset = next_relocation; | 448 file_offset = next_relocation; |
417 continue; | 449 continue; |
418 } | 450 } |
419 | 451 |
420 if (*current_abs_offset != end_abs_offset && | 452 if (*current_abs_offset != end_abs_offset && |
421 file_offset == **current_abs_offset) { | 453 file_offset == **current_abs_offset) { |
422 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset)); | 454 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset)); |
423 DCHECK_NE(kNoRVA, target_rva); | 455 DCHECK_NE(kNoRVA, target_rva); |
424 | 456 |
425 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) | 457 Label* label = program->FindAbs32Label(target_rva); |
| 458 CHECK(label); |
| 459 if (!program->EmitAbs32(label)) |
426 return false; | 460 return false; |
427 file_offset += sizeof(RVA); | 461 file_offset += sizeof(RVA); |
428 ++(*current_abs_offset); | 462 ++(*current_abs_offset); |
429 continue; | 463 continue; |
430 } | 464 } |
431 | 465 |
432 if (*current_rel != end_rel && | 466 if (*current_rel != end_rel && |
433 file_offset == (**current_rel)->file_offset()) { | 467 file_offset == (**current_rel)->file_offset()) { |
434 uint32_t relative_target = (**current_rel)->relative_target(); | 468 uint32_t relative_target = (**current_rel)->relative_target(); |
| 469 CHECK_EQ(RVA(origin + (file_offset - origin_offset)), |
| 470 (**current_rel)->rva()); |
435 // This cast is for 64 bit systems, and is only safe because we | 471 // This cast is for 64 bit systems, and is only safe because we |
436 // are working on 32 bit executables. | 472 // are working on 32 bit executables. |
437 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + | 473 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + |
438 relative_target); | 474 relative_target); |
439 | 475 |
440 if (!(**current_rel)->EmitInstruction(program, target_rva)) | 476 Label* label = program->FindRel32Label(target_rva); |
| 477 CHECK(label); |
| 478 |
| 479 if (!(**current_rel)->EmitInstruction(program, label)) |
441 return false; | 480 return false; |
442 file_offset += (**current_rel)->op_size(); | 481 file_offset += (**current_rel)->op_size(); |
443 ++(*current_rel); | 482 ++(*current_rel); |
444 continue; | 483 continue; |
445 } | 484 } |
446 } | 485 } |
447 | 486 |
448 // Rest of the section (if any) | 487 // Rest of the section (if any) |
449 return ParseSimpleRegion(file_offset, section_end, program); | 488 return ParseSimpleRegion(file_offset, section_end, program); |
450 } | 489 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 if (!ParseRel32RelocsFromSection(section_header)) | 587 if (!ParseRel32RelocsFromSection(section_header)) |
549 return false; | 588 return false; |
550 } | 589 } |
551 if (!found_rel32) | 590 if (!found_rel32) |
552 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; | 591 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; |
553 | 592 |
554 return true; | 593 return true; |
555 } | 594 } |
556 | 595 |
557 } // namespace courgette | 596 } // namespace courgette |
OLD | NEW |