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