blob: febcdeabef504e2c540c9d65dde763fbb093b776 [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>
huangsc8037632016-05-19 18:16:408#include <iterator>
etiennep7d4e8ee2016-05-11 20:13:369#include <utility>
[email protected]39ed9732013-06-20 10:17:5310
[email protected]39ed9732013-06-20 10:17:5311#include "base/logging.h"
[email protected]39ed9732013-06-20 10:17:5312#include "courgette/assembly_program.h"
13#include "courgette/courgette.h"
[email protected]39ed9732013-06-20 10:17:5314
15namespace courgette {
16
huangs8cffb282016-04-09 19:43:5017namespace {
18
huangs691893002016-04-19 20:04:3319// Sorts |section_headers| by file offset and stores the resulting permutation
20// of section ids in |order|.
21std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder(
22 const std::vector<Elf32_Shdr>& section_headers) {
23 size_t size = section_headers.size();
24 std::vector<Elf32_Half> order(size);
25 for (size_t i = 0; i < size; ++i)
26 order[i] = static_cast<Elf32_Half>(i);
27
28 auto comp = [&](int idx1, int idx2) {
29 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset;
huangs8cffb282016-04-09 19:43:5030 };
huangs691893002016-04-19 20:04:3331 std::stable_sort(order.begin(), order.end(), comp);
32 return order;
huangs8cffb282016-04-09 19:43:5033}
34
35} // namespace
36
huangsc8037632016-05-19 18:16:4037DisassemblerElf32::Elf32RvaVisitor_Rel32::Elf32RvaVisitor_Rel32(
38 const std::vector<std::unique_ptr<TypedRVA>>& rva_locations)
39 : VectorRvaVisitor<std::unique_ptr<TypedRVA>>(rva_locations) {
40}
41
42RVA DisassemblerElf32::Elf32RvaVisitor_Rel32::Get() const {
43 return (*it_)->rva() + (*it_)->relative_target();
44}
45
[email protected]39ed9732013-06-20 10:17:5346DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
huangsdda11d062016-03-14 16:35:3947 : Disassembler(start, length),
48 header_(nullptr),
huangsdda11d062016-03-14 16:35:3949 section_header_table_size_(0),
50 program_header_table_(nullptr),
51 program_header_table_size_(0),
52 default_string_section_(nullptr) {
53}
54
55RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
56 // File offsets can be 64-bit values, but we are dealing with 32-bit
57 // executables and so only need to support 32-bit file sizes.
58 uint32_t offset32 = static_cast<uint32_t>(offset);
59
huangs691893002016-04-19 20:04:3360 // Visit section headers ordered by file offset.
61 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:3962 const Elf32_Shdr* section_header = SectionHeader(section_id);
63 // These can appear to have a size in the file, but don't.
64 if (section_header->sh_type == SHT_NOBITS)
65 continue;
66
67 Elf32_Off section_begin = section_header->sh_offset;
68 Elf32_Off section_end = section_begin + section_header->sh_size;
69
70 if (offset32 >= section_begin && offset32 < section_end) {
71 return section_header->sh_addr + (offset32 - section_begin);
72 }
73 }
74
75 return 0;
76}
77
78FileOffset DisassemblerElf32::RVAToFileOffset(RVA rva) const {
79 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
80 ++section_id) {
81 const Elf32_Shdr* section_header = SectionHeader(section_id);
82 // These can appear to have a size in the file, but don't.
83 if (section_header->sh_type == SHT_NOBITS)
84 continue;
85 Elf32_Addr begin = section_header->sh_addr;
86 Elf32_Addr end = begin + section_header->sh_size;
87
88 if (rva >= begin && rva < end)
89 return section_header->sh_offset + (rva - begin);
90 }
91 return kNoFileOffset;
[email protected]39ed9732013-06-20 10:17:5392}
93
huangsf940a8c92016-03-23 20:40:3594RVA DisassemblerElf32::PointerToTargetRVA(const uint8_t* p) const {
95 // TODO(huangs): Add check (e.g., IsValidTargetRVA(), but more efficient).
96 return Read32LittleEndian(p);
97}
98
[email protected]39ed9732013-06-20 10:17:5399bool DisassemblerElf32::ParseHeader() {
100 if (length() < sizeof(Elf32_Ehdr))
101 return Bad("Too small");
102
huangsdda11d062016-03-14 16:35:39103 header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
[email protected]39ed9732013-06-20 10:17:53104
huangsdda11d062016-03-14 16:35:39105 // Have magic for ELF header?
[email protected]39ed9732013-06-20 10:17:53106 if (header_->e_ident[0] != 0x7f ||
107 header_->e_ident[1] != 'E' ||
108 header_->e_ident[2] != 'L' ||
109 header_->e_ident[3] != 'F')
110 return Bad("No Magic Number");
111
112 if (header_->e_type != ET_EXEC &&
113 header_->e_type != ET_DYN)
114 return Bad("Not an executable file or shared library");
115
116 if (header_->e_machine != ElfEM())
117 return Bad("Not a supported architecture");
118
119 if (header_->e_version != 1)
120 return Bad("Unknown file version");
121
122 if (header_->e_shentsize != sizeof(Elf32_Shdr))
123 return Bad("Unexpected section header size");
124
halyavinc9de6f72015-03-24 15:40:12125 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
126 return Bad("Out of bounds section header table");
[email protected]39ed9732013-06-20 10:17:53127
huangs691893002016-04-19 20:04:33128 // Extract |section_header_table_|, ordered by section id.
huangs8cffb282016-04-09 19:43:50129 const Elf32_Shdr* section_header_table_raw =
130 reinterpret_cast<const Elf32_Shdr*>(
131 FileOffsetToPointer(header_->e_shoff));
[email protected]39ed9732013-06-20 10:17:53132 section_header_table_size_ = header_->e_shnum;
huangs691893002016-04-19 20:04:33133 section_header_table_.assign(section_header_table_raw,
134 section_header_table_raw + section_header_table_size_);
135
huangs16f01e02016-04-21 19:38:38136 // TODO(huangs): Validate offsets of all section headers.
137
huangs691893002016-04-19 20:04:33138 section_header_file_offset_order_ =
139 GetSectionHeaderFileOffsetOrder(section_header_table_);
[email protected]39ed9732013-06-20 10:17:53140
halyavinc9de6f72015-03-24 15:40:12141 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
142 return Bad("Out of bounds program header table");
[email protected]39ed9732013-06-20 10:17:53143
huangsdda11d062016-03-14 16:35:39144 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
145 FileOffsetToPointer(header_->e_phoff));
[email protected]39ed9732013-06-20 10:17:53146 program_header_table_size_ = header_->e_phnum;
147
huangs16f01e02016-04-21 19:38:38148 Elf32_Half string_section_id = header_->e_shstrndx;
149 if (string_section_id >= header_->e_shnum)
halyavinc9de6f72015-03-24 15:40:12150 return Bad("Out of bounds string section index");
[email protected]39ed9732013-06-20 10:17:53151
huangs16f01e02016-04-21 19:38:38152 default_string_section_ =
153 reinterpret_cast<const char*>(SectionBody(string_section_id));
154 default_string_section_size_ = SectionHeader(string_section_id)->sh_size;
155 // String section may be empty. If nonempty, then last byte must be null.
156 if (default_string_section_size_ > 0) {
157 if (default_string_section_[default_string_section_size_ - 1] != '\0')
158 return Bad("String section does not terminate");
159 }
[email protected]39ed9732013-06-20 10:17:53160
huangsdda11d062016-03-14 16:35:39161 if (!UpdateLength())
halyavinc9de6f72015-03-24 15:40:12162 return Bad("Out of bounds section or segment");
[email protected]39ed9732013-06-20 10:17:53163
164 return Good();
165}
166
167bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
168 if (!ok())
169 return false;
170
171 // The Image Base is always 0 for ELF Executables
172 target->set_image_base(0);
173
174 if (!ParseAbs32Relocs())
175 return false;
176
huangsc8037632016-05-19 18:16:40177 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations.
[email protected]39ed9732013-06-20 10:17:53178 return false;
179
huangsc8037632016-05-19 18:16:40180 PrecomputeLabels(target);
181 RemoveUnusedRel32Locations(target);
182
[email protected]39ed9732013-06-20 10:17:53183 if (!ParseFile(target))
184 return false;
185
huangsc8037632016-05-19 18:16:40186 // Finally sort rel32 locations.
huangs3da0dd932016-04-28 22:14:45187 std::sort(rel32_locations_.begin(),
188 rel32_locations_.end(),
189 TypedRVA::IsLessThanByRVA);
190 DCHECK(rel32_locations_.empty() ||
191 rel32_locations_.back()->rva() != kUnassignedRVA);
192
[email protected]39ed9732013-06-20 10:17:53193 target->DefaultAssignIndexes();
[email protected]39ed9732013-06-20 10:17:53194 return true;
195}
196
huangsc8037632016-05-19 18:16:40197CheckBool 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
halyavinc9de6f72015-03-24 15:40:12219bool DisassemblerElf32::UpdateLength() {
220 Elf32_Off result = 0;
[email protected]39ed9732013-06-20 10:17:53221
222 // Find the end of the last section
huangsdda11d062016-03-14 16:35:39223 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
224 ++section_id) {
225 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53226
227 if (section_header->sh_type == SHT_NOBITS)
228 continue;
229
halyavinc9de6f72015-03-24 15:40:12230 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
231 return false;
[email protected]39ed9732013-06-20 10:17:53232
halyavinc9de6f72015-03-24 15:40:12233 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
234 result = std::max(result, section_end);
[email protected]39ed9732013-06-20 10:17:53235 }
236
237 // Find the end of the last segment
huangsdda11d062016-03-14 16:35:39238 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
239 ++segment_id) {
240 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53241
halyavinc9de6f72015-03-24 15:40:12242 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
243 return false;
[email protected]39ed9732013-06-20 10:17:53244
halyavinc9de6f72015-03-24 15:40:12245 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
246 result = std::max(result, segment_end);
[email protected]39ed9732013-06-20 10:17:53247 }
248
huangsdda11d062016-03-14 16:35:39249 Elf32_Off section_table_end =
250 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr));
halyavinc9de6f72015-03-24 15:40:12251 result = std::max(result, section_table_end);
[email protected]39ed9732013-06-20 10:17:53252
huangsdda11d062016-03-14 16:35:39253 Elf32_Off segment_table_end =
254 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr));
halyavinc9de6f72015-03-24 15:40:12255 result = std::max(result, segment_table_end);
[email protected]39ed9732013-06-20 10:17:53256
halyavinc9de6f72015-03-24 15:40:12257 ReduceLength(result);
258 return true;
[email protected]39ed9732013-06-20 10:17:53259}
260
huangs16f01e02016-04-21 19:38:38261CheckBool DisassemblerElf32::SectionName(const Elf32_Shdr& shdr,
262 std::string* name) const {
263 DCHECK(name);
264 size_t string_pos = shdr.sh_name;
265 if (string_pos == 0) {
266 // Empty string by convention. Valid even if string section is empty.
267 name->clear();
268 } else {
269 if (string_pos >= default_string_section_size_)
270 return false;
271 // Safe because string section must terminate with null.
272 *name = default_string_section_ + string_pos;
273 }
274 return true;
275}
276
huangsdda11d062016-03-14 16:35:39277CheckBool DisassemblerElf32::RVAsToFileOffsets(
278 const std::vector<RVA>& rvas,
279 std::vector<FileOffset>* file_offsets) {
280 file_offsets->clear();
huangsc8037632016-05-19 18:16:40281 file_offsets->reserve(rvas.size());
huangsdda11d062016-03-14 16:35:39282 for (RVA rva : rvas) {
283 FileOffset file_offset = RVAToFileOffset(rva);
284 if (file_offset == kNoFileOffset)
scottmg4a95ca52016-03-12 23:54:56285 return false;
huangsdda11d062016-03-14 16:35:39286 file_offsets->push_back(file_offset);
scottmg4a95ca52016-03-12 23:54:56287 }
[email protected]39ed9732013-06-20 10:17:53288 return true;
289}
290
huangsdda11d062016-03-14 16:35:39291CheckBool DisassemblerElf32::RVAsToFileOffsets(
etiennep7d4e8ee2016-05-11 20:13:36292 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) {
293 for (auto& typed_rva : *typed_rvas) {
huangsdda11d062016-03-14 16:35:39294 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
295 if (file_offset == kNoFileOffset)
[email protected]144c8e92013-07-23 21:18:19296 return false;
huangsdda11d062016-03-14 16:35:39297 typed_rva->set_file_offset(file_offset);
[email protected]144c8e92013-07-23 21:18:19298 }
[email protected]144c8e92013-07-23 21:18:19299 return true;
300}
301
huangsc8037632016-05-19 18:16:40302RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
303 return new RvaVisitor_Abs32(abs32_locations_, *this);
304}
305
306RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() {
307 return new Elf32RvaVisitor_Rel32(rel32_locations_);
308}
309
310void 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
[email protected]39ed9732013-06-20 10:17:53328CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
329 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39330 FileOffset file_offset = 0;
[email protected]39ed9732013-06-20 10:17:53331
huangsdda11d062016-03-14 16:35:39332 std::vector<FileOffset> abs_offsets;
[email protected]39ed9732013-06-20 10:17:53333
huangs3da0dd932016-04-28 22:14:45334 // File parsing follows file offset order, and we visit abs32 and rel32
335 // locations in lockstep. Therefore we need to extract and sort file offsets
336 // of all abs32 and rel32 locations.
huangsdda11d062016-03-14 16:35:39337 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
[email protected]39ed9732013-06-20 10:17:53338 return false;
huangs3da0dd932016-04-28 22:14:45339 std::sort(abs32_locations_.begin(), abs32_locations_.end());
[email protected]39ed9732013-06-20 10:17:53340
huangsdda11d062016-03-14 16:35:39341 if (!RVAsToFileOffsets(&rel32_locations_))
[email protected]39ed9732013-06-20 10:17:53342 return false;
huangs3da0dd932016-04-28 22:14:45343 std::sort(rel32_locations_.begin(),
344 rel32_locations_.end(),
345 TypedRVA::IsLessThanByFileOffset);
[email protected]39ed9732013-06-20 10:17:53346
huangsdda11d062016-03-14 16:35:39347 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin();
huangsdda11d062016-03-14 16:35:39348 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end();
huangs3da0dd932016-04-28 22:14:45349
etiennep7d4e8ee2016-05-11 20:13:36350 std::vector<std::unique_ptr<TypedRVA>>::iterator current_rel =
351 rel32_locations_.begin();
352 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel =
353 rel32_locations_.end();
[email protected]39ed9732013-06-20 10:17:53354
huangs691893002016-04-19 20:04:33355 // Visit section headers ordered by file offset.
356 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:39357 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53358
Will Harris3e6fa972015-03-02 21:14:25359 if (section_header->sh_type == SHT_NOBITS)
360 continue;
361
huangsdda11d062016-03-14 16:35:39362 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program))
[email protected]39ed9732013-06-20 10:17:53363 return false;
huangsdda11d062016-03-14 16:35:39364
[email protected]39ed9732013-06-20 10:17:53365 file_offset = section_header->sh_offset;
366
367 switch (section_header->sh_type) {
368 case SHT_REL:
369 if (!ParseRelocationSection(section_header, program))
370 return false;
371 file_offset = section_header->sh_offset + section_header->sh_size;
372 break;
373 case SHT_PROGBITS:
374 if (!ParseProgbitsSection(section_header,
huangsdda11d062016-03-14 16:35:39375 &current_abs_offset,
376 end_abs_offset,
377 &current_rel,
378 end_rel,
379 program)) {
[email protected]39ed9732013-06-20 10:17:53380 return false;
huangsdda11d062016-03-14 16:35:39381 }
[email protected]39ed9732013-06-20 10:17:53382 file_offset = section_header->sh_offset + section_header->sh_size;
383 break;
[email protected]39ed9732013-06-20 10:17:53384 case SHT_INIT_ARRAY:
385 // Fall through
386 case SHT_FINI_ARRAY:
387 while (current_abs_offset != end_abs_offset &&
388 *current_abs_offset >= section_header->sh_offset &&
389 *current_abs_offset <
huangsdda11d062016-03-14 16:35:39390 section_header->sh_offset + section_header->sh_size) {
[email protected]39ed9732013-06-20 10:17:53391 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
huangsdda11d062016-03-14 16:35:39392 VLOG(1) << "Skipping relocation entry for unsupported section: "
393 << section_header->sh_type;
394 ++current_abs_offset;
[email protected]39ed9732013-06-20 10:17:53395 }
396 break;
397 default:
398 if (current_abs_offset != end_abs_offset &&
huangsdda11d062016-03-14 16:35:39399 *current_abs_offset >= section_header->sh_offset &&
400 *current_abs_offset <
401 section_header->sh_offset + section_header->sh_size) {
402 VLOG(1) << "Relocation address in unrecognized ELF section: "
403 << section_header->sh_type;
404 }
405 break;
[email protected]39ed9732013-06-20 10:17:53406 }
407 }
408
409 // Rest of the file past the last section
huangsdda11d062016-03-14 16:35:39410 if (!ParseSimpleRegion(file_offset, length(), program))
[email protected]39ed9732013-06-20 10:17:53411 return false;
412
413 // Make certain we consume all of the relocations as expected
414 return (current_abs_offset == end_abs_offset);
415}
416
417CheckBool DisassemblerElf32::ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39418 const Elf32_Shdr* section_header,
419 std::vector<FileOffset>::iterator* current_abs_offset,
420 std::vector<FileOffset>::iterator end_abs_offset,
etiennep7d4e8ee2016-05-11 20:13:36421 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
422 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
[email protected]39ed9732013-06-20 10:17:53423 AssemblyProgram* program) {
[email protected]39ed9732013-06-20 10:17:53424 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39425 FileOffset file_offset = section_header->sh_offset;
426 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
[email protected]39ed9732013-06-20 10:17:53427
428 Elf32_Addr origin = section_header->sh_addr;
huangsdda11d062016-03-14 16:35:39429 FileOffset origin_offset = section_header->sh_offset;
[email protected]39ed9732013-06-20 10:17:53430 if (!program->EmitOriginInstruction(origin))
431 return false;
432
433 while (file_offset < section_end) {
[email protected]39ed9732013-06-20 10:17:53434 if (*current_abs_offset != end_abs_offset &&
435 file_offset > **current_abs_offset)
436 return false;
437
[email protected]144c8e92013-07-23 21:18:19438 while (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39439 file_offset > (**current_rel)->file_offset()) {
440 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53441 }
442
huangsdda11d062016-03-14 16:35:39443 FileOffset next_relocation = section_end;
[email protected]39ed9732013-06-20 10:17:53444
445 if (*current_abs_offset != end_abs_offset &&
446 next_relocation > **current_abs_offset)
447 next_relocation = **current_abs_offset;
448
449 // Rel offsets are heuristically derived, and might (incorrectly) overlap
450 // an Abs value, or the end of the section, so +3 to make sure there is
451 // room for the full 4 byte value.
[email protected]144c8e92013-07-23 21:18:19452 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39453 next_relocation > ((**current_rel)->file_offset() + 3))
454 next_relocation = (**current_rel)->file_offset();
[email protected]39ed9732013-06-20 10:17:53455
456 if (next_relocation > file_offset) {
457 if (!ParseSimpleRegion(file_offset, next_relocation, program))
458 return false;
459
460 file_offset = next_relocation;
461 continue;
462 }
463
464 if (*current_abs_offset != end_abs_offset &&
465 file_offset == **current_abs_offset) {
huangsf940a8c92016-03-23 20:40:35466 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
467 DCHECK_NE(kNoRVA, target_rva);
[email protected]39ed9732013-06-20 10:17:53468
huangsc8037632016-05-19 18:16:40469 Label* label = program->FindAbs32Label(target_rva);
470 CHECK(label);
471 if (!program->EmitAbs32(label))
[email protected]39ed9732013-06-20 10:17:53472 return false;
473 file_offset += sizeof(RVA);
huangsdda11d062016-03-14 16:35:39474 ++(*current_abs_offset);
[email protected]39ed9732013-06-20 10:17:53475 continue;
476 }
477
[email protected]144c8e92013-07-23 21:18:19478 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39479 file_offset == (**current_rel)->file_offset()) {
aviab98dcc92015-12-21 19:35:33480 uint32_t relative_target = (**current_rel)->relative_target();
huangsc8037632016-05-19 18:16:40481 CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
482 (**current_rel)->rva());
[email protected]39ed9732013-06-20 10:17:53483 // This cast is for 64 bit systems, and is only safe because we
484 // are working on 32 bit executables.
485 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
[email protected]144c8e92013-07-23 21:18:19486 relative_target);
[email protected]39ed9732013-06-20 10:17:53487
huangsc8037632016-05-19 18:16:40488 Label* label = program->FindRel32Label(target_rva);
489 CHECK(label);
490
491 if (!(**current_rel)->EmitInstruction(program, label))
[email protected]39ed9732013-06-20 10:17:53492 return false;
[email protected]2b637b62013-08-01 00:11:24493 file_offset += (**current_rel)->op_size();
huangsdda11d062016-03-14 16:35:39494 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53495 continue;
496 }
497 }
498
499 // Rest of the section (if any)
500 return ParseSimpleRegion(file_offset, section_end, program);
501}
502
huangsdda11d062016-03-14 16:35:39503CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset,
504 FileOffset end_file_offset,
505 AssemblyProgram* program) {
[email protected]c092858a2013-08-13 00:46:30506 // Callers don't guarantee start < end
huangsdda11d062016-03-14 16:35:39507 if (start_file_offset >= end_file_offset)
508 return true;
[email protected]39ed9732013-06-20 10:17:53509
pkasting8e3a26a2014-10-03 18:52:29510 const size_t len = end_file_offset - start_file_offset;
[email protected]c092858a2013-08-13 00:46:30511
huangsdda11d062016-03-14 16:35:39512 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
513 len)) {
[email protected]c092858a2013-08-13 00:46:30514 return false;
huangsdda11d062016-03-14 16:35:39515 }
[email protected]39ed9732013-06-20 10:17:53516
517 return true;
518}
519
520CheckBool DisassemblerElf32::ParseAbs32Relocs() {
521 abs32_locations_.clear();
522
523 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39524 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
525 ++section_id) {
526 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53527
528 if (section_header->sh_type == SHT_REL) {
huangsdda11d062016-03-14 16:35:39529 const Elf32_Rel* relocs_table =
530 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id));
[email protected]39ed9732013-06-20 10:17:53531
532 int relocs_table_count = section_header->sh_size /
533 section_header->sh_entsize;
534
535 // Elf32_Word relocation_section_id = section_header->sh_info;
536
537 // Loop through relocation objects in the relocation section
huangsdda11d062016-03-14 16:35:39538 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) {
[email protected]39ed9732013-06-20 10:17:53539 RVA rva;
540
541 // Quite a few of these conversions fail, and we simply skip
542 // them, that's okay.
[email protected]a8e80412013-07-18 22:07:53543 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
[email protected]39ed9732013-06-20 10:17:53544 abs32_locations_.push_back(rva);
545 }
546 }
547 }
548
549 std::sort(abs32_locations_.begin(), abs32_locations_.end());
huangsbb4b8a92016-01-19 22:09:03550 DCHECK(abs32_locations_.empty() ||
551 abs32_locations_.back() != kUnassignedRVA);
[email protected]39ed9732013-06-20 10:17:53552 return true;
553}
554
[email protected]a8e80412013-07-18 22:07:53555CheckBool DisassemblerElf32::CheckSection(RVA rva) {
huangsdda11d062016-03-14 16:35:39556 FileOffset file_offset = RVAToFileOffset(rva);
557 if (file_offset == kNoFileOffset)
[email protected]a8e80412013-07-18 22:07:53558 return false;
[email protected]a8e80412013-07-18 22:07:53559
huangsdda11d062016-03-14 16:35:39560 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
561 ++section_id) {
562 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]a8e80412013-07-18 22:07:53563
huangsdda11d062016-03-14 16:35:39564 if (file_offset >= section_header->sh_offset &&
565 file_offset < (section_header->sh_offset + section_header->sh_size)) {
[email protected]a8e80412013-07-18 22:07:53566 switch (section_header->sh_type) {
huangsdda11d062016-03-14 16:35:39567 case SHT_REL: // Falls through.
[email protected]a8e80412013-07-18 22:07:53568 case SHT_PROGBITS:
569 return true;
570 }
571 }
572 }
573
574 return false;
575}
576
[email protected]39ed9732013-06-20 10:17:53577CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
[email protected]39ed9732013-06-20 10:17:53578 rel32_locations_.clear();
huangs3da0dd932016-04-28 22:14:45579 bool found_rel32 = false;
[email protected]39ed9732013-06-20 10:17:53580
581 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39582 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
583 ++section_id) {
584 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53585
huangs7ec152c2016-02-04 22:26:43586 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
587 if (section_header->sh_type != SHT_PROGBITS ||
588 section_header->sh_addr == 0)
[email protected]39ed9732013-06-20 10:17:53589 continue;
590
huangs3da0dd932016-04-28 22:14:45591 // Heuristic: Only consider ".text" section.
592 std::string section_name;
593 if (!SectionName(*section_header, &section_name))
594 return false;
595 if (section_name != ".text")
596 continue;
597
598 found_rel32 = true;
[email protected]39ed9732013-06-20 10:17:53599 if (!ParseRel32RelocsFromSection(section_header))
600 return false;
601 }
huangs3da0dd932016-04-28 22:14:45602 if (!found_rel32)
603 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";
[email protected]39ed9732013-06-20 10:17:53604
[email protected]39ed9732013-06-20 10:17:53605 return true;
606}
607
608} // namespace courgette