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

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

Powered by Google App Engine
This is Rietveld 408576698