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 <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 | 47 |
48 if (header_->e_machine != ElfEM()) | 48 if (header_->e_machine != ElfEM()) |
49 return Bad("Not a supported architecture"); | 49 return Bad("Not a supported architecture"); |
50 | 50 |
51 if (header_->e_version != 1) | 51 if (header_->e_version != 1) |
52 return Bad("Unknown file version"); | 52 return Bad("Unknown file version"); |
53 | 53 |
54 if (header_->e_shentsize != sizeof(Elf32_Shdr)) | 54 if (header_->e_shentsize != sizeof(Elf32_Shdr)) |
55 return Bad("Unexpected section header size"); | 55 return Bad("Unexpected section header size"); |
56 | 56 |
57 if (header_->e_shoff >= length()) | 57 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr))) |
58 return Bad("Out of bounds section header table offset"); | 58 return Bad("Out of bounds section header table"); |
59 | 59 |
60 section_header_table_ = (Elf32_Shdr *)OffsetToPointer(header_->e_shoff); | 60 section_header_table_ = (Elf32_Shdr *)OffsetToPointer(header_->e_shoff); |
61 section_header_table_size_ = header_->e_shnum; | 61 section_header_table_size_ = header_->e_shnum; |
62 | 62 |
63 if ((header_->e_shoff + header_->e_shnum ) >= length()) | 63 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr))) |
64 return Bad("Out of bounds section header table"); | 64 return Bad("Out of bounds program header table"); |
65 | |
66 if (header_->e_phoff >= length()) | |
67 return Bad("Out of bounds program header table offset"); | |
68 | 65 |
69 program_header_table_ = (Elf32_Phdr *)OffsetToPointer(header_->e_phoff); | 66 program_header_table_ = (Elf32_Phdr *)OffsetToPointer(header_->e_phoff); |
70 program_header_table_size_ = header_->e_phnum; | 67 program_header_table_size_ = header_->e_phnum; |
71 | 68 |
72 if ((header_->e_phoff + header_->e_phnum) >= length()) | 69 if (header_->e_shstrndx >= header_->e_shnum) |
73 return Bad("Out of bounds program header table"); | 70 return Bad("Out of bounds string section index"); |
74 | 71 |
75 default_string_section_ = (const char *)SectionBody((int)header_->e_shstrndx); | 72 default_string_section_ = (const char *)SectionBody((int)header_->e_shstrndx); |
76 | 73 |
77 ReduceLength(DiscoverLength()); | 74 if (!UpdateLength()) { |
| 75 return Bad("Out of bounds section or segment"); |
| 76 } |
78 | 77 |
79 return Good(); | 78 return Good(); |
80 } | 79 } |
81 | 80 |
82 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { | 81 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { |
83 if (!ok()) | 82 if (!ok()) |
84 return false; | 83 return false; |
85 | 84 |
86 // The Image Base is always 0 for ELF Executables | 85 // The Image Base is always 0 for ELF Executables |
87 target->set_image_base(0); | 86 target->set_image_base(0); |
88 | 87 |
89 if (!ParseAbs32Relocs()) | 88 if (!ParseAbs32Relocs()) |
90 return false; | 89 return false; |
91 | 90 |
92 if (!ParseRel32RelocsFromSections()) | 91 if (!ParseRel32RelocsFromSections()) |
93 return false; | 92 return false; |
94 | 93 |
95 if (!ParseFile(target)) | 94 if (!ParseFile(target)) |
96 return false; | 95 return false; |
97 | 96 |
98 target->DefaultAssignIndexes(); | 97 target->DefaultAssignIndexes(); |
99 | 98 |
100 return true; | 99 return true; |
101 } | 100 } |
102 | 101 |
103 uint32 DisassemblerElf32::DiscoverLength() { | 102 bool DisassemblerElf32::UpdateLength() { |
104 uint32 result = 0; | 103 Elf32_Off result = 0; |
105 | 104 |
106 // Find the end of the last section | 105 // Find the end of the last section |
107 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { | 106 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { |
108 const Elf32_Shdr *section_header = SectionHeader(section_id); | 107 const Elf32_Shdr *section_header = SectionHeader(section_id); |
109 | 108 |
110 if (section_header->sh_type == SHT_NOBITS) | 109 if (section_header->sh_type == SHT_NOBITS) |
111 continue; | 110 continue; |
112 | 111 |
113 uint32 section_end = section_header->sh_offset + section_header->sh_size; | 112 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1)) |
| 113 return false; |
114 | 114 |
115 if (section_end > result) | 115 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size; |
116 result = section_end; | 116 result = std::max(result, section_end); |
117 } | 117 } |
118 | 118 |
119 // Find the end of the last segment | 119 // Find the end of the last segment |
120 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { | 120 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { |
121 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); | 121 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); |
122 | 122 |
123 uint32 segment_end = segment_header->p_offset + segment_header->p_filesz; | 123 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1)) |
| 124 return false; |
124 | 125 |
125 if (segment_end > result) | 126 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz; |
126 result = segment_end; | 127 result = std::max(result, segment_end); |
127 } | 128 } |
128 | 129 |
129 uint32 section_table_end = header_->e_shoff + | 130 Elf32_Off section_table_end = header_->e_shoff + |
130 (header_->e_shnum * sizeof(Elf32_Shdr)); | 131 (header_->e_shnum * sizeof(Elf32_Shdr)); |
131 if (section_table_end > result) | 132 result = std::max(result, section_table_end); |
132 result = section_table_end; | |
133 | 133 |
134 uint32 segment_table_end = header_->e_phoff + | 134 Elf32_Off segment_table_end = header_->e_phoff + |
135 (header_->e_phnum * sizeof(Elf32_Phdr)); | 135 (header_->e_phnum * sizeof(Elf32_Phdr)); |
136 if (segment_table_end > result) | 136 result = std::max(result, segment_table_end); |
137 result = segment_table_end; | |
138 | 137 |
139 return result; | 138 ReduceLength(result); |
| 139 return true; |
140 } | 140 } |
141 | 141 |
142 CheckBool DisassemblerElf32::IsValidRVA(RVA rva) const { | 142 CheckBool DisassemblerElf32::IsValidRVA(RVA rva) const { |
143 | 143 |
144 // It's valid if it's contained in any program segment | 144 // It's valid if it's contained in any program segment |
145 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { | 145 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { |
146 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); | 146 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); |
147 | 147 |
148 if (segment_header->p_type != PT_LOAD) | 148 if (segment_header->p_type != PT_LOAD) |
149 continue; | 149 continue; |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 return false; | 494 return false; |
495 } | 495 } |
496 | 496 |
497 std::sort(rel32_locations_.begin(), | 497 std::sort(rel32_locations_.begin(), |
498 rel32_locations_.end(), | 498 rel32_locations_.end(), |
499 TypedRVA::IsLessThan); | 499 TypedRVA::IsLessThan); |
500 return true; | 500 return true; |
501 } | 501 } |
502 | 502 |
503 } // namespace courgette | 503 } // namespace courgette |
OLD | NEW |