blob: a9592626faca80fd28af8164456b2259c5b157a2 [file] [log] [blame]
[email protected]39ed9732013-06-20 10:17:531// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "courgette/disassembler_elf_32.h"
6
7#include <algorithm>
[email protected]39ed9732013-06-20 10:17:538
[email protected]39ed9732013-06-20 10:17:539#include "base/logging.h"
[email protected]39ed9732013-06-20 10:17:5310#include "courgette/assembly_program.h"
11#include "courgette/courgette.h"
[email protected]39ed9732013-06-20 10:17:5312
13namespace courgette {
14
huangs8cffb282016-04-09 19:43:5015namespace {
16
huangs691893002016-04-19 20:04:3317// Sorts |section_headers| by file offset and stores the resulting permutation
18// of section ids in |order|.
19std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder(
20 const std::vector<Elf32_Shdr>& section_headers) {
21 size_t size = section_headers.size();
22 std::vector<Elf32_Half> order(size);
23 for (size_t i = 0; i < size; ++i)
24 order[i] = static_cast<Elf32_Half>(i);
25
26 auto comp = [&](int idx1, int idx2) {
27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset;
huangs8cffb282016-04-09 19:43:5028 };
huangs691893002016-04-19 20:04:3329 std::stable_sort(order.begin(), order.end(), comp);
30 return order;
huangs8cffb282016-04-09 19:43:5031}
32
33} // namespace
34
[email protected]39ed9732013-06-20 10:17:5335DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
huangsdda11d062016-03-14 16:35:3936 : Disassembler(start, length),
37 header_(nullptr),
huangsdda11d062016-03-14 16:35:3938 section_header_table_size_(0),
39 program_header_table_(nullptr),
40 program_header_table_size_(0),
41 default_string_section_(nullptr) {
42}
43
44RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
45 // File offsets can be 64-bit values, but we are dealing with 32-bit
46 // executables and so only need to support 32-bit file sizes.
47 uint32_t offset32 = static_cast<uint32_t>(offset);
48
huangs691893002016-04-19 20:04:3349 // Visit section headers ordered by file offset.
50 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:3951 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
56 Elf32_Off section_begin = section_header->sh_offset;
57 Elf32_Off section_end = section_begin + section_header->sh_size;
58
59 if (offset32 >= section_begin && offset32 < section_end) {
60 return section_header->sh_addr + (offset32 - section_begin);
61 }
62 }
63
64 return 0;
65}
66
67FileOffset DisassemblerElf32::RVAToFileOffset(RVA rva) const {
68 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
69 ++section_id) {
70 const Elf32_Shdr* section_header = SectionHeader(section_id);
71 // These can appear to have a size in the file, but don't.
72 if (section_header->sh_type == SHT_NOBITS)
73 continue;
74 Elf32_Addr begin = section_header->sh_addr;
75 Elf32_Addr end = begin + section_header->sh_size;
76
77 if (rva >= begin && rva < end)
78 return section_header->sh_offset + (rva - begin);
79 }
80 return kNoFileOffset;
[email protected]39ed9732013-06-20 10:17:5381}
82
huangsf940a8c92016-03-23 20:40:3583RVA DisassemblerElf32::PointerToTargetRVA(const uint8_t* p) const {
84 // TODO(huangs): Add check (e.g., IsValidTargetRVA(), but more efficient).
85 return Read32LittleEndian(p);
86}
87
[email protected]39ed9732013-06-20 10:17:5388bool DisassemblerElf32::ParseHeader() {
89 if (length() < sizeof(Elf32_Ehdr))
90 return Bad("Too small");
91
huangsdda11d062016-03-14 16:35:3992 header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
[email protected]39ed9732013-06-20 10:17:5393
huangsdda11d062016-03-14 16:35:3994 // Have magic for ELF header?
[email protected]39ed9732013-06-20 10:17:5395 if (header_->e_ident[0] != 0x7f ||
96 header_->e_ident[1] != 'E' ||
97 header_->e_ident[2] != 'L' ||
98 header_->e_ident[3] != 'F')
99 return Bad("No Magic Number");
100
101 if (header_->e_type != ET_EXEC &&
102 header_->e_type != ET_DYN)
103 return Bad("Not an executable file or shared library");
104
105 if (header_->e_machine != ElfEM())
106 return Bad("Not a supported architecture");
107
108 if (header_->e_version != 1)
109 return Bad("Unknown file version");
110
111 if (header_->e_shentsize != sizeof(Elf32_Shdr))
112 return Bad("Unexpected section header size");
113
halyavinc9de6f72015-03-24 15:40:12114 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
115 return Bad("Out of bounds section header table");
[email protected]39ed9732013-06-20 10:17:53116
huangs691893002016-04-19 20:04:33117 // Extract |section_header_table_|, ordered by section id.
huangs8cffb282016-04-09 19:43:50118 const Elf32_Shdr* section_header_table_raw =
119 reinterpret_cast<const Elf32_Shdr*>(
120 FileOffsetToPointer(header_->e_shoff));
[email protected]39ed9732013-06-20 10:17:53121 section_header_table_size_ = header_->e_shnum;
huangs691893002016-04-19 20:04:33122 section_header_table_.assign(section_header_table_raw,
123 section_header_table_raw + section_header_table_size_);
124
huangs16f01e02016-04-21 19:38:38125 // TODO(huangs): Validate offsets of all section headers.
126
huangs691893002016-04-19 20:04:33127 section_header_file_offset_order_ =
128 GetSectionHeaderFileOffsetOrder(section_header_table_);
[email protected]39ed9732013-06-20 10:17:53129
halyavinc9de6f72015-03-24 15:40:12130 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
131 return Bad("Out of bounds program header table");
[email protected]39ed9732013-06-20 10:17:53132
huangsdda11d062016-03-14 16:35:39133 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
134 FileOffsetToPointer(header_->e_phoff));
[email protected]39ed9732013-06-20 10:17:53135 program_header_table_size_ = header_->e_phnum;
136
huangs16f01e02016-04-21 19:38:38137 Elf32_Half string_section_id = header_->e_shstrndx;
138 if (string_section_id >= header_->e_shnum)
halyavinc9de6f72015-03-24 15:40:12139 return Bad("Out of bounds string section index");
[email protected]39ed9732013-06-20 10:17:53140
huangs16f01e02016-04-21 19:38:38141 default_string_section_ =
142 reinterpret_cast<const char*>(SectionBody(string_section_id));
143 default_string_section_size_ = SectionHeader(string_section_id)->sh_size;
144 // String section may be empty. If nonempty, then last byte must be null.
145 if (default_string_section_size_ > 0) {
146 if (default_string_section_[default_string_section_size_ - 1] != '\0')
147 return Bad("String section does not terminate");
148 }
[email protected]39ed9732013-06-20 10:17:53149
huangsdda11d062016-03-14 16:35:39150 if (!UpdateLength())
halyavinc9de6f72015-03-24 15:40:12151 return Bad("Out of bounds section or segment");
[email protected]39ed9732013-06-20 10:17:53152
153 return Good();
154}
155
156bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
157 if (!ok())
158 return false;
159
160 // The Image Base is always 0 for ELF Executables
161 target->set_image_base(0);
162
163 if (!ParseAbs32Relocs())
164 return false;
165
166 if (!ParseRel32RelocsFromSections())
167 return false;
168
169 if (!ParseFile(target))
170 return false;
171
172 target->DefaultAssignIndexes();
[email protected]39ed9732013-06-20 10:17:53173 return true;
174}
175
halyavinc9de6f72015-03-24 15:40:12176bool DisassemblerElf32::UpdateLength() {
177 Elf32_Off result = 0;
[email protected]39ed9732013-06-20 10:17:53178
179 // Find the end of the last section
huangsdda11d062016-03-14 16:35:39180 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
181 ++section_id) {
182 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53183
184 if (section_header->sh_type == SHT_NOBITS)
185 continue;
186
halyavinc9de6f72015-03-24 15:40:12187 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
188 return false;
[email protected]39ed9732013-06-20 10:17:53189
halyavinc9de6f72015-03-24 15:40:12190 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
191 result = std::max(result, section_end);
[email protected]39ed9732013-06-20 10:17:53192 }
193
194 // Find the end of the last segment
huangsdda11d062016-03-14 16:35:39195 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
196 ++segment_id) {
197 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53198
halyavinc9de6f72015-03-24 15:40:12199 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
200 return false;
[email protected]39ed9732013-06-20 10:17:53201
halyavinc9de6f72015-03-24 15:40:12202 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
203 result = std::max(result, segment_end);
[email protected]39ed9732013-06-20 10:17:53204 }
205
huangsdda11d062016-03-14 16:35:39206 Elf32_Off section_table_end =
207 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr));
halyavinc9de6f72015-03-24 15:40:12208 result = std::max(result, section_table_end);
[email protected]39ed9732013-06-20 10:17:53209
huangsdda11d062016-03-14 16:35:39210 Elf32_Off segment_table_end =
211 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr));
halyavinc9de6f72015-03-24 15:40:12212 result = std::max(result, segment_table_end);
[email protected]39ed9732013-06-20 10:17:53213
halyavinc9de6f72015-03-24 15:40:12214 ReduceLength(result);
215 return true;
[email protected]39ed9732013-06-20 10:17:53216}
217
huangs16f01e02016-04-21 19:38:38218CheckBool DisassemblerElf32::SectionName(const Elf32_Shdr& shdr,
219 std::string* name) const {
220 DCHECK(name);
221 size_t string_pos = shdr.sh_name;
222 if (string_pos == 0) {
223 // Empty string by convention. Valid even if string section is empty.
224 name->clear();
225 } else {
226 if (string_pos >= default_string_section_size_)
227 return false;
228 // Safe because string section must terminate with null.
229 *name = default_string_section_ + string_pos;
230 }
231 return true;
232}
233
huangsdda11d062016-03-14 16:35:39234CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
huangsbb4b8a92016-01-19 22:09:03235 if (rva == kUnassignedRVA)
236 return false;
[email protected]39ed9732013-06-20 10:17:53237
238 // It's valid if it's contained in any program segment
huangsdda11d062016-03-14 16:35:39239 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
240 ++segment_id) {
241 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53242
243 if (segment_header->p_type != PT_LOAD)
244 continue;
245
246 Elf32_Addr begin = segment_header->p_vaddr;
247 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
248
249 if (rva >= begin && rva < end)
250 return true;
251 }
252
253 return false;
254}
255
huangsdda11d062016-03-14 16:35:39256CheckBool DisassemblerElf32::RVAsToFileOffsets(
257 const std::vector<RVA>& rvas,
258 std::vector<FileOffset>* file_offsets) {
259 file_offsets->clear();
260 for (RVA rva : rvas) {
261 FileOffset file_offset = RVAToFileOffset(rva);
262 if (file_offset == kNoFileOffset)
scottmg4a95ca52016-03-12 23:54:56263 return false;
huangsdda11d062016-03-14 16:35:39264 file_offsets->push_back(file_offset);
scottmg4a95ca52016-03-12 23:54:56265 }
[email protected]39ed9732013-06-20 10:17:53266 return true;
267}
268
huangsdda11d062016-03-14 16:35:39269CheckBool DisassemblerElf32::RVAsToFileOffsets(
270 ScopedVector<TypedRVA>* typed_rvas) {
271 for (TypedRVA* typed_rva : *typed_rvas) {
272 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
273 if (file_offset == kNoFileOffset)
[email protected]144c8e92013-07-23 21:18:19274 return false;
huangsdda11d062016-03-14 16:35:39275 typed_rva->set_file_offset(file_offset);
[email protected]144c8e92013-07-23 21:18:19276 }
[email protected]144c8e92013-07-23 21:18:19277 return true;
278}
279
[email protected]39ed9732013-06-20 10:17:53280CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
281 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39282 FileOffset file_offset = 0;
[email protected]39ed9732013-06-20 10:17:53283
huangsdda11d062016-03-14 16:35:39284 std::vector<FileOffset> abs_offsets;
[email protected]39ed9732013-06-20 10:17:53285
huangsdda11d062016-03-14 16:35:39286 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
[email protected]39ed9732013-06-20 10:17:53287 return false;
288
huangsdda11d062016-03-14 16:35:39289 if (!RVAsToFileOffsets(&rel32_locations_))
[email protected]39ed9732013-06-20 10:17:53290 return false;
291
huangsdda11d062016-03-14 16:35:39292 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin();
[email protected]144c8e92013-07-23 21:18:19293 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin();
[email protected]39ed9732013-06-20 10:17:53294
huangsdda11d062016-03-14 16:35:39295 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end();
[email protected]144c8e92013-07-23 21:18:19296 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end();
[email protected]39ed9732013-06-20 10:17:53297
huangs691893002016-04-19 20:04:33298 // Visit section headers ordered by file offset.
299 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:39300 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53301
Will Harris3e6fa972015-03-02 21:14:25302 if (section_header->sh_type == SHT_NOBITS)
303 continue;
304
huangsdda11d062016-03-14 16:35:39305 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program))
[email protected]39ed9732013-06-20 10:17:53306 return false;
huangsdda11d062016-03-14 16:35:39307
[email protected]39ed9732013-06-20 10:17:53308 file_offset = section_header->sh_offset;
309
310 switch (section_header->sh_type) {
311 case SHT_REL:
312 if (!ParseRelocationSection(section_header, program))
313 return false;
314 file_offset = section_header->sh_offset + section_header->sh_size;
315 break;
316 case SHT_PROGBITS:
317 if (!ParseProgbitsSection(section_header,
huangsdda11d062016-03-14 16:35:39318 &current_abs_offset,
319 end_abs_offset,
320 &current_rel,
321 end_rel,
322 program)) {
[email protected]39ed9732013-06-20 10:17:53323 return false;
huangsdda11d062016-03-14 16:35:39324 }
[email protected]39ed9732013-06-20 10:17:53325 file_offset = section_header->sh_offset + section_header->sh_size;
326 break;
[email protected]39ed9732013-06-20 10:17:53327 case SHT_INIT_ARRAY:
328 // Fall through
329 case SHT_FINI_ARRAY:
330 while (current_abs_offset != end_abs_offset &&
331 *current_abs_offset >= section_header->sh_offset &&
332 *current_abs_offset <
huangsdda11d062016-03-14 16:35:39333 section_header->sh_offset + section_header->sh_size) {
[email protected]39ed9732013-06-20 10:17:53334 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
huangsdda11d062016-03-14 16:35:39335 VLOG(1) << "Skipping relocation entry for unsupported section: "
336 << section_header->sh_type;
337 ++current_abs_offset;
[email protected]39ed9732013-06-20 10:17:53338 }
339 break;
340 default:
341 if (current_abs_offset != end_abs_offset &&
huangsdda11d062016-03-14 16:35:39342 *current_abs_offset >= section_header->sh_offset &&
343 *current_abs_offset <
344 section_header->sh_offset + section_header->sh_size) {
345 VLOG(1) << "Relocation address in unrecognized ELF section: "
346 << section_header->sh_type;
347 }
348 break;
[email protected]39ed9732013-06-20 10:17:53349 }
350 }
351
352 // Rest of the file past the last section
huangsdda11d062016-03-14 16:35:39353 if (!ParseSimpleRegion(file_offset, length(), program))
[email protected]39ed9732013-06-20 10:17:53354 return false;
355
356 // Make certain we consume all of the relocations as expected
357 return (current_abs_offset == end_abs_offset);
358}
359
360CheckBool DisassemblerElf32::ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39361 const Elf32_Shdr* section_header,
362 std::vector<FileOffset>::iterator* current_abs_offset,
363 std::vector<FileOffset>::iterator end_abs_offset,
[email protected]144c8e92013-07-23 21:18:19364 ScopedVector<TypedRVA>::iterator* current_rel,
365 ScopedVector<TypedRVA>::iterator end_rel,
[email protected]39ed9732013-06-20 10:17:53366 AssemblyProgram* program) {
[email protected]39ed9732013-06-20 10:17:53367 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39368 FileOffset file_offset = section_header->sh_offset;
369 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
[email protected]39ed9732013-06-20 10:17:53370
371 Elf32_Addr origin = section_header->sh_addr;
huangsdda11d062016-03-14 16:35:39372 FileOffset origin_offset = section_header->sh_offset;
[email protected]39ed9732013-06-20 10:17:53373 if (!program->EmitOriginInstruction(origin))
374 return false;
375
376 while (file_offset < section_end) {
[email protected]39ed9732013-06-20 10:17:53377 if (*current_abs_offset != end_abs_offset &&
378 file_offset > **current_abs_offset)
379 return false;
380
[email protected]144c8e92013-07-23 21:18:19381 while (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39382 file_offset > (**current_rel)->file_offset()) {
383 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53384 }
385
huangsdda11d062016-03-14 16:35:39386 FileOffset next_relocation = section_end;
[email protected]39ed9732013-06-20 10:17:53387
388 if (*current_abs_offset != end_abs_offset &&
389 next_relocation > **current_abs_offset)
390 next_relocation = **current_abs_offset;
391
392 // Rel offsets are heuristically derived, and might (incorrectly) overlap
393 // an Abs value, or the end of the section, so +3 to make sure there is
394 // room for the full 4 byte value.
[email protected]144c8e92013-07-23 21:18:19395 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39396 next_relocation > ((**current_rel)->file_offset() + 3))
397 next_relocation = (**current_rel)->file_offset();
[email protected]39ed9732013-06-20 10:17:53398
399 if (next_relocation > file_offset) {
400 if (!ParseSimpleRegion(file_offset, next_relocation, program))
401 return false;
402
403 file_offset = next_relocation;
404 continue;
405 }
406
407 if (*current_abs_offset != end_abs_offset &&
408 file_offset == **current_abs_offset) {
huangsf940a8c92016-03-23 20:40:35409 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
410 DCHECK_NE(kNoRVA, target_rva);
[email protected]39ed9732013-06-20 10:17:53411
412 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
413 return false;
414 file_offset += sizeof(RVA);
huangsdda11d062016-03-14 16:35:39415 ++(*current_abs_offset);
[email protected]39ed9732013-06-20 10:17:53416 continue;
417 }
418
[email protected]144c8e92013-07-23 21:18:19419 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39420 file_offset == (**current_rel)->file_offset()) {
aviab98dcc92015-12-21 19:35:33421 uint32_t relative_target = (**current_rel)->relative_target();
[email protected]39ed9732013-06-20 10:17:53422 // This cast is for 64 bit systems, and is only safe because we
423 // are working on 32 bit executables.
424 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
[email protected]144c8e92013-07-23 21:18:19425 relative_target);
[email protected]39ed9732013-06-20 10:17:53426
huangsdda11d062016-03-14 16:35:39427 if (!(**current_rel)->EmitInstruction(program, target_rva))
[email protected]39ed9732013-06-20 10:17:53428 return false;
[email protected]2b637b62013-08-01 00:11:24429 file_offset += (**current_rel)->op_size();
huangsdda11d062016-03-14 16:35:39430 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53431 continue;
432 }
433 }
434
435 // Rest of the section (if any)
436 return ParseSimpleRegion(file_offset, section_end, program);
437}
438
huangsdda11d062016-03-14 16:35:39439CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset,
440 FileOffset end_file_offset,
441 AssemblyProgram* program) {
[email protected]c092858a2013-08-13 00:46:30442 // Callers don't guarantee start < end
huangsdda11d062016-03-14 16:35:39443 if (start_file_offset >= end_file_offset)
444 return true;
[email protected]39ed9732013-06-20 10:17:53445
pkasting8e3a26a2014-10-03 18:52:29446 const size_t len = end_file_offset - start_file_offset;
[email protected]c092858a2013-08-13 00:46:30447
huangsdda11d062016-03-14 16:35:39448 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
449 len)) {
[email protected]c092858a2013-08-13 00:46:30450 return false;
huangsdda11d062016-03-14 16:35:39451 }
[email protected]39ed9732013-06-20 10:17:53452
453 return true;
454}
455
456CheckBool DisassemblerElf32::ParseAbs32Relocs() {
457 abs32_locations_.clear();
458
459 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39460 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
461 ++section_id) {
462 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53463
464 if (section_header->sh_type == SHT_REL) {
huangsdda11d062016-03-14 16:35:39465 const Elf32_Rel* relocs_table =
466 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id));
[email protected]39ed9732013-06-20 10:17:53467
468 int relocs_table_count = section_header->sh_size /
469 section_header->sh_entsize;
470
471 // Elf32_Word relocation_section_id = section_header->sh_info;
472
473 // Loop through relocation objects in the relocation section
huangsdda11d062016-03-14 16:35:39474 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) {
[email protected]39ed9732013-06-20 10:17:53475 RVA rva;
476
477 // Quite a few of these conversions fail, and we simply skip
478 // them, that's okay.
[email protected]a8e80412013-07-18 22:07:53479 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
[email protected]39ed9732013-06-20 10:17:53480 abs32_locations_.push_back(rva);
481 }
482 }
483 }
484
485 std::sort(abs32_locations_.begin(), abs32_locations_.end());
huangsbb4b8a92016-01-19 22:09:03486 DCHECK(abs32_locations_.empty() ||
487 abs32_locations_.back() != kUnassignedRVA);
[email protected]39ed9732013-06-20 10:17:53488 return true;
489}
490
[email protected]a8e80412013-07-18 22:07:53491CheckBool DisassemblerElf32::CheckSection(RVA rva) {
huangsdda11d062016-03-14 16:35:39492 FileOffset file_offset = RVAToFileOffset(rva);
493 if (file_offset == kNoFileOffset)
[email protected]a8e80412013-07-18 22:07:53494 return false;
[email protected]a8e80412013-07-18 22:07:53495
huangsdda11d062016-03-14 16:35:39496 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
497 ++section_id) {
498 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]a8e80412013-07-18 22:07:53499
huangsdda11d062016-03-14 16:35:39500 if (file_offset >= section_header->sh_offset &&
501 file_offset < (section_header->sh_offset + section_header->sh_size)) {
[email protected]a8e80412013-07-18 22:07:53502 switch (section_header->sh_type) {
huangsdda11d062016-03-14 16:35:39503 case SHT_REL: // Falls through.
[email protected]a8e80412013-07-18 22:07:53504 case SHT_PROGBITS:
505 return true;
506 }
507 }
508 }
509
510 return false;
511}
512
[email protected]39ed9732013-06-20 10:17:53513CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
[email protected]39ed9732013-06-20 10:17:53514 rel32_locations_.clear();
515
516 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39517 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
518 ++section_id) {
519 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53520
huangsdda11d062016-03-14 16:35:39521 // TODO(huangs): Add better checks to skip non-code sections.
huangs7ec152c2016-02-04 22:26:43522 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
523 if (section_header->sh_type != SHT_PROGBITS ||
524 section_header->sh_addr == 0)
[email protected]39ed9732013-06-20 10:17:53525 continue;
526
527 if (!ParseRel32RelocsFromSection(section_header))
528 return false;
529 }
530
[email protected]144c8e92013-07-23 21:18:19531 std::sort(rel32_locations_.begin(),
532 rel32_locations_.end(),
533 TypedRVA::IsLessThan);
huangsbb4b8a92016-01-19 22:09:03534 DCHECK(rel32_locations_.empty() ||
535 rel32_locations_.back()->rva() != kUnassignedRVA);
[email protected]39ed9732013-06-20 10:17:53536 return true;
537}
538
539} // namespace courgette