blob: fac661c79160926a3cb53ba6895348983537fd16 [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>
[email protected]39ed9732013-06-20 10:17:539
huangs7b221a52016-11-09 22:28:2310#include "base/bind.h"
[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
etiennep5059bca2016-07-08 17:55:2046DisassemblerElf32::DisassemblerElf32(const uint8_t* 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),
etiennep5059bca2016-07-08 17:55:2052 default_string_section_(nullptr) {}
huangsdda11d062016-03-14 16:35:3953
54RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
55 // File offsets can be 64-bit values, but we are dealing with 32-bit
56 // executables and so only need to support 32-bit file sizes.
57 uint32_t offset32 = static_cast<uint32_t>(offset);
58
huangs691893002016-04-19 20:04:3359 // Visit section headers ordered by file offset.
60 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:3961 const Elf32_Shdr* section_header = SectionHeader(section_id);
62 // These can appear to have a size in the file, but don't.
63 if (section_header->sh_type == SHT_NOBITS)
64 continue;
65
66 Elf32_Off section_begin = section_header->sh_offset;
67 Elf32_Off section_end = section_begin + section_header->sh_size;
68
69 if (offset32 >= section_begin && offset32 < section_end) {
70 return section_header->sh_addr + (offset32 - section_begin);
71 }
72 }
73
74 return 0;
75}
76
77FileOffset DisassemblerElf32::RVAToFileOffset(RVA rva) const {
78 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
79 ++section_id) {
80 const Elf32_Shdr* section_header = SectionHeader(section_id);
81 // These can appear to have a size in the file, but don't.
82 if (section_header->sh_type == SHT_NOBITS)
83 continue;
84 Elf32_Addr begin = section_header->sh_addr;
85 Elf32_Addr end = begin + section_header->sh_size;
86
87 if (rva >= begin && rva < end)
88 return section_header->sh_offset + (rva - begin);
89 }
90 return kNoFileOffset;
[email protected]39ed9732013-06-20 10:17:5391}
92
huangsf940a8c92016-03-23 20:40:3593RVA DisassemblerElf32::PointerToTargetRVA(const uint8_t* p) const {
94 // TODO(huangs): Add check (e.g., IsValidTargetRVA(), but more efficient).
95 return Read32LittleEndian(p);
96}
97
[email protected]39ed9732013-06-20 10:17:5398bool DisassemblerElf32::ParseHeader() {
99 if (length() < sizeof(Elf32_Ehdr))
100 return Bad("Too small");
101
huangsdda11d062016-03-14 16:35:39102 header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
[email protected]39ed9732013-06-20 10:17:53103
huangsdda11d062016-03-14 16:35:39104 // Have magic for ELF header?
[email protected]39ed9732013-06-20 10:17:53105 if (header_->e_ident[0] != 0x7f ||
106 header_->e_ident[1] != 'E' ||
107 header_->e_ident[2] != 'L' ||
108 header_->e_ident[3] != 'F')
109 return Bad("No Magic Number");
110
111 if (header_->e_type != ET_EXEC &&
112 header_->e_type != ET_DYN)
113 return Bad("Not an executable file or shared library");
114
115 if (header_->e_machine != ElfEM())
116 return Bad("Not a supported architecture");
117
118 if (header_->e_version != 1)
119 return Bad("Unknown file version");
120
121 if (header_->e_shentsize != sizeof(Elf32_Shdr))
122 return Bad("Unexpected section header size");
123
halyavinc9de6f72015-03-24 15:40:12124 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
125 return Bad("Out of bounds section header table");
[email protected]39ed9732013-06-20 10:17:53126
huangs691893002016-04-19 20:04:33127 // Extract |section_header_table_|, ordered by section id.
huangs8cffb282016-04-09 19:43:50128 const Elf32_Shdr* section_header_table_raw =
129 reinterpret_cast<const Elf32_Shdr*>(
130 FileOffsetToPointer(header_->e_shoff));
[email protected]39ed9732013-06-20 10:17:53131 section_header_table_size_ = header_->e_shnum;
huangs691893002016-04-19 20:04:33132 section_header_table_.assign(section_header_table_raw,
133 section_header_table_raw + section_header_table_size_);
134
huangs16f01e02016-04-21 19:38:38135 // TODO(huangs): Validate offsets of all section headers.
136
huangs691893002016-04-19 20:04:33137 section_header_file_offset_order_ =
138 GetSectionHeaderFileOffsetOrder(section_header_table_);
[email protected]39ed9732013-06-20 10:17:53139
halyavinc9de6f72015-03-24 15:40:12140 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
141 return Bad("Out of bounds program header table");
[email protected]39ed9732013-06-20 10:17:53142
huangsdda11d062016-03-14 16:35:39143 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
144 FileOffsetToPointer(header_->e_phoff));
[email protected]39ed9732013-06-20 10:17:53145 program_header_table_size_ = header_->e_phnum;
146
huangs16f01e02016-04-21 19:38:38147 Elf32_Half string_section_id = header_->e_shstrndx;
148 if (string_section_id >= header_->e_shnum)
halyavinc9de6f72015-03-24 15:40:12149 return Bad("Out of bounds string section index");
[email protected]39ed9732013-06-20 10:17:53150
huangs16f01e02016-04-21 19:38:38151 default_string_section_ =
152 reinterpret_cast<const char*>(SectionBody(string_section_id));
153 default_string_section_size_ = SectionHeader(string_section_id)->sh_size;
154 // String section may be empty. If nonempty, then last byte must be null.
155 if (default_string_section_size_ > 0) {
156 if (default_string_section_[default_string_section_size_ - 1] != '\0')
157 return Bad("String section does not terminate");
158 }
[email protected]39ed9732013-06-20 10:17:53159
huangsdda11d062016-03-14 16:35:39160 if (!UpdateLength())
halyavinc9de6f72015-03-24 15:40:12161 return Bad("Out of bounds section or segment");
[email protected]39ed9732013-06-20 10:17:53162
163 return Good();
164}
165
huangsc8037632016-05-19 18:16:40166CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
167 if (rva == kUnassignedRVA)
168 return false;
169
170 // |rva| is valid if it's contained in any program segment.
171 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
172 ++segment_id) {
173 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
174
175 if (segment_header->p_type != PT_LOAD)
176 continue;
177
178 Elf32_Addr begin = segment_header->p_vaddr;
179 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
180
181 if (rva >= begin && rva < end)
182 return true;
183 }
184
185 return false;
186}
187
etiennep5059bca2016-07-08 17:55:20188// static
189bool DisassemblerElf32::QuickDetect(const uint8_t* start,
190 size_t length,
191 e_machine_values elf_em) {
192 if (length < sizeof(Elf32_Ehdr))
193 return false;
194
195 const Elf32_Ehdr* header = reinterpret_cast<const Elf32_Ehdr*>(start);
196
197 // Have magic for ELF header?
198 if (header->e_ident[0] != 0x7f || header->e_ident[1] != 'E' ||
199 header->e_ident[2] != 'L' || header->e_ident[3] != 'F')
200 return false;
201
202 if (header->e_type != ET_EXEC && header->e_type != ET_DYN)
203 return false;
204 if (header->e_machine != elf_em)
205 return false;
206 if (header->e_version != 1)
207 return false;
208 if (header->e_shentsize != sizeof(Elf32_Shdr))
209 return false;
210
211 return true;
212}
213
halyavinc9de6f72015-03-24 15:40:12214bool DisassemblerElf32::UpdateLength() {
215 Elf32_Off result = 0;
[email protected]39ed9732013-06-20 10:17:53216
217 // Find the end of the last section
huangsdda11d062016-03-14 16:35:39218 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
219 ++section_id) {
220 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53221
222 if (section_header->sh_type == SHT_NOBITS)
223 continue;
224
halyavinc9de6f72015-03-24 15:40:12225 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
226 return false;
[email protected]39ed9732013-06-20 10:17:53227
halyavinc9de6f72015-03-24 15:40:12228 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
229 result = std::max(result, section_end);
[email protected]39ed9732013-06-20 10:17:53230 }
231
232 // Find the end of the last segment
huangsdda11d062016-03-14 16:35:39233 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
234 ++segment_id) {
235 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53236
halyavinc9de6f72015-03-24 15:40:12237 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
238 return false;
[email protected]39ed9732013-06-20 10:17:53239
halyavinc9de6f72015-03-24 15:40:12240 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
241 result = std::max(result, segment_end);
[email protected]39ed9732013-06-20 10:17:53242 }
243
huangsdda11d062016-03-14 16:35:39244 Elf32_Off section_table_end =
245 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr));
halyavinc9de6f72015-03-24 15:40:12246 result = std::max(result, section_table_end);
[email protected]39ed9732013-06-20 10:17:53247
huangsdda11d062016-03-14 16:35:39248 Elf32_Off segment_table_end =
249 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr));
halyavinc9de6f72015-03-24 15:40:12250 result = std::max(result, segment_table_end);
[email protected]39ed9732013-06-20 10:17:53251
halyavinc9de6f72015-03-24 15:40:12252 ReduceLength(result);
253 return true;
[email protected]39ed9732013-06-20 10:17:53254}
255
huangs16f01e02016-04-21 19:38:38256CheckBool DisassemblerElf32::SectionName(const Elf32_Shdr& shdr,
257 std::string* name) const {
258 DCHECK(name);
259 size_t string_pos = shdr.sh_name;
260 if (string_pos == 0) {
261 // Empty string by convention. Valid even if string section is empty.
262 name->clear();
263 } else {
264 if (string_pos >= default_string_section_size_)
265 return false;
266 // Safe because string section must terminate with null.
267 *name = default_string_section_ + string_pos;
268 }
269 return true;
270}
271
huangsdda11d062016-03-14 16:35:39272CheckBool DisassemblerElf32::RVAsToFileOffsets(
273 const std::vector<RVA>& rvas,
huangs7b221a52016-11-09 22:28:23274 std::vector<FileOffset>* file_offsets) const {
huangsdda11d062016-03-14 16:35:39275 file_offsets->clear();
huangsc8037632016-05-19 18:16:40276 file_offsets->reserve(rvas.size());
huangsdda11d062016-03-14 16:35:39277 for (RVA rva : rvas) {
278 FileOffset file_offset = RVAToFileOffset(rva);
279 if (file_offset == kNoFileOffset)
scottmg4a95ca52016-03-12 23:54:56280 return false;
huangsdda11d062016-03-14 16:35:39281 file_offsets->push_back(file_offset);
scottmg4a95ca52016-03-12 23:54:56282 }
[email protected]39ed9732013-06-20 10:17:53283 return true;
284}
285
huangsdda11d062016-03-14 16:35:39286CheckBool DisassemblerElf32::RVAsToFileOffsets(
huangs7b221a52016-11-09 22:28:23287 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const {
etiennep7d4e8ee2016-05-11 20:13:36288 for (auto& typed_rva : *typed_rvas) {
huangsdda11d062016-03-14 16:35:39289 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
290 if (file_offset == kNoFileOffset)
[email protected]144c8e92013-07-23 21:18:19291 return false;
huangsdda11d062016-03-14 16:35:39292 typed_rva->set_file_offset(file_offset);
[email protected]144c8e92013-07-23 21:18:19293 }
[email protected]144c8e92013-07-23 21:18:19294 return true;
295}
296
huangs257f9fb02017-03-23 23:17:50297bool DisassemblerElf32::ExtractAbs32Locations() {
huangsdc779d92017-03-01 22:22:38298 abs32_locations_.clear();
299
300 // Loop through sections for relocation sections
301 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
302 ++section_id) {
303 const Elf32_Shdr* section_header = SectionHeader(section_id);
304
305 if (section_header->sh_type == SHT_REL) {
306 const Elf32_Rel* relocs_table =
307 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id));
308
309 int relocs_table_count =
310 section_header->sh_size / section_header->sh_entsize;
311
312 // Elf32_Word relocation_section_id = section_header->sh_info;
313
314 // Loop through relocation objects in the relocation section
315 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) {
316 RVA rva;
317
318 // Quite a few of these conversions fail, and we simply skip
319 // them, that's okay.
320 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
321 abs32_locations_.push_back(rva);
322 }
323 }
324 }
325
326 std::sort(abs32_locations_.begin(), abs32_locations_.end());
327 DCHECK(abs32_locations_.empty() || abs32_locations_.back() != kUnassignedRVA);
328 return true;
329}
330
huangs257f9fb02017-03-23 23:17:50331bool DisassemblerElf32::ExtractRel32Locations() {
huangsdc779d92017-03-01 22:22:38332 rel32_locations_.clear();
333 bool found_rel32 = false;
334
335 // Loop through sections for relocation sections
336 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
337 ++section_id) {
338 const Elf32_Shdr* section_header = SectionHeader(section_id);
339
340 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
341 if (section_header->sh_type != SHT_PROGBITS || section_header->sh_addr == 0)
342 continue;
343
344 // Heuristic: Only consider ".text" section.
345 std::string section_name;
346 if (!SectionName(*section_header, &section_name))
347 return false;
348 if (section_name != ".text")
349 continue;
350
351 found_rel32 = true;
352 if (!ParseRel32RelocsFromSection(section_header))
353 return false;
354 }
355 if (!found_rel32)
356 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";
357
huangsc615c9112017-03-22 06:52:24358 std::sort(rel32_locations_.begin(), rel32_locations_.end(),
359 TypedRVA::IsLessThanByRVA);
360 DCHECK(rel32_locations_.empty() ||
361 rel32_locations_.back()->rva() != kUnassignedRVA);
362
huangsdc779d92017-03-01 22:22:38363 return true;
364}
365
huangsc8037632016-05-19 18:16:40366RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
367 return new RvaVisitor_Abs32(abs32_locations_, *this);
368}
369
370RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() {
371 return new Elf32RvaVisitor_Rel32(rel32_locations_);
372}
373
374void DisassemblerElf32::RemoveUnusedRel32Locations(AssemblyProgram* program) {
375 auto tail_it = rel32_locations_.begin();
376 for (auto head_it = rel32_locations_.begin();
377 head_it != rel32_locations_.end(); ++head_it) {
378 RVA target_rva = (*head_it)->rva() + (*head_it)->relative_target();
379 if (program->FindRel32Label(target_rva) == nullptr) {
380 // If address does not match a Label (because it was removed), deallocate.
381 (*head_it).reset(nullptr);
382 } else {
383 // Else squeeze nullptr to end to compactify.
384 if (tail_it != head_it)
385 (*tail_it).swap(*head_it);
386 ++tail_it;
387 }
388 }
389 rel32_locations_.resize(std::distance(rel32_locations_.begin(), tail_it));
390}
391
huangs257f9fb02017-03-23 23:17:50392InstructionGenerator DisassemblerElf32::GetInstructionGenerator(
393 AssemblyProgram* program) {
tzik0881a4002018-03-08 06:19:49394 return base::BindRepeating(&DisassemblerElf32::ParseFile,
395 base::Unretained(this), program);
huangs257f9fb02017-03-23 23:17:50396}
397
huangs7b221a52016-11-09 22:28:23398CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program,
399 InstructionReceptor* receptor) const {
[email protected]39ed9732013-06-20 10:17:53400 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39401 FileOffset file_offset = 0;
[email protected]39ed9732013-06-20 10:17:53402
huangs3da0dd932016-04-28 22:14:45403 // File parsing follows file offset order, and we visit abs32 and rel32
404 // locations in lockstep. Therefore we need to extract and sort file offsets
huangsc615c9112017-03-22 06:52:24405 // of all abs32 and rel32 locations. For abs32, we copy the offsets to a new
406 // array.
407 std::vector<FileOffset> abs_offsets;
huangsdda11d062016-03-14 16:35:39408 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
[email protected]39ed9732013-06-20 10:17:53409 return false;
huangsc615c9112017-03-22 06:52:24410 std::sort(abs_offsets.begin(), abs_offsets.end());
[email protected]39ed9732013-06-20 10:17:53411
huangsc615c9112017-03-22 06:52:24412 // For rel32, TypedRVA (rather than raw offset) is stored, so sort-by-offset
413 // is performed in place to save memory. At the end of function we will
414 // sort-by-RVA.
huangsdda11d062016-03-14 16:35:39415 if (!RVAsToFileOffsets(&rel32_locations_))
[email protected]39ed9732013-06-20 10:17:53416 return false;
huangs3da0dd932016-04-28 22:14:45417 std::sort(rel32_locations_.begin(),
418 rel32_locations_.end(),
419 TypedRVA::IsLessThanByFileOffset);
[email protected]39ed9732013-06-20 10:17:53420
huangsdda11d062016-03-14 16:35:39421 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin();
huangsdda11d062016-03-14 16:35:39422 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end();
huangs3da0dd932016-04-28 22:14:45423
etiennep7d4e8ee2016-05-11 20:13:36424 std::vector<std::unique_ptr<TypedRVA>>::iterator current_rel =
425 rel32_locations_.begin();
426 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel =
427 rel32_locations_.end();
[email protected]39ed9732013-06-20 10:17:53428
huangs691893002016-04-19 20:04:33429 // Visit section headers ordered by file offset.
430 for (Elf32_Half section_id : section_header_file_offset_order_) {
huangsdda11d062016-03-14 16:35:39431 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53432
Will Harris3e6fa972015-03-02 21:14:25433 if (section_header->sh_type == SHT_NOBITS)
434 continue;
435
huangs7b221a52016-11-09 22:28:23436 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, receptor))
[email protected]39ed9732013-06-20 10:17:53437 return false;
huangsdda11d062016-03-14 16:35:39438
[email protected]39ed9732013-06-20 10:17:53439 file_offset = section_header->sh_offset;
440
441 switch (section_header->sh_type) {
442 case SHT_REL:
huangs7b221a52016-11-09 22:28:23443 if (!ParseRelocationSection(section_header, receptor))
[email protected]39ed9732013-06-20 10:17:53444 return false;
445 file_offset = section_header->sh_offset + section_header->sh_size;
446 break;
447 case SHT_PROGBITS:
huangs7b221a52016-11-09 22:28:23448 if (!ParseProgbitsSection(section_header, &current_abs_offset,
449 end_abs_offset, &current_rel, end_rel,
450 program, receptor)) {
[email protected]39ed9732013-06-20 10:17:53451 return false;
huangsdda11d062016-03-14 16:35:39452 }
[email protected]39ed9732013-06-20 10:17:53453 file_offset = section_header->sh_offset + section_header->sh_size;
454 break;
[email protected]39ed9732013-06-20 10:17:53455 case SHT_INIT_ARRAY:
456 // Fall through
457 case SHT_FINI_ARRAY:
458 while (current_abs_offset != end_abs_offset &&
459 *current_abs_offset >= section_header->sh_offset &&
460 *current_abs_offset <
huangsdda11d062016-03-14 16:35:39461 section_header->sh_offset + section_header->sh_size) {
[email protected]39ed9732013-06-20 10:17:53462 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
huangsdda11d062016-03-14 16:35:39463 VLOG(1) << "Skipping relocation entry for unsupported section: "
464 << section_header->sh_type;
465 ++current_abs_offset;
[email protected]39ed9732013-06-20 10:17:53466 }
467 break;
468 default:
469 if (current_abs_offset != end_abs_offset &&
huangsdda11d062016-03-14 16:35:39470 *current_abs_offset >= section_header->sh_offset &&
471 *current_abs_offset <
472 section_header->sh_offset + section_header->sh_size) {
473 VLOG(1) << "Relocation address in unrecognized ELF section: "
474 << section_header->sh_type;
475 }
476 break;
[email protected]39ed9732013-06-20 10:17:53477 }
478 }
479
480 // Rest of the file past the last section
huangs7b221a52016-11-09 22:28:23481 if (!ParseSimpleRegion(file_offset, length(), receptor))
[email protected]39ed9732013-06-20 10:17:53482 return false;
483
huangsc615c9112017-03-22 06:52:24484 // Restore original rel32 location order and sort by RVA order.
485 std::sort(rel32_locations_.begin(), rel32_locations_.end(),
486 TypedRVA::IsLessThanByRVA);
487
[email protected]39ed9732013-06-20 10:17:53488 // Make certain we consume all of the relocations as expected
489 return (current_abs_offset == end_abs_offset);
490}
491
492CheckBool DisassemblerElf32::ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39493 const Elf32_Shdr* section_header,
494 std::vector<FileOffset>::iterator* current_abs_offset,
495 std::vector<FileOffset>::iterator end_abs_offset,
etiennep7d4e8ee2016-05-11 20:13:36496 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
497 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
huangs7b221a52016-11-09 22:28:23498 AssemblyProgram* program,
499 InstructionReceptor* receptor) const {
[email protected]39ed9732013-06-20 10:17:53500 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39501 FileOffset file_offset = section_header->sh_offset;
502 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
[email protected]39ed9732013-06-20 10:17:53503
504 Elf32_Addr origin = section_header->sh_addr;
huangsdda11d062016-03-14 16:35:39505 FileOffset origin_offset = section_header->sh_offset;
huangs7b221a52016-11-09 22:28:23506 if (!receptor->EmitOrigin(origin))
[email protected]39ed9732013-06-20 10:17:53507 return false;
508
509 while (file_offset < section_end) {
[email protected]39ed9732013-06-20 10:17:53510 if (*current_abs_offset != end_abs_offset &&
511 file_offset > **current_abs_offset)
512 return false;
513
[email protected]144c8e92013-07-23 21:18:19514 while (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39515 file_offset > (**current_rel)->file_offset()) {
516 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53517 }
518
huangsdda11d062016-03-14 16:35:39519 FileOffset next_relocation = section_end;
[email protected]39ed9732013-06-20 10:17:53520
521 if (*current_abs_offset != end_abs_offset &&
522 next_relocation > **current_abs_offset)
523 next_relocation = **current_abs_offset;
524
525 // Rel offsets are heuristically derived, and might (incorrectly) overlap
526 // an Abs value, or the end of the section, so +3 to make sure there is
527 // room for the full 4 byte value.
[email protected]144c8e92013-07-23 21:18:19528 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39529 next_relocation > ((**current_rel)->file_offset() + 3))
530 next_relocation = (**current_rel)->file_offset();
[email protected]39ed9732013-06-20 10:17:53531
532 if (next_relocation > file_offset) {
huangs7b221a52016-11-09 22:28:23533 if (!ParseSimpleRegion(file_offset, next_relocation, receptor))
[email protected]39ed9732013-06-20 10:17:53534 return false;
535
536 file_offset = next_relocation;
537 continue;
538 }
539
540 if (*current_abs_offset != end_abs_offset &&
541 file_offset == **current_abs_offset) {
huangsf940a8c92016-03-23 20:40:35542 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
543 DCHECK_NE(kNoRVA, target_rva);
[email protected]39ed9732013-06-20 10:17:53544
huangsc8037632016-05-19 18:16:40545 Label* label = program->FindAbs32Label(target_rva);
546 CHECK(label);
huangs7b221a52016-11-09 22:28:23547 if (!receptor->EmitAbs32(label))
[email protected]39ed9732013-06-20 10:17:53548 return false;
549 file_offset += sizeof(RVA);
huangsdda11d062016-03-14 16:35:39550 ++(*current_abs_offset);
[email protected]39ed9732013-06-20 10:17:53551 continue;
552 }
553
[email protected]144c8e92013-07-23 21:18:19554 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39555 file_offset == (**current_rel)->file_offset()) {
aviab98dcc92015-12-21 19:35:33556 uint32_t relative_target = (**current_rel)->relative_target();
huangsc8037632016-05-19 18:16:40557 CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
558 (**current_rel)->rva());
[email protected]39ed9732013-06-20 10:17:53559 // This cast is for 64 bit systems, and is only safe because we
560 // are working on 32 bit executables.
561 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
[email protected]144c8e92013-07-23 21:18:19562 relative_target);
[email protected]39ed9732013-06-20 10:17:53563
huangsc8037632016-05-19 18:16:40564 Label* label = program->FindRel32Label(target_rva);
565 CHECK(label);
566
huangs7b221a52016-11-09 22:28:23567 if (!(**current_rel)->EmitInstruction(label, receptor))
[email protected]39ed9732013-06-20 10:17:53568 return false;
[email protected]2b637b62013-08-01 00:11:24569 file_offset += (**current_rel)->op_size();
huangsdda11d062016-03-14 16:35:39570 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53571 continue;
572 }
573 }
574
575 // Rest of the section (if any)
huangs7b221a52016-11-09 22:28:23576 return ParseSimpleRegion(file_offset, section_end, receptor);
[email protected]39ed9732013-06-20 10:17:53577}
578
huangs7b221a52016-11-09 22:28:23579CheckBool DisassemblerElf32::ParseSimpleRegion(
580 FileOffset start_file_offset,
581 FileOffset end_file_offset,
582 InstructionReceptor* receptor) const {
[email protected]c092858a2013-08-13 00:46:30583 // Callers don't guarantee start < end
huangsdda11d062016-03-14 16:35:39584 if (start_file_offset >= end_file_offset)
585 return true;
[email protected]39ed9732013-06-20 10:17:53586
pkasting8e3a26a2014-10-03 18:52:29587 const size_t len = end_file_offset - start_file_offset;
[email protected]c092858a2013-08-13 00:46:30588
huangs7b221a52016-11-09 22:28:23589 if (!receptor->EmitMultipleBytes(FileOffsetToPointer(start_file_offset),
590 len)) {
[email protected]c092858a2013-08-13 00:46:30591 return false;
huangsdda11d062016-03-14 16:35:39592 }
[email protected]39ed9732013-06-20 10:17:53593
594 return true;
595}
596
[email protected]a8e80412013-07-18 22:07:53597CheckBool DisassemblerElf32::CheckSection(RVA rva) {
huangsdda11d062016-03-14 16:35:39598 FileOffset file_offset = RVAToFileOffset(rva);
599 if (file_offset == kNoFileOffset)
[email protected]a8e80412013-07-18 22:07:53600 return false;
[email protected]a8e80412013-07-18 22:07:53601
huangsdda11d062016-03-14 16:35:39602 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
603 ++section_id) {
604 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]a8e80412013-07-18 22:07:53605
huangsdda11d062016-03-14 16:35:39606 if (file_offset >= section_header->sh_offset &&
607 file_offset < (section_header->sh_offset + section_header->sh_size)) {
[email protected]a8e80412013-07-18 22:07:53608 switch (section_header->sh_type) {
huangsdda11d062016-03-14 16:35:39609 case SHT_REL: // Falls through.
[email protected]a8e80412013-07-18 22:07:53610 case SHT_PROGBITS:
611 return true;
612 }
613 }
614 }
615
616 return false;
617}
618
[email protected]39ed9732013-06-20 10:17:53619} // namespace courgette