| 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" |
| 11 #include "courgette/courgette.h" | 11 #include "courgette/courgette.h" |
| 12 | 12 |
| 13 namespace courgette { | 13 namespace courgette { |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 // Initializes |section_header_table| by copying |section_header_table_size| | 17 // Sorts |section_headers| by file offset and stores the resulting permutation |
| 18 // entries from |section_header_table_raw|, and sorting by |sh_offset|. | 18 // of section ids in |order|. |
| 19 void SortSectionHeader(const Elf32_Shdr* section_header_table_raw, | 19 std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder( |
| 20 Elf32_Half section_header_table_size, | 20 const std::vector<Elf32_Shdr>& section_headers) { |
| 21 std::vector<Elf32_Shdr>* section_header_table) { | 21 size_t size = section_headers.size(); |
| 22 section_header_table->assign(section_header_table_raw, | 22 std::vector<Elf32_Half> order(size); |
| 23 section_header_table_raw + section_header_table_size); | 23 for (size_t i = 0; i < size; ++i) |
| 24 auto comp = [](const Elf32_Shdr& header1, const Elf32_Shdr& header2) { | 24 order[i] = static_cast<Elf32_Half>(i); |
| 25 return header1.sh_offset < header2.sh_offset; | 25 |
| 26 auto comp = [&](int idx1, int idx2) { |
| 27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset; |
| 26 }; | 28 }; |
| 27 std::stable_sort( | 29 std::stable_sort(order.begin(), order.end(), comp); |
| 28 section_header_table->begin(), section_header_table->end(), comp); | 30 return order; |
| 29 } | 31 } |
| 30 | 32 |
| 31 } // namespace | 33 } // namespace |
| 32 | 34 |
| 33 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) | 35 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) |
| 34 : Disassembler(start, length), | 36 : Disassembler(start, length), |
| 35 header_(nullptr), | 37 header_(nullptr), |
| 36 section_header_table_size_(0), | 38 section_header_table_size_(0), |
| 37 program_header_table_(nullptr), | 39 program_header_table_(nullptr), |
| 38 program_header_table_size_(0), | 40 program_header_table_size_(0), |
| 39 default_string_section_(nullptr) { | 41 default_string_section_(nullptr) { |
| 40 } | 42 } |
| 41 | 43 |
| 42 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { | 44 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { |
| 43 // File offsets can be 64-bit values, but we are dealing with 32-bit | 45 // File offsets can be 64-bit values, but we are dealing with 32-bit |
| 44 // executables and so only need to support 32-bit file sizes. | 46 // executables and so only need to support 32-bit file sizes. |
| 45 uint32_t offset32 = static_cast<uint32_t>(offset); | 47 uint32_t offset32 = static_cast<uint32_t>(offset); |
| 46 | 48 |
| 47 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); | 49 // Visit section headers ordered by file offset. |
| 48 ++section_id) { | 50 for (Elf32_Half section_id : section_header_file_offset_order_) { |
| 49 const Elf32_Shdr* section_header = SectionHeader(section_id); | 51 const Elf32_Shdr* section_header = SectionHeader(section_id); |
| 50 // These can appear to have a size in the file, but don't. | 52 // These can appear to have a size in the file, but don't. |
| 51 if (section_header->sh_type == SHT_NOBITS) | 53 if (section_header->sh_type == SHT_NOBITS) |
| 52 continue; | 54 continue; |
| 53 | 55 |
| 54 Elf32_Off section_begin = section_header->sh_offset; | 56 Elf32_Off section_begin = section_header->sh_offset; |
| 55 Elf32_Off section_end = section_begin + section_header->sh_size; | 57 Elf32_Off section_end = section_begin + section_header->sh_size; |
| 56 | 58 |
| 57 if (offset32 >= section_begin && offset32 < section_end) { | 59 if (offset32 >= section_begin && offset32 < section_end) { |
| 58 return section_header->sh_addr + (offset32 - section_begin); | 60 return section_header->sh_addr + (offset32 - section_begin); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 107 |
| 106 if (header_->e_version != 1) | 108 if (header_->e_version != 1) |
| 107 return Bad("Unknown file version"); | 109 return Bad("Unknown file version"); |
| 108 | 110 |
| 109 if (header_->e_shentsize != sizeof(Elf32_Shdr)) | 111 if (header_->e_shentsize != sizeof(Elf32_Shdr)) |
| 110 return Bad("Unexpected section header size"); | 112 return Bad("Unexpected section header size"); |
| 111 | 113 |
| 112 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr))) | 114 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr))) |
| 113 return Bad("Out of bounds section header table"); | 115 return Bad("Out of bounds section header table"); |
| 114 | 116 |
| 117 // Extract |section_header_table_|, ordered by section id. |
| 115 const Elf32_Shdr* section_header_table_raw = | 118 const Elf32_Shdr* section_header_table_raw = |
| 116 reinterpret_cast<const Elf32_Shdr*>( | 119 reinterpret_cast<const Elf32_Shdr*>( |
| 117 FileOffsetToPointer(header_->e_shoff)); | 120 FileOffsetToPointer(header_->e_shoff)); |
| 118 section_header_table_size_ = header_->e_shnum; | 121 section_header_table_size_ = header_->e_shnum; |
| 119 SortSectionHeader(section_header_table_raw, section_header_table_size_, | 122 section_header_table_.assign(section_header_table_raw, |
| 120 §ion_header_table_); | 123 section_header_table_raw + section_header_table_size_); |
| 124 |
| 125 section_header_file_offset_order_ = |
| 126 GetSectionHeaderFileOffsetOrder(section_header_table_); |
| 121 | 127 |
| 122 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr))) | 128 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr))) |
| 123 return Bad("Out of bounds program header table"); | 129 return Bad("Out of bounds program header table"); |
| 124 | 130 |
| 125 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>( | 131 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>( |
| 126 FileOffsetToPointer(header_->e_phoff)); | 132 FileOffsetToPointer(header_->e_phoff)); |
| 127 program_header_table_size_ = header_->e_phnum; | 133 program_header_table_size_ = header_->e_phnum; |
| 128 | 134 |
| 129 if (header_->e_shstrndx >= header_->e_shnum) | 135 if (header_->e_shstrndx >= header_->e_shnum) |
| 130 return Bad("Out of bounds string section index"); | 136 return Bad("Out of bounds string section index"); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 | 263 |
| 258 if (!RVAsToFileOffsets(&rel32_locations_)) | 264 if (!RVAsToFileOffsets(&rel32_locations_)) |
| 259 return false; | 265 return false; |
| 260 | 266 |
| 261 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin(); | 267 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin(); |
| 262 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin(); | 268 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin(); |
| 263 | 269 |
| 264 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end(); | 270 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end(); |
| 265 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end(); | 271 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end(); |
| 266 | 272 |
| 267 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); | 273 // Visit section headers ordered by file offset. |
| 268 ++section_id) { | 274 for (Elf32_Half section_id : section_header_file_offset_order_) { |
| 269 const Elf32_Shdr* section_header = SectionHeader(section_id); | 275 const Elf32_Shdr* section_header = SectionHeader(section_id); |
| 270 | 276 |
| 271 if (section_header->sh_type == SHT_NOBITS) | 277 if (section_header->sh_type == SHT_NOBITS) |
| 272 continue; | 278 continue; |
| 273 | 279 |
| 274 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program)) | 280 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program)) |
| 275 return false; | 281 return false; |
| 276 | 282 |
| 277 file_offset = section_header->sh_offset; | 283 file_offset = section_header->sh_offset; |
| 278 | 284 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 | 505 |
| 500 std::sort(rel32_locations_.begin(), | 506 std::sort(rel32_locations_.begin(), |
| 501 rel32_locations_.end(), | 507 rel32_locations_.end(), |
| 502 TypedRVA::IsLessThan); | 508 TypedRVA::IsLessThan); |
| 503 DCHECK(rel32_locations_.empty() || | 509 DCHECK(rel32_locations_.empty() || |
| 504 rel32_locations_.back()->rva() != kUnassignedRVA); | 510 rel32_locations_.back()->rva() != kUnassignedRVA); |
| 505 return true; | 511 return true; |
| 506 } | 512 } |
| 507 | 513 |
| 508 } // namespace courgette | 514 } // namespace courgette |
| OLD | NEW |