Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: courgette/disassembler_elf_32.cc

Issue 1676683002: [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wrap #include <iostream> under #if COURGETTE_HISTOGRAM_TARGETS. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/disassembler_elf_32.h" 5 #include "courgette/disassembler_elf_32.h"
6 6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm> 7 #include <algorithm>
11 #include <string>
12 #include <vector>
13 8
14 #include "base/logging.h" 9 #include "base/logging.h"
15 #include "base/memory/scoped_vector.h"
16
17 #include "courgette/assembly_program.h" 10 #include "courgette/assembly_program.h"
18 #include "courgette/courgette.h" 11 #include "courgette/courgette.h"
19 #include "courgette/encoded_program.h"
20 12
21 namespace courgette { 13 namespace courgette {
22 14
23 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) 15 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
24 : Disassembler(start, length), 16 : Disassembler(start, length),
25 header_(NULL), 17 header_(nullptr),
26 section_header_table_(NULL), 18 section_header_table_(nullptr),
27 section_header_table_size_(0), 19 section_header_table_size_(0),
28 program_header_table_(NULL), 20 program_header_table_(nullptr),
29 program_header_table_size_(0), 21 program_header_table_size_(0),
30 default_string_section_(NULL) { 22 default_string_section_(nullptr) {
23 }
24
25 RVA 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
48 FileOffset 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;
31 } 62 }
32 63
33 bool DisassemblerElf32::ParseHeader() { 64 bool DisassemblerElf32::ParseHeader() {
34 if (length() < sizeof(Elf32_Ehdr)) 65 if (length() < sizeof(Elf32_Ehdr))
35 return Bad("Too small"); 66 return Bad("Too small");
36 67
37 header_ = (Elf32_Ehdr *)start(); 68 header_ = reinterpret_cast<const Elf32_Ehdr*>(start());
38 69
39 // Have magic for elf header? 70 // Have magic for ELF header?
40 if (header_->e_ident[0] != 0x7f || 71 if (header_->e_ident[0] != 0x7f ||
41 header_->e_ident[1] != 'E' || 72 header_->e_ident[1] != 'E' ||
42 header_->e_ident[2] != 'L' || 73 header_->e_ident[2] != 'L' ||
43 header_->e_ident[3] != 'F') 74 header_->e_ident[3] != 'F')
44 return Bad("No Magic Number"); 75 return Bad("No Magic Number");
45 76
46 if (header_->e_type != ET_EXEC && 77 if (header_->e_type != ET_EXEC &&
47 header_->e_type != ET_DYN) 78 header_->e_type != ET_DYN)
48 return Bad("Not an executable file or shared library"); 79 return Bad("Not an executable file or shared library");
49 80
50 if (header_->e_machine != ElfEM()) 81 if (header_->e_machine != ElfEM())
51 return Bad("Not a supported architecture"); 82 return Bad("Not a supported architecture");
52 83
53 if (header_->e_version != 1) 84 if (header_->e_version != 1)
54 return Bad("Unknown file version"); 85 return Bad("Unknown file version");
55 86
56 if (header_->e_shentsize != sizeof(Elf32_Shdr)) 87 if (header_->e_shentsize != sizeof(Elf32_Shdr))
57 return Bad("Unexpected section header size"); 88 return Bad("Unexpected section header size");
58 89
59 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr))) 90 if (!IsArrayInBounds(header_->e_shoff, header_->e_shnum, sizeof(Elf32_Shdr)))
60 return Bad("Out of bounds section header table"); 91 return Bad("Out of bounds section header table");
61 92
62 section_header_table_ = (Elf32_Shdr *)OffsetToPointer(header_->e_shoff); 93 section_header_table_ = reinterpret_cast<const Elf32_Shdr*>(
94 FileOffsetToPointer(header_->e_shoff));
63 section_header_table_size_ = header_->e_shnum; 95 section_header_table_size_ = header_->e_shnum;
64 96
65 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr))) 97 if (!IsArrayInBounds(header_->e_phoff, header_->e_phnum, sizeof(Elf32_Phdr)))
66 return Bad("Out of bounds program header table"); 98 return Bad("Out of bounds program header table");
67 99
68 program_header_table_ = (Elf32_Phdr *)OffsetToPointer(header_->e_phoff); 100 program_header_table_ = reinterpret_cast<const Elf32_Phdr*>(
101 FileOffsetToPointer(header_->e_phoff));
69 program_header_table_size_ = header_->e_phnum; 102 program_header_table_size_ = header_->e_phnum;
70 103
71 if (header_->e_shstrndx >= header_->e_shnum) 104 if (header_->e_shstrndx >= header_->e_shnum)
72 return Bad("Out of bounds string section index"); 105 return Bad("Out of bounds string section index");
73 106
74 default_string_section_ = (const char *)SectionBody((int)header_->e_shstrndx); 107 default_string_section_ = reinterpret_cast<const char*>(
108 SectionBody(static_cast<int>(header_->e_shstrndx)));
75 109
76 if (!UpdateLength()) { 110 if (!UpdateLength())
77 return Bad("Out of bounds section or segment"); 111 return Bad("Out of bounds section or segment");
78 }
79 112
80 return Good(); 113 return Good();
81 } 114 }
82 115
83 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { 116 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
84 if (!ok()) 117 if (!ok())
85 return false; 118 return false;
86 119
87 // The Image Base is always 0 for ELF Executables 120 // The Image Base is always 0 for ELF Executables
88 target->set_image_base(0); 121 target->set_image_base(0);
89 122
90 if (!ParseAbs32Relocs()) 123 if (!ParseAbs32Relocs())
91 return false; 124 return false;
92 125
93 if (!ParseRel32RelocsFromSections()) 126 if (!ParseRel32RelocsFromSections())
94 return false; 127 return false;
95 128
96 if (!ParseFile(target)) 129 if (!ParseFile(target))
97 return false; 130 return false;
98 131
99 target->DefaultAssignIndexes(); 132 target->DefaultAssignIndexes();
100
101 return true; 133 return true;
102 } 134 }
103 135
104 bool DisassemblerElf32::UpdateLength() { 136 bool DisassemblerElf32::UpdateLength() {
105 Elf32_Off result = 0; 137 Elf32_Off result = 0;
106 138
107 // Find the end of the last section 139 // Find the end of the last section
108 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { 140 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
109 const Elf32_Shdr *section_header = SectionHeader(section_id); 141 ++section_id) {
142 const Elf32_Shdr* section_header = SectionHeader(section_id);
110 143
111 if (section_header->sh_type == SHT_NOBITS) 144 if (section_header->sh_type == SHT_NOBITS)
112 continue; 145 continue;
113 146
114 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1)) 147 if (!IsArrayInBounds(section_header->sh_offset, section_header->sh_size, 1))
115 return false; 148 return false;
116 149
117 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size; 150 Elf32_Off section_end = section_header->sh_offset + section_header->sh_size;
118 result = std::max(result, section_end); 151 result = std::max(result, section_end);
119 } 152 }
120 153
121 // Find the end of the last segment 154 // Find the end of the last segment
122 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { 155 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
123 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); 156 ++segment_id) {
157 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
124 158
125 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1)) 159 if (!IsArrayInBounds(segment_header->p_offset, segment_header->p_filesz, 1))
126 return false; 160 return false;
127 161
128 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz; 162 Elf32_Off segment_end = segment_header->p_offset + segment_header->p_filesz;
129 result = std::max(result, segment_end); 163 result = std::max(result, segment_end);
130 } 164 }
131 165
132 Elf32_Off section_table_end = header_->e_shoff + 166 Elf32_Off section_table_end =
133 (header_->e_shnum * sizeof(Elf32_Shdr)); 167 header_->e_shoff + (header_->e_shnum * sizeof(Elf32_Shdr));
134 result = std::max(result, section_table_end); 168 result = std::max(result, section_table_end);
135 169
136 Elf32_Off segment_table_end = header_->e_phoff + 170 Elf32_Off segment_table_end =
137 (header_->e_phnum * sizeof(Elf32_Phdr)); 171 header_->e_phoff + (header_->e_phnum * sizeof(Elf32_Phdr));
138 result = std::max(result, segment_table_end); 172 result = std::max(result, segment_table_end);
139 173
140 ReduceLength(result); 174 ReduceLength(result);
141 return true; 175 return true;
142 } 176 }
143 177
144 CheckBool DisassemblerElf32::IsValidRVA(RVA rva) const { 178 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
145 if (rva == kUnassignedRVA) 179 if (rva == kUnassignedRVA)
146 return false; 180 return false;
147 181
148 // It's valid if it's contained in any program segment 182 // It's valid if it's contained in any program segment
149 for (int i = 0; i < ProgramSegmentHeaderCount(); i++) { 183 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
150 const Elf32_Phdr *segment_header = ProgramSegmentHeader(i); 184 ++segment_id) {
185 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
151 186
152 if (segment_header->p_type != PT_LOAD) 187 if (segment_header->p_type != PT_LOAD)
153 continue; 188 continue;
154 189
155 Elf32_Addr begin = segment_header->p_vaddr; 190 Elf32_Addr begin = segment_header->p_vaddr;
156 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz; 191 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
157 192
158 if (rva >= begin && rva < end) 193 if (rva >= begin && rva < end)
159 return true; 194 return true;
160 } 195 }
161 196
162 return false; 197 return false;
163 } 198 }
164 199
165 CheckBool DisassemblerElf32::RVAToFileOffset(RVA rva, 200 CheckBool DisassemblerElf32::RVAsToFileOffsets(
166 size_t* result) const { 201 const std::vector<RVA>& rvas,
167 for (int i = 0; i < SectionHeaderCount(); i++) { 202 std::vector<FileOffset>* file_offsets) {
168 const Elf32_Shdr *section_header = SectionHeader(i); 203 file_offsets->clear();
169 // These can appear to have a size in the file, but don't. 204 for (RVA rva : rvas) {
170 if (section_header->sh_type == SHT_NOBITS) 205 FileOffset file_offset = RVAToFileOffset(rva);
171 continue; 206 if (file_offset == kNoFileOffset)
172 Elf32_Addr begin = section_header->sh_addr; 207 return false;
173 Elf32_Addr end = begin + section_header->sh_size; 208 file_offsets->push_back(file_offset);
174
175 if (rva >= begin && rva < end) {
176 *result = section_header->sh_offset + (rva - begin);
177 return true;
178 }
179 } 209 }
180 return false;
181 }
182
183 RVA DisassemblerElf32::FileOffsetToRVA(size_t offset) const {
184 // File offsets can be 64 bit values, but we are dealing with 32
185 // bit executables and so only need to support 32bit file sizes.
186 uint32_t offset32 = (uint32_t)offset;
187
188 for (int i = 0; i < SectionHeaderCount(); i++) {
189
190 const Elf32_Shdr *section_header = SectionHeader(i);
191
192 // These can appear to have a size in the file, but don't.
193 if (section_header->sh_type == SHT_NOBITS)
194 continue;
195
196 Elf32_Off section_begin = section_header->sh_offset;
197 Elf32_Off section_end = section_begin + section_header->sh_size;
198
199 if (offset32 >= section_begin && offset32 < section_end) {
200 return section_header->sh_addr + (offset32 - section_begin);
201 }
202 }
203
204 return 0;
205 }
206
207 CheckBool DisassemblerElf32::RVAsToOffsets(std::vector<RVA>* rvas,
208 std::vector<size_t>* offsets) {
209 offsets->clear();
210
211 for (std::vector<RVA>::iterator rva = rvas->begin();
212 rva != rvas->end();
213 rva++) {
214
215 size_t offset;
216
217 if (!RVAToFileOffset(*rva, &offset))
218 return false;
219
220 offsets->push_back(offset);
221 }
222
223 return true; 210 return true;
224 } 211 }
225 212
226 CheckBool DisassemblerElf32::RVAsToOffsets(ScopedVector<TypedRVA>* rvas) { 213 CheckBool DisassemblerElf32::RVAsToFileOffsets(
227 for (ScopedVector<TypedRVA>::iterator rva = rvas->begin(); 214 ScopedVector<TypedRVA>* typed_rvas) {
228 rva != rvas->end(); 215 for (TypedRVA* typed_rva : *typed_rvas) {
229 rva++) { 216 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
230 217 if (file_offset == kNoFileOffset)
231 size_t offset;
232
233 if (!RVAToFileOffset((*rva)->rva(), &offset))
234 return false; 218 return false;
235 219 typed_rva->set_file_offset(file_offset);
236 (*rva)->set_offset(offset);
237 } 220 }
238
239 return true; 221 return true;
240 } 222 }
241 223
242 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { 224 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
243 // Walk all the bytes in the file, whether or not in a section. 225 // Walk all the bytes in the file, whether or not in a section.
244 uint32_t file_offset = 0; 226 FileOffset file_offset = 0;
245 227
246 std::vector<size_t> abs_offsets; 228 std::vector<FileOffset> abs_offsets;
247 229
248 if (!RVAsToOffsets(&abs32_locations_, &abs_offsets)) 230 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
249 return false; 231 return false;
250 232
251 if (!RVAsToOffsets(&rel32_locations_)) 233 if (!RVAsToFileOffsets(&rel32_locations_))
252 return false; 234 return false;
253 235
254 std::vector<size_t>::iterator current_abs_offset = abs_offsets.begin(); 236 std::vector<FileOffset>::iterator current_abs_offset = abs_offsets.begin();
255 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin(); 237 ScopedVector<TypedRVA>::iterator current_rel = rel32_locations_.begin();
256 238
257 std::vector<size_t>::iterator end_abs_offset = abs_offsets.end(); 239 std::vector<FileOffset>::iterator end_abs_offset = abs_offsets.end();
258 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end(); 240 ScopedVector<TypedRVA>::iterator end_rel = rel32_locations_.end();
259 241
260 for (int section_id = 0; 242 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
261 section_id < SectionHeaderCount(); 243 ++section_id) {
262 section_id++) { 244 const Elf32_Shdr* section_header = SectionHeader(section_id);
263
264 const Elf32_Shdr *section_header = SectionHeader(section_id);
265 245
266 if (section_header->sh_type == SHT_NOBITS) 246 if (section_header->sh_type == SHT_NOBITS)
267 continue; 247 continue;
268 248
269 if (!ParseSimpleRegion(file_offset, 249 if (!ParseSimpleRegion(file_offset, section_header->sh_offset, program))
270 section_header->sh_offset,
271 program))
272 return false; 250 return false;
251
273 file_offset = section_header->sh_offset; 252 file_offset = section_header->sh_offset;
274 253
275 switch (section_header->sh_type) { 254 switch (section_header->sh_type) {
276 case SHT_REL: 255 case SHT_REL:
277 if (!ParseRelocationSection(section_header, program)) 256 if (!ParseRelocationSection(section_header, program))
278 return false; 257 return false;
279 file_offset = section_header->sh_offset + section_header->sh_size; 258 file_offset = section_header->sh_offset + section_header->sh_size;
280 break; 259 break;
281 case SHT_PROGBITS: 260 case SHT_PROGBITS:
282 if (!ParseProgbitsSection(section_header, 261 if (!ParseProgbitsSection(section_header,
283 &current_abs_offset, end_abs_offset, 262 &current_abs_offset,
284 &current_rel, end_rel, 263 end_abs_offset,
285 program)) 264 &current_rel,
265 end_rel,
266 program)) {
286 return false; 267 return false;
268 }
287 file_offset = section_header->sh_offset + section_header->sh_size; 269 file_offset = section_header->sh_offset + section_header->sh_size;
288 break; 270 break;
289 case SHT_INIT_ARRAY: 271 case SHT_INIT_ARRAY:
290 // Fall through 272 // Fall through
291 case SHT_FINI_ARRAY: 273 case SHT_FINI_ARRAY:
292 while (current_abs_offset != end_abs_offset && 274 while (current_abs_offset != end_abs_offset &&
293 *current_abs_offset >= section_header->sh_offset && 275 *current_abs_offset >= section_header->sh_offset &&
294 *current_abs_offset < 276 *current_abs_offset <
295 (section_header->sh_offset + section_header->sh_size)) { 277 section_header->sh_offset + section_header->sh_size) {
296 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section 278 // Skip any abs_offsets appear in the unsupported INIT_ARRAY section
297 VLOG(1) << "Skipping relocation entry for unsupported section: " << 279 VLOG(1) << "Skipping relocation entry for unsupported section: "
298 section_header->sh_type; 280 << section_header->sh_type;
299 current_abs_offset++; 281 ++current_abs_offset;
300 } 282 }
301 break; 283 break;
302 default: 284 default:
303 if (current_abs_offset != end_abs_offset && 285 if (current_abs_offset != end_abs_offset &&
304 *current_abs_offset >= section_header->sh_offset && 286 *current_abs_offset >= section_header->sh_offset &&
305 *current_abs_offset < 287 *current_abs_offset <
306 (section_header->sh_offset + section_header->sh_size)) 288 section_header->sh_offset + section_header->sh_size) {
307 VLOG(1) << "Relocation address in unrecognized ELF section: " << \ 289 VLOG(1) << "Relocation address in unrecognized ELF section: "
308 section_header->sh_type; 290 << section_header->sh_type;
309 break; 291 }
292 break;
310 } 293 }
311 } 294 }
312 295
313 // Rest of the file past the last section 296 // Rest of the file past the last section
314 if (!ParseSimpleRegion(file_offset, 297 if (!ParseSimpleRegion(file_offset, length(), program))
315 length(),
316 program))
317 return false; 298 return false;
318 299
319 // Make certain we consume all of the relocations as expected 300 // Make certain we consume all of the relocations as expected
320 return (current_abs_offset == end_abs_offset); 301 return (current_abs_offset == end_abs_offset);
321 } 302 }
322 303
323 CheckBool DisassemblerElf32::ParseProgbitsSection( 304 CheckBool DisassemblerElf32::ParseProgbitsSection(
324 const Elf32_Shdr *section_header, 305 const Elf32_Shdr* section_header,
325 std::vector<size_t>::iterator* current_abs_offset, 306 std::vector<FileOffset>::iterator* current_abs_offset,
326 std::vector<size_t>::iterator end_abs_offset, 307 std::vector<FileOffset>::iterator end_abs_offset,
327 ScopedVector<TypedRVA>::iterator* current_rel, 308 ScopedVector<TypedRVA>::iterator* current_rel,
328 ScopedVector<TypedRVA>::iterator end_rel, 309 ScopedVector<TypedRVA>::iterator end_rel,
329 AssemblyProgram* program) { 310 AssemblyProgram* program) {
330
331 // Walk all the bytes in the file, whether or not in a section. 311 // Walk all the bytes in the file, whether or not in a section.
332 size_t file_offset = section_header->sh_offset; 312 FileOffset file_offset = section_header->sh_offset;
333 size_t section_end = section_header->sh_offset + section_header->sh_size; 313 FileOffset section_end = section_header->sh_offset + section_header->sh_size;
334 314
335 Elf32_Addr origin = section_header->sh_addr; 315 Elf32_Addr origin = section_header->sh_addr;
336 size_t origin_offset = section_header->sh_offset; 316 FileOffset origin_offset = section_header->sh_offset;
337 if (!program->EmitOriginInstruction(origin)) 317 if (!program->EmitOriginInstruction(origin))
338 return false; 318 return false;
339 319
340 while (file_offset < section_end) { 320 while (file_offset < section_end) {
341
342 if (*current_abs_offset != end_abs_offset && 321 if (*current_abs_offset != end_abs_offset &&
343 file_offset > **current_abs_offset) 322 file_offset > **current_abs_offset)
344 return false; 323 return false;
345 324
346 while (*current_rel != end_rel && 325 while (*current_rel != end_rel &&
347 file_offset > (**current_rel)->get_offset()) { 326 file_offset > (**current_rel)->file_offset()) {
348 (*current_rel)++; 327 ++(*current_rel);
349 } 328 }
350 329
351 size_t next_relocation = section_end; 330 FileOffset next_relocation = section_end;
352 331
353 if (*current_abs_offset != end_abs_offset && 332 if (*current_abs_offset != end_abs_offset &&
354 next_relocation > **current_abs_offset) 333 next_relocation > **current_abs_offset)
355 next_relocation = **current_abs_offset; 334 next_relocation = **current_abs_offset;
356 335
357 // Rel offsets are heuristically derived, and might (incorrectly) overlap 336 // Rel offsets are heuristically derived, and might (incorrectly) overlap
358 // an Abs value, or the end of the section, so +3 to make sure there is 337 // an Abs value, or the end of the section, so +3 to make sure there is
359 // room for the full 4 byte value. 338 // room for the full 4 byte value.
360 if (*current_rel != end_rel && 339 if (*current_rel != end_rel &&
361 next_relocation > ((**current_rel)->get_offset() + 3)) 340 next_relocation > ((**current_rel)->file_offset() + 3))
362 next_relocation = (**current_rel)->get_offset(); 341 next_relocation = (**current_rel)->file_offset();
363 342
364 if (next_relocation > file_offset) { 343 if (next_relocation > file_offset) {
365 if (!ParseSimpleRegion(file_offset, next_relocation, program)) 344 if (!ParseSimpleRegion(file_offset, next_relocation, program))
366 return false; 345 return false;
367 346
368 file_offset = next_relocation; 347 file_offset = next_relocation;
369 continue; 348 continue;
370 } 349 }
371 350
372 if (*current_abs_offset != end_abs_offset && 351 if (*current_abs_offset != end_abs_offset &&
373 file_offset == **current_abs_offset) { 352 file_offset == **current_abs_offset) {
374 const uint8_t* p = OffsetToPointer(file_offset); 353 const uint8_t* p = FileOffsetToPointer(file_offset);
375 RVA target_rva = Read32LittleEndian(p); 354 RVA target_rva = Read32LittleEndian(p);
376 355
377 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) 356 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
378 return false; 357 return false;
379 file_offset += sizeof(RVA); 358 file_offset += sizeof(RVA);
380 (*current_abs_offset)++; 359 ++(*current_abs_offset);
381 continue; 360 continue;
382 } 361 }
383 362
384 if (*current_rel != end_rel && 363 if (*current_rel != end_rel &&
385 file_offset == (**current_rel)->get_offset()) { 364 file_offset == (**current_rel)->file_offset()) {
386 uint32_t relative_target = (**current_rel)->relative_target(); 365 uint32_t relative_target = (**current_rel)->relative_target();
387 // This cast is for 64 bit systems, and is only safe because we 366 // This cast is for 64 bit systems, and is only safe because we
388 // are working on 32 bit executables. 367 // are working on 32 bit executables.
389 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + 368 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
390 relative_target); 369 relative_target);
391 370
392 if (! (**current_rel)->EmitInstruction(program, target_rva)) 371 if (!(**current_rel)->EmitInstruction(program, target_rva))
393 return false; 372 return false;
394 file_offset += (**current_rel)->op_size(); 373 file_offset += (**current_rel)->op_size();
395 (*current_rel)++; 374 ++(*current_rel);
396 continue; 375 continue;
397 } 376 }
398 } 377 }
399 378
400 // Rest of the section (if any) 379 // Rest of the section (if any)
401 return ParseSimpleRegion(file_offset, section_end, program); 380 return ParseSimpleRegion(file_offset, section_end, program);
402 } 381 }
403 382
404 CheckBool DisassemblerElf32::ParseSimpleRegion( 383 CheckBool DisassemblerElf32::ParseSimpleRegion(FileOffset start_file_offset,
405 size_t start_file_offset, 384 FileOffset end_file_offset,
406 size_t end_file_offset, 385 AssemblyProgram* program) {
407 AssemblyProgram* program) {
408 // Callers don't guarantee start < end 386 // Callers don't guarantee start < end
409 if (start_file_offset >= end_file_offset) return true; 387 if (start_file_offset >= end_file_offset)
388 return true;
410 389
411 const size_t len = end_file_offset - start_file_offset; 390 const size_t len = end_file_offset - start_file_offset;
412 391
413 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), len)) 392 if (!program->EmitBytesInstruction(FileOffsetToPointer(start_file_offset),
393 len)) {
414 return false; 394 return false;
395 }
415 396
416 return true; 397 return true;
417 } 398 }
418 399
419 CheckBool DisassemblerElf32::ParseAbs32Relocs() { 400 CheckBool DisassemblerElf32::ParseAbs32Relocs() {
420 abs32_locations_.clear(); 401 abs32_locations_.clear();
421 402
422 // Loop through sections for relocation sections 403 // Loop through sections for relocation sections
423 for (int section_id = 0; section_id < SectionHeaderCount(); section_id++) { 404 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
424 const Elf32_Shdr *section_header = SectionHeader(section_id); 405 ++section_id) {
406 const Elf32_Shdr* section_header = SectionHeader(section_id);
425 407
426 if (section_header->sh_type == SHT_REL) { 408 if (section_header->sh_type == SHT_REL) {
427 409 const Elf32_Rel* relocs_table =
428 Elf32_Rel *relocs_table = (Elf32_Rel *)SectionBody(section_id); 410 reinterpret_cast<const Elf32_Rel*>(SectionBody(section_id));
429 411
430 int relocs_table_count = section_header->sh_size / 412 int relocs_table_count = section_header->sh_size /
431 section_header->sh_entsize; 413 section_header->sh_entsize;
432 414
433 // Elf32_Word relocation_section_id = section_header->sh_info; 415 // Elf32_Word relocation_section_id = section_header->sh_info;
434 416
435 // Loop through relocation objects in the relocation section 417 // Loop through relocation objects in the relocation section
436 for (int rel_id = 0; rel_id < relocs_table_count; rel_id++) { 418 for (int rel_id = 0; rel_id < relocs_table_count; ++rel_id) {
437 RVA rva; 419 RVA rva;
438 420
439 // Quite a few of these conversions fail, and we simply skip 421 // Quite a few of these conversions fail, and we simply skip
440 // them, that's okay. 422 // them, that's okay.
441 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva)) 423 if (RelToRVA(relocs_table[rel_id], &rva) && CheckSection(rva))
442 abs32_locations_.push_back(rva); 424 abs32_locations_.push_back(rva);
443 } 425 }
444 } 426 }
445 } 427 }
446 428
447 std::sort(abs32_locations_.begin(), abs32_locations_.end()); 429 std::sort(abs32_locations_.begin(), abs32_locations_.end());
448 DCHECK(abs32_locations_.empty() || 430 DCHECK(abs32_locations_.empty() ||
449 abs32_locations_.back() != kUnassignedRVA); 431 abs32_locations_.back() != kUnassignedRVA);
450 return true; 432 return true;
451 } 433 }
452 434
453 CheckBool DisassemblerElf32::CheckSection(RVA rva) { 435 CheckBool DisassemblerElf32::CheckSection(RVA rva) {
454 size_t offset; 436 FileOffset file_offset = RVAToFileOffset(rva);
437 if (file_offset == kNoFileOffset)
438 return false;
455 439
456 if (!RVAToFileOffset(rva, &offset)) { 440 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
457 return false; 441 ++section_id) {
458 } 442 const Elf32_Shdr* section_header = SectionHeader(section_id);
459 443
460 for (int section_id = 0; 444 if (file_offset >= section_header->sh_offset &&
461 section_id < SectionHeaderCount(); 445 file_offset < (section_header->sh_offset + section_header->sh_size)) {
462 section_id++) {
463
464 const Elf32_Shdr *section_header = SectionHeader(section_id);
465
466 if (offset >= section_header->sh_offset &&
467 offset < (section_header->sh_offset + section_header->sh_size)) {
468 switch (section_header->sh_type) { 446 switch (section_header->sh_type) {
469 case SHT_REL: 447 case SHT_REL: // Falls through.
470 // Fall-through
471 case SHT_PROGBITS: 448 case SHT_PROGBITS:
472 return true; 449 return true;
473 } 450 }
474 } 451 }
475 } 452 }
476 453
477 return false; 454 return false;
478 } 455 }
479 456
480 CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() { 457 CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
481
482 rel32_locations_.clear(); 458 rel32_locations_.clear();
483 459
484 // Loop through sections for relocation sections 460 // Loop through sections for relocation sections
485 for (int section_id = 0; 461 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
486 section_id < SectionHeaderCount(); 462 ++section_id) {
487 section_id++) { 463 const Elf32_Shdr* section_header = SectionHeader(section_id);
488 464
489 const Elf32_Shdr *section_header = SectionHeader(section_id); 465 // TODO(huangs): Add better checks to skip non-code sections.
490
491 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0. 466 // Some debug sections can have sh_type=SHT_PROGBITS but sh_addr=0.
492 if (section_header->sh_type != SHT_PROGBITS || 467 if (section_header->sh_type != SHT_PROGBITS ||
493 section_header->sh_addr == 0) 468 section_header->sh_addr == 0)
494 continue; 469 continue;
495 470
496 if (!ParseRel32RelocsFromSection(section_header)) 471 if (!ParseRel32RelocsFromSection(section_header))
497 return false; 472 return false;
498 } 473 }
499 474
500 std::sort(rel32_locations_.begin(), 475 std::sort(rel32_locations_.begin(),
501 rel32_locations_.end(), 476 rel32_locations_.end(),
502 TypedRVA::IsLessThan); 477 TypedRVA::IsLessThan);
503 DCHECK(rel32_locations_.empty() || 478 DCHECK(rel32_locations_.empty() ||
504 rel32_locations_.back()->rva() != kUnassignedRVA); 479 rel32_locations_.back()->rva() != kUnassignedRVA);
505 return true; 480 return true;
506 } 481 }
507 482
508 } // namespace courgette 483 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698