blob: 9ceb8ab7b6ad08ae0cc1dd3b8c29d34aad189be8 [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
15DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
huangsdda11d062016-03-14 16:35:3916 : Disassembler(start, length),
17 header_(nullptr),
18 section_header_table_(nullptr),
19 section_header_table_size_(0),
20 program_header_table_(nullptr),
21 program_header_table_size_(0),
22 default_string_section_(nullptr) {
23}
24
25RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
26 // File offsets can be 64-bit values, but we are dealing with 32-bit
27 // executables and so only need to support 32-bit file sizes.
28 uint32_t offset32 = static_cast<uint32_t>(offset);
29
30 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
31 ++section_id) {
32 const Elf32_Shdr* section_header = SectionHeader(section_id);
33 // These can appear to have a size in the file, but don't.
34 if (section_header->sh_type == SHT_NOBITS)
35 continue;
36
37 Elf32_Off section_begin = section_header->sh_offset;
38 Elf32_Off section_end = section_begin + section_header->sh_size;
39
40 if (offset32 >= section_begin && offset32 < section_end) {
41 return section_header->sh_addr + (offset32 - section_begin);
42 }
43 }
44
45 return 0;
46}
47
48FileOffset DisassemblerElf32::RVAToFileOffset(RVA rva) const {
49 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
50 ++section_id) {
51 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 Elf32_Addr begin = section_header->sh_addr;
56 Elf32_Addr end = begin + section_header->sh_size;
57
58 if (rva >= begin && rva < end)
59 return section_header->sh_offset + (rva - begin);
60 }
61 return kNoFileOffset;
[email protected]39ed9732013-06-20 10:17:5362}
63
64bool DisassemblerElf32::ParseHeader() {
65 if (length() < sizeof(Elf32_Ehdr))
66 return Bad("Too small");
67
huangsdda11d062016-03-14 16:35:3968 header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
[email protected]39ed9732013-06-20 10:17:5369
huangsdda11d062016-03-14 16:35:3970 // Have magic for ELF header?
[email protected]39ed9732013-06-20 10:17:5371 if (header_->e_ident[0] != 0x7f ||
72 header_->e_ident[1] != 'E' ||
73 header_->e_ident[2] != 'L' ||
74 header_->e_ident[3] != 'F')
75 return Bad("No Magic Number");
76
77 if (header_->e_type != ET_EXEC &&
78 header_->e_type != ET_DYN)
79 return Bad("Not an executable file or shared library");
80
81 if (header_->e_machine != ElfEM())
82 return Bad("Not a supported architecture");
83
84 if (header_->e_version != 1)
85 return Bad("Unknown file version");
86
87 if (header_->e_shentsize != sizeof(Elf32_Shdr))
88 return Bad("Unexpected section header size");
89
halyavinc9de6f72015-03-24 15:40:1290 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
91 return Bad("Out of bounds section header table");
[email protected]39ed9732013-06-20 10:17:5392
huangsdda11d062016-03-14 16:35:3993 section_header_table_ = reinterpret_cast<const Elf32_Shdr*>(
94 FileOffsetToPointer(header_->e_shoff));
[email protected]39ed9732013-06-20 10:17:5395 section_header_table_size_ = header_->e_shnum;
96
halyavinc9de6f72015-03-24 15:40:1297 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
98 return Bad("Out of bounds program header table");
[email protected]39ed9732013-06-20 10:17:5399
huangsdda11d062016-03-14 16:35:39100 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
101 FileOffsetToPointer(header_->e_phoff));
[email protected]39ed9732013-06-20 10:17:53102 program_header_table_size_ = header_->e_phnum;
103
halyavinc9de6f72015-03-24 15:40:12104 if (header_->e_shstrndx >= header_->e_shnum)
105 return Bad("Out of bounds string section index");
[email protected]39ed9732013-06-20 10:17:53106
huangsdda11d062016-03-14 16:35:39107 default_string_section_ = reinterpret_cast<const char*>(
108 SectionBody(static_cast<int>(header_->e_shstrndx)));
[email protected]39ed9732013-06-20 10:17:53109
huangsdda11d062016-03-14 16:35:39110 if (!UpdateLength())
halyavinc9de6f72015-03-24 15:40:12111 return Bad("Out of bounds section or segment");
[email protected]39ed9732013-06-20 10:17:53112
113 return Good();
114}
115
116bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
117 if (!ok())
118 return false;
119
120 // The Image Base is always 0 for ELF Executables
121 target->set_image_base(0);
122
123 if (!ParseAbs32Relocs())
124 return false;
125
126 if (!ParseRel32RelocsFromSections())
127 return false;
128
129 if (!ParseFile(target))
130 return false;
131
132 target->DefaultAssignIndexes();
[email protected]39ed9732013-06-20 10:17:53133 return true;
134}
135
halyavinc9de6f72015-03-24 15:40:12136bool DisassemblerElf32::UpdateLength() {
137 Elf32_Off result = 0;
[email protected]39ed9732013-06-20 10:17:53138
139 // Find the end of the last section
huangsdda11d062016-03-14 16:35:39140 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
141 ++section_id) {
142 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53143
144 if (section_header->sh_type == SHT_NOBITS)
145 continue;
146
halyavinc9de6f72015-03-24 15:40:12147 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
148 return false;
[email protected]39ed9732013-06-20 10:17:53149
halyavinc9de6f72015-03-24 15:40:12150 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
151 result = std::max(result, section_end);
[email protected]39ed9732013-06-20 10:17:53152 }
153
154 // Find the end of the last segment
huangsdda11d062016-03-14 16:35:39155 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
156 ++segment_id) {
157 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53158
halyavinc9de6f72015-03-24 15:40:12159 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
160 return false;
[email protected]39ed9732013-06-20 10:17:53161
halyavinc9de6f72015-03-24 15:40:12162 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
163 result = std::max(result, segment_end);
[email protected]39ed9732013-06-20 10:17:53164 }
165
huangsdda11d062016-03-14 16:35:39166 Elf32_Off section_table_end =
167 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr));
halyavinc9de6f72015-03-24 15:40:12168 result = std::max(result, section_table_end);
[email protected]39ed9732013-06-20 10:17:53169
huangsdda11d062016-03-14 16:35:39170 Elf32_Off segment_table_end =
171 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr));
halyavinc9de6f72015-03-24 15:40:12172 result = std::max(result, segment_table_end);
[email protected]39ed9732013-06-20 10:17:53173
halyavinc9de6f72015-03-24 15:40:12174 ReduceLength(result);
175 return true;
[email protected]39ed9732013-06-20 10:17:53176}
177
huangsdda11d062016-03-14 16:35:39178CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
huangsbb4b8a92016-01-19 22:09:03179 if (rva == kUnassignedRVA)
180 return false;
[email protected]39ed9732013-06-20 10:17:53181
182 // It's valid if it's contained in any program segment
huangsdda11d062016-03-14 16:35:39183 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
184 ++segment_id) {
185 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
[email protected]39ed9732013-06-20 10:17:53186
187 if (segment_header->p_type != PT_LOAD)
188 continue;
189
190 Elf32_Addr begin = segment_header->p_vaddr;
191 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
192
193 if (rva >= begin && rva < end)
194 return true;
195 }
196
197 return false;
198}
199
huangsdda11d062016-03-14 16:35:39200CheckBool DisassemblerElf32::RVAsToFileOffsets(
201 const std::vector<RVA>& rvas,
202 std::vector<FileOffset>* file_offsets) {
203 file_offsets->clear();
204 for (RVA rva : rvas) {
205 FileOffset file_offset = RVAToFileOffset(rva);
206 if (file_offset == kNoFileOffset)
scottmg4a95ca52016-03-12 23:54:56207 return false;
huangsdda11d062016-03-14 16:35:39208 file_offsets->push_back(file_offset);
scottmg4a95ca52016-03-12 23:54:56209 }
[email protected]39ed9732013-06-20 10:17:53210 return true;
211}
212
huangsdda11d062016-03-14 16:35:39213CheckBool DisassemblerElf32::RVAsToFileOffsets(
214 ScopedVector<TypedRVA>* typed_rvas) {
215 for (TypedRVA* typed_rva : *typed_rvas) {
216 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
217 if (file_offset == kNoFileOffset)
[email protected]144c8e92013-07-23 21:18:19218 return false;
huangsdda11d062016-03-14 16:35:39219 typed_rva->set_file_offset(file_offset);
[email protected]144c8e92013-07-23 21:18:19220 }
[email protected]144c8e92013-07-23 21:18:19221 return true;
222}
223
[email protected]39ed9732013-06-20 10:17:53224CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
225 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39226 FileOffset file_offset = 0;
[email protected]39ed9732013-06-20 10:17:53227
huangsdda11d062016-03-14 16:35:39228 std::vector<FileOffset> abs_offsets;
[email protected]39ed9732013-06-20 10:17:53229
huangsdda11d062016-03-14 16:35:39230 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
[email protected]39ed9732013-06-20 10:17:53231 return false;
232
huangsdda11d062016-03-14 16:35:39233 if (!RVAsToFileOffsets(&rel32_locations_))
[email protected]39ed9732013-06-20 10:17:53234 return false;
235
huangsdda11d062016-03-14 16:35:39236 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin();
[email protected]144c8e92013-07-23 21:18:19237 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin();
[email protected]39ed9732013-06-20 10:17:53238
huangsdda11d062016-03-14 16:35:39239 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end();
[email protected]144c8e92013-07-23 21:18:19240 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end();
[email protected]39ed9732013-06-20 10:17:53241
huangsdda11d062016-03-14 16:35:39242 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
243 ++section_id) {
244 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53245
Will Harris3e6fa972015-03-02 21:14:25246 if (section_header->sh_type == SHT_NOBITS)
247 continue;
248
huangsdda11d062016-03-14 16:35:39249 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program))
[email protected]39ed9732013-06-20 10:17:53250 return false;
huangsdda11d062016-03-14 16:35:39251
[email protected]39ed9732013-06-20 10:17:53252 file_offset = section_header->sh_offset;
253
254 switch (section_header->sh_type) {
255 case SHT_REL:
256 if (!ParseRelocationSection(section_header, program))
257 return false;
258 file_offset = section_header->sh_offset + section_header->sh_size;
259 break;
260 case SHT_PROGBITS:
261 if (!ParseProgbitsSection(section_header,
huangsdda11d062016-03-14 16:35:39262 &current_abs_offset,
263 end_abs_offset,
264 &current_rel,
265 end_rel,
266 program)) {
[email protected]39ed9732013-06-20 10:17:53267 return false;
huangsdda11d062016-03-14 16:35:39268 }
[email protected]39ed9732013-06-20 10:17:53269 file_offset = section_header->sh_offset + section_header->sh_size;
270 break;
[email protected]39ed9732013-06-20 10:17:53271 case SHT_INIT_ARRAY:
272 // Fall through
273 case SHT_FINI_ARRAY:
274 while (current_abs_offset != end_abs_offset &&
275 *current_abs_offset >= section_header->sh_offset &&
276 *current_abs_offset <
huangsdda11d062016-03-14 16:35:39277 section_header->sh_offset + section_header->sh_size) {
[email protected]39ed9732013-06-20 10:17:53278 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
huangsdda11d062016-03-14 16:35:39279 VLOG(1) << "Skipping relocation entry for unsupported section: "
280 << section_header->sh_type;
281 ++current_abs_offset;
[email protected]39ed9732013-06-20 10:17:53282 }
283 break;
284 default:
285 if (current_abs_offset != end_abs_offset &&
huangsdda11d062016-03-14 16:35:39286 *current_abs_offset >= section_header->sh_offset &&
287 *current_abs_offset <
288 section_header->sh_offset + section_header->sh_size) {
289 VLOG(1) << "Relocation address in unrecognized ELF section: "
290 << section_header->sh_type;
291 }
292 break;
[email protected]39ed9732013-06-20 10:17:53293 }
294 }
295
296 // Rest of the file past the last section
huangsdda11d062016-03-14 16:35:39297 if (!ParseSimpleRegion(file_offset, length(), program))
[email protected]39ed9732013-06-20 10:17:53298 return false;
299
300 // Make certain we consume all of the relocations as expected
301 return (current_abs_offset == end_abs_offset);
302}
303
304CheckBool DisassemblerElf32::ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39305 const Elf32_Shdr* section_header,
306 std::vector<FileOffset>::iterator* current_abs_offset,
307 std::vector<FileOffset>::iterator end_abs_offset,
[email protected]144c8e92013-07-23 21:18:19308 ScopedVector<TypedRVA>::iterator* current_rel,
309 ScopedVector<TypedRVA>::iterator end_rel,
[email protected]39ed9732013-06-20 10:17:53310 AssemblyProgram* program) {
[email protected]39ed9732013-06-20 10:17:53311 // Walk all the bytes in the file, whether or not in a section.
huangsdda11d062016-03-14 16:35:39312 FileOffset file_offset = section_header->sh_offset;
313 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
[email protected]39ed9732013-06-20 10:17:53314
315 Elf32_Addr origin = section_header->sh_addr;
huangsdda11d062016-03-14 16:35:39316 FileOffset origin_offset = section_header->sh_offset;
[email protected]39ed9732013-06-20 10:17:53317 if (!program->EmitOriginInstruction(origin))
318 return false;
319
320 while (file_offset < section_end) {
[email protected]39ed9732013-06-20 10:17:53321 if (*current_abs_offset != end_abs_offset &&
322 file_offset > **current_abs_offset)
323 return false;
324
[email protected]144c8e92013-07-23 21:18:19325 while (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39326 file_offset > (**current_rel)->file_offset()) {
327 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53328 }
329
huangsdda11d062016-03-14 16:35:39330 FileOffset next_relocation = section_end;
[email protected]39ed9732013-06-20 10:17:53331
332 if (*current_abs_offset != end_abs_offset &&
333 next_relocation > **current_abs_offset)
334 next_relocation = **current_abs_offset;
335
336 // Rel offsets are heuristically derived, and might (incorrectly) overlap
337 // an Abs value, or the end of the section, so +3 to make sure there is
338 // room for the full 4 byte value.
[email protected]144c8e92013-07-23 21:18:19339 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39340 next_relocation > ((**current_rel)->file_offset() + 3))
341 next_relocation = (**current_rel)->file_offset();
[email protected]39ed9732013-06-20 10:17:53342
343 if (next_relocation > file_offset) {
344 if (!ParseSimpleRegion(file_offset, next_relocation, program))
345 return false;
346
347 file_offset = next_relocation;
348 continue;
349 }
350
351 if (*current_abs_offset != end_abs_offset &&
352 file_offset == **current_abs_offset) {
huangsdda11d062016-03-14 16:35:39353 const uint8_t* p = FileOffsetToPointer(file_offset);
[email protected]39ed9732013-06-20 10:17:53354 RVA target_rva = Read32LittleEndian(p);
355
356 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
357 return false;
358 file_offset += sizeof(RVA);
huangsdda11d062016-03-14 16:35:39359 ++(*current_abs_offset);
[email protected]39ed9732013-06-20 10:17:53360 continue;
361 }
362
[email protected]144c8e92013-07-23 21:18:19363 if (*current_rel != end_rel &&
huangsdda11d062016-03-14 16:35:39364 file_offset == (**current_rel)->file_offset()) {
aviab98dcc92015-12-21 19:35:33365 uint32_t relative_target = (**current_rel)->relative_target();
[email protected]39ed9732013-06-20 10:17:53366 // This cast is for 64 bit systems, and is only safe because we
367 // are working on 32 bit executables.
368 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
[email protected]144c8e92013-07-23 21:18:19369 relative_target);
[email protected]39ed9732013-06-20 10:17:53370
huangsdda11d062016-03-14 16:35:39371 if (!(**current_rel)->EmitInstruction(program, target_rva))
[email protected]39ed9732013-06-20 10:17:53372 return false;
[email protected]2b637b62013-08-01 00:11:24373 file_offset += (**current_rel)->op_size();
huangsdda11d062016-03-14 16:35:39374 ++(*current_rel);
[email protected]39ed9732013-06-20 10:17:53375 continue;
376 }
377 }
378
379 // Rest of the section (if any)
380 return ParseSimpleRegion(file_offset, section_end, program);
381}
382
huangsdda11d062016-03-14 16:35:39383CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset,
384 FileOffset end_file_offset,
385 AssemblyProgram* program) {
[email protected]c092858a2013-08-13 00:46:30386 // Callers don't guarantee start < end
huangsdda11d062016-03-14 16:35:39387 if (start_file_offset >= end_file_offset)
388 return true;
[email protected]39ed9732013-06-20 10:17:53389
pkasting8e3a26a2014-10-03 18:52:29390 const size_t len = end_file_offset - start_file_offset;
[email protected]c092858a2013-08-13 00:46:30391
huangsdda11d062016-03-14 16:35:39392 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
393 len)) {
[email protected]c092858a2013-08-13 00:46:30394 return false;
huangsdda11d062016-03-14 16:35:39395 }
[email protected]39ed9732013-06-20 10:17:53396
397 return true;
398}
399
400CheckBool DisassemblerElf32::ParseAbs32Relocs() {
401 abs32_locations_.clear();
402
403 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39404 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
405 ++section_id) {
406 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53407
408 if (section_header->sh_type == SHT_REL) {
huangsdda11d062016-03-14 16:35:39409 const Elf32_Rel* relocs_table =
410 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id));
[email protected]39ed9732013-06-20 10:17:53411
412 int relocs_table_count = section_header->sh_size /
413 section_header->sh_entsize;
414
415 // Elf32_Word relocation_section_id = section_header->sh_info;
416
417 // Loop through relocation objects in the relocation section
huangsdda11d062016-03-14 16:35:39418 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) {
[email protected]39ed9732013-06-20 10:17:53419 RVA rva;
420
421 // Quite a few of these conversions fail, and we simply skip
422 // them, that's okay.
[email protected]a8e80412013-07-18 22:07:53423 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
[email protected]39ed9732013-06-20 10:17:53424 abs32_locations_.push_back(rva);
425 }
426 }
427 }
428
429 std::sort(abs32_locations_.begin(), abs32_locations_.end());
huangsbb4b8a92016-01-19 22:09:03430 DCHECK(abs32_locations_.empty() ||
431 abs32_locations_.back() != kUnassignedRVA);
[email protected]39ed9732013-06-20 10:17:53432 return true;
433}
434
[email protected]a8e80412013-07-18 22:07:53435CheckBool DisassemblerElf32::CheckSection(RVA rva) {
huangsdda11d062016-03-14 16:35:39436 FileOffset file_offset = RVAToFileOffset(rva);
437 if (file_offset == kNoFileOffset)
[email protected]a8e80412013-07-18 22:07:53438 return false;
[email protected]a8e80412013-07-18 22:07:53439
huangsdda11d062016-03-14 16:35:39440 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
441 ++section_id) {
442 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]a8e80412013-07-18 22:07:53443
huangsdda11d062016-03-14 16:35:39444 if (file_offset >= section_header->sh_offset &&
445 file_offset < (section_header->sh_offset + section_header->sh_size)) {
[email protected]a8e80412013-07-18 22:07:53446 switch (section_header->sh_type) {
huangsdda11d062016-03-14 16:35:39447 case SHT_REL: // Falls through.
[email protected]a8e80412013-07-18 22:07:53448 case SHT_PROGBITS:
449 return true;
450 }
451 }
452 }
453
454 return false;
455}
456
[email protected]39ed9732013-06-20 10:17:53457CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
[email protected]39ed9732013-06-20 10:17:53458 rel32_locations_.clear();
459
460 // Loop through sections for relocation sections
huangsdda11d062016-03-14 16:35:39461 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
462 ++section_id) {
463 const Elf32_Shdr* section_header = SectionHeader(section_id);
[email protected]39ed9732013-06-20 10:17:53464
huangsdda11d062016-03-14 16:35:39465 // TODO(huangs): Add better checks to skip non-code sections.
huangs7ec152c2016-02-04 22:26:43466 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
467 if (section_header->sh_type != SHT_PROGBITS ||
468 section_header->sh_addr == 0)
[email protected]39ed9732013-06-20 10:17:53469 continue;
470
471 if (!ParseRel32RelocsFromSection(section_header))
472 return false;
473 }
474
[email protected]144c8e92013-07-23 21:18:19475 std::sort(rel32_locations_.begin(),
476 rel32_locations_.end(),
477 TypedRVA::IsLessThan);
huangsbb4b8a92016-01-19 22:09:03478 DCHECK(rel32_locations_.empty() ||
479 rel32_locations_.back()->rva() != kUnassignedRVA);
[email protected]39ed9732013-06-20 10:17:53480 return true;
481}
482
483} // namespace courgette