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

Side by Side Diff: courgette/disassembler_win32_x64.cc

Issue 1543643002: Switch to standard integer types in courgette/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 5 years 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_win32_x64.h ('k') | courgette/disassembler_win32_x64_unittest.cc » ('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_win32_x64.h" 5 #include "courgette/disassembler_win32_x64.h"
6 6
7 #include <stddef.h>
8 #include <stdint.h>
9
7 #include <algorithm> 10 #include <algorithm>
8 #include <string> 11 #include <string>
9 #include <vector> 12 #include <vector>
10 13
11 #include "base/basictypes.h"
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "base/numerics/safe_conversions.h" 15 #include "base/numerics/safe_conversions.h"
14 16
15 #include "courgette/assembly_program.h" 17 #include "courgette/assembly_program.h"
16 #include "courgette/courgette.h" 18 #include "courgette/courgette.h"
17 #include "courgette/encoded_program.h" 19 #include "courgette/encoded_program.h"
18 20
19 namespace courgette { 21 namespace courgette {
20 22
21 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length) 23 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length)
(...skipping 26 matching lines...) Expand all
48 // 50 //
49 bool DisassemblerWin32X64::ParseHeader() { 51 bool DisassemblerWin32X64::ParseHeader() {
50 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/) 52 if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
51 return Bad("Too small"); 53 return Bad("Too small");
52 54
53 // Have 'MZ' magic for a DOS header? 55 // Have 'MZ' magic for a DOS header?
54 if (start()[0] != 'M' || start()[1] != 'Z') 56 if (start()[0] != 'M' || start()[1] != 'Z')
55 return Bad("Not MZ"); 57 return Bad("Not MZ");
56 58
57 // offset from DOS header to PE header is stored in DOS header. 59 // offset from DOS header to PE header is stored in DOS header.
58 uint32 offset = ReadU32(start(), 60 uint32_t offset = ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader);
59 kOffsetOfFileAddressOfNewExeHeader);
60 61
61 if (offset >= length()) 62 if (offset >= length())
62 return Bad("Bad offset to PE header"); 63 return Bad("Bad offset to PE header");
63 64
64 const uint8* const pe_header = OffsetToPointer(offset); 65 const uint8_t* const pe_header = OffsetToPointer(offset);
65 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader; 66 const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
66 if (pe_header <= start() || 67 if (pe_header <= start() ||
67 pe_header >= end() - kMinPEHeaderSize) 68 pe_header >= end() - kMinPEHeaderSize)
68 return Bad("Bad offset to PE header"); 69 return Bad("Bad offset to PE header");
69 70
70 if (offset % 8 != 0) 71 if (offset % 8 != 0)
71 return Bad("Misaligned PE header"); 72 return Bad("Misaligned PE header");
72 73
73 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H. 74 // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H.
74 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx 75 // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
75 // 76 //
76 // The first field of the IMAGE_NT_HEADERS is the signature. 77 // The first field of the IMAGE_NT_HEADERS is the signature.
77 if (!(pe_header[0] == 'P' && 78 if (!(pe_header[0] == 'P' &&
78 pe_header[1] == 'E' && 79 pe_header[1] == 'E' &&
79 pe_header[2] == 0 && 80 pe_header[2] == 0 &&
80 pe_header[3] == 0)) 81 pe_header[3] == 0))
81 return Bad("no PE signature"); 82 return Bad("no PE signature");
82 83
83 // The second field of the IMAGE_NT_HEADERS is the COFF header. 84 // The second field of the IMAGE_NT_HEADERS is the COFF header.
84 // The COFF header is also called an IMAGE_FILE_HEADER 85 // The COFF header is also called an IMAGE_FILE_HEADER
85 // http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx 86 // http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx
86 const uint8* const coff_header = pe_header + 4; 87 const uint8_t* const coff_header = pe_header + 4;
87 machine_type_ = ReadU16(coff_header, 0); 88 machine_type_ = ReadU16(coff_header, 0);
88 number_of_sections_ = ReadU16(coff_header, 2); 89 number_of_sections_ = ReadU16(coff_header, 2);
89 size_of_optional_header_ = ReadU16(coff_header, 16); 90 size_of_optional_header_ = ReadU16(coff_header, 16);
90 91
91 // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64) 92 // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64)
92 const uint8* const optional_header = coff_header + kSizeOfCoffHeader; 93 const uint8_t* const optional_header = coff_header + kSizeOfCoffHeader;
93 optional_header_ = optional_header; 94 optional_header_ = optional_header;
94 95
95 if (optional_header + size_of_optional_header_ >= end()) 96 if (optional_header + size_of_optional_header_ >= end())
96 return Bad("optional header past end of file"); 97 return Bad("optional header past end of file");
97 98
98 // Check we can read the magic. 99 // Check we can read the magic.
99 if (size_of_optional_header_ < 2) 100 if (size_of_optional_header_ < 2)
100 return Bad("optional header no magic"); 101 return Bad("optional header no magic");
101 102
102 uint16 magic = ReadU16(optional_header, 0); 103 uint16_t magic = ReadU16(optional_header, 0);
103 104
104 if (magic == kImageNtOptionalHdr32Magic) { 105 if (magic == kImageNtOptionalHdr32Magic) {
105 is_PE32_plus_ = false; 106 is_PE32_plus_ = false;
106 offset_of_data_directories_ = 107 offset_of_data_directories_ =
107 kOffsetOfDataDirectoryFromImageOptionalHeader32; 108 kOffsetOfDataDirectoryFromImageOptionalHeader32;
108 } else if (magic == kImageNtOptionalHdr64Magic) { 109 } else if (magic == kImageNtOptionalHdr64Magic) {
109 is_PE32_plus_ = true; 110 is_PE32_plus_ = true;
110 offset_of_data_directories_ = 111 offset_of_data_directories_ =
111 kOffsetOfDataDirectoryFromImageOptionalHeader64; 112 kOffsetOfDataDirectoryFromImageOptionalHeader64;
112 } else { 113 } else {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 size_t detected_length = 0; 170 size_t detected_length = 0;
170 171
171 for (int i = 0; i < number_of_sections_; ++i) { 172 for (int i = 0; i < number_of_sections_; ++i) {
172 const Section* section = &sections_[i]; 173 const Section* section = &sections_[i];
173 174
174 // TODO(sra): consider using the 'characteristics' field of the section 175 // TODO(sra): consider using the 'characteristics' field of the section
175 // header to see if the section contains instructions. 176 // header to see if the section contains instructions.
176 if (memcmp(section->name, ".text", 6) == 0) 177 if (memcmp(section->name, ".text", 6) == 0)
177 has_text_section_ = true; 178 has_text_section_ = true;
178 179
179 uint32 section_end = 180 uint32_t section_end =
180 section->file_offset_of_raw_data + section->size_of_raw_data; 181 section->file_offset_of_raw_data + section->size_of_raw_data;
181 if (section_end > detected_length) 182 if (section_end > detected_length)
182 detected_length = section_end; 183 detected_length = section_end;
183 } 184 }
184 185
185 // Pretend our in-memory copy is only as long as our detected length. 186 // Pretend our in-memory copy is only as long as our detected length.
186 ReduceLength(detected_length); 187 ReduceLength(detected_length);
187 188
188 if (is_32bit()) { 189 if (is_32bit()) {
189 return Bad("32 bit executables are not supported by this disassembler"); 190 return Bad("32 bit executables are not supported by this disassembler");
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 223
223 size_t relocs_size = base_relocation_table_.size_; 224 size_t relocs_size = base_relocation_table_.size_;
224 if (relocs_size == 0) 225 if (relocs_size == 0)
225 return true; 226 return true;
226 227
227 // The format of the base relocation table is a sequence of variable sized 228 // The format of the base relocation table is a sequence of variable sized
228 // IMAGE_BASE_RELOCATION blocks. Search for 229 // IMAGE_BASE_RELOCATION blocks. Search for
229 // "The format of the base relocation data is somewhat quirky" 230 // "The format of the base relocation data is somewhat quirky"
230 // at http://msdn.microsoft.com/en-us/library/ms809762.aspx 231 // at http://msdn.microsoft.com/en-us/library/ms809762.aspx
231 232
232 const uint8* relocs_start = RVAToPointer(base_relocation_table_.address_); 233 const uint8_t* relocs_start = RVAToPointer(base_relocation_table_.address_);
233 const uint8* relocs_end = relocs_start + relocs_size; 234 const uint8_t* relocs_end = relocs_start + relocs_size;
234 235
235 // Make sure entire base relocation table is within the buffer. 236 // Make sure entire base relocation table is within the buffer.
236 if (relocs_start < start() || 237 if (relocs_start < start() ||
237 relocs_start >= end() || 238 relocs_start >= end() ||
238 relocs_end <= start() || 239 relocs_end <= start() ||
239 relocs_end > end()) { 240 relocs_end > end()) {
240 return Bad(".relocs outside image"); 241 return Bad(".relocs outside image");
241 } 242 }
242 243
243 const uint8* block = relocs_start; 244 const uint8_t* block = relocs_start;
244 245
245 // Walk the variable sized blocks. 246 // Walk the variable sized blocks.
246 while (block + 8 < relocs_end) { 247 while (block + 8 < relocs_end) {
247 RVA page_rva = ReadU32(block, 0); 248 RVA page_rva = ReadU32(block, 0);
248 uint32 size = ReadU32(block, 4); 249 uint32_t size = ReadU32(block, 4);
249 if (size < 8 || // Size includes header ... 250 if (size < 8 || // Size includes header ...
250 size % 4 != 0) // ... and is word aligned. 251 size % 4 != 0) // ... and is word aligned.
251 return Bad("unreasonable relocs block"); 252 return Bad("unreasonable relocs block");
252 253
253 const uint8* end_entries = block + size; 254 const uint8_t* end_entries = block + size;
254 255
255 if (end_entries <= block || 256 if (end_entries <= block ||
256 end_entries <= start() || 257 end_entries <= start() ||
257 end_entries > end()) 258 end_entries > end())
258 return Bad(".relocs block outside image"); 259 return Bad(".relocs block outside image");
259 260
260 // Walk through the two-byte entries. 261 // Walk through the two-byte entries.
261 for (const uint8* p = block + 8; p < end_entries; p += 2) { 262 for (const uint8_t* p = block + 8; p < end_entries; p += 2) {
262 uint16 entry = ReadU16(p, 0); 263 uint16_t entry = ReadU16(p, 0);
263 int type = entry >> 12; 264 int type = entry >> 12;
264 int offset = entry & 0xFFF; 265 int offset = entry & 0xFFF;
265 266
266 RVA rva = page_rva + offset; 267 RVA rva = page_rva + offset;
267 // TODO(sebmarchand): Skip the relocs that live outside of the image. See 268 // TODO(sebmarchand): Skip the relocs that live outside of the image. See
268 // the version of this function in disassembler_win32_x86.cc. 269 // the version of this function in disassembler_win32_x86.cc.
269 if (type == 10) { // IMAGE_REL_BASED_DIR64 270 if (type == 10) { // IMAGE_REL_BASED_DIR64
270 relocs->push_back(rva); 271 relocs->push_back(rva);
271 } else if (type == 0) { // IMAGE_REL_BASED_ABSOLUTE 272 } else if (type == 0) { // IMAGE_REL_BASED_ABSOLUTE
272 // Ignore, used as padding. 273 // Ignore, used as padding.
273 } else { 274 } else {
274 // Does not occur in Windows x64 executables. 275 // Does not occur in Windows x64 executables.
275 return Bad("unknown type of reloc"); 276 return Bad("unknown type of reloc");
276 } 277 }
277 } 278 }
278 279
279 block += size; 280 block += size;
280 } 281 }
281 282
282 std::sort(relocs->begin(), relocs->end()); 283 std::sort(relocs->begin(), relocs->end());
283 284
284 return true; 285 return true;
285 } 286 }
286 287
287 const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const { 288 const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const {
288 for (int i = 0; i < number_of_sections_; i++) { 289 for (int i = 0; i < number_of_sections_; i++) {
289 const Section* section = &sections_[i]; 290 const Section* section = &sections_[i];
290 uint32 offset = rva - section->virtual_address; 291 uint32_t offset = rva - section->virtual_address;
291 if (offset < section->virtual_size) { 292 if (offset < section->virtual_size) {
292 return section; 293 return section;
293 } 294 }
294 } 295 }
295 return NULL; 296 return NULL;
296 } 297 }
297 298
298 int DisassemblerWin32X64::RVAToFileOffset(RVA rva) const { 299 int DisassemblerWin32X64::RVAToFileOffset(RVA rva) const {
299 const Section* section = RVAToSection(rva); 300 const Section* section = RVAToSection(rva);
300 if (section) { 301 if (section) {
301 uint32 offset = rva - section->virtual_address; 302 uint32_t offset = rva - section->virtual_address;
302 if (offset < section->size_of_raw_data) { 303 if (offset < section->size_of_raw_data) {
303 return section->file_offset_of_raw_data + offset; 304 return section->file_offset_of_raw_data + offset;
304 } else { 305 } else {
305 return kNoOffset; // In section but not in file (e.g. uninit data). 306 return kNoOffset; // In section but not in file (e.g. uninit data).
306 } 307 }
307 } 308 }
308 309
309 // Small RVA values point into the file header in the loaded image. 310 // Small RVA values point into the file header in the loaded image.
310 // RVA 0 is the module load address which Windows uses as the module handle. 311 // RVA 0 is the module load address which Windows uses as the module handle.
311 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the 312 // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
312 // DOS header. 313 // DOS header.
313 if (rva == 0 || rva == 2) 314 if (rva == 0 || rva == 2)
314 return rva; 315 return rva;
315 316
316 NOTREACHED(); 317 NOTREACHED();
317 return kNoOffset; 318 return kNoOffset;
318 } 319 }
319 320
320 const uint8* DisassemblerWin32X64::RVAToPointer(RVA rva) const { 321 const uint8_t* DisassemblerWin32X64::RVAToPointer(RVA rva) const {
321 int file_offset = RVAToFileOffset(rva); 322 int file_offset = RVAToFileOffset(rva);
322 if (file_offset == kNoOffset) 323 if (file_offset == kNoOffset)
323 return NULL; 324 return NULL;
324 else 325 else
325 return OffsetToPointer(file_offset); 326 return OffsetToPointer(file_offset);
326 } 327 }
327 328
328 std::string DisassemblerWin32X64::SectionName(const Section* section) { 329 std::string DisassemblerWin32X64::SectionName(const Section* section) {
329 if (section == NULL) 330 if (section == NULL)
330 return "<none>"; 331 return "<none>";
331 char name[9]; 332 char name[9];
332 memcpy(name, section->name, 8); 333 memcpy(name, section->name, 8);
333 name[8] = '\0'; // Ensure termination. 334 name[8] = '\0'; // Ensure termination.
334 return name; 335 return name;
335 } 336 }
336 337
337 CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) { 338 CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) {
338 // Walk all the bytes in the file, whether or not in a section. 339 // Walk all the bytes in the file, whether or not in a section.
339 uint32 file_offset = 0; 340 uint32_t file_offset = 0;
340 while (file_offset < length()) { 341 while (file_offset < length()) {
341 const Section* section = FindNextSection(file_offset); 342 const Section* section = FindNextSection(file_offset);
342 if (section == NULL) { 343 if (section == NULL) {
343 // No more sections. There should not be extra stuff following last 344 // No more sections. There should not be extra stuff following last
344 // section. 345 // section.
345 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program); 346 // ParseNonSectionFileRegion(file_offset, pe_info().length(), program);
346 break; 347 break;
347 } 348 }
348 if (file_offset < section->file_offset_of_raw_data) { 349 if (file_offset < section->file_offset_of_raw_data) {
349 uint32 section_start_offset = section->file_offset_of_raw_data; 350 uint32_t section_start_offset = section->file_offset_of_raw_data;
350 if(!ParseNonSectionFileRegion(file_offset, section_start_offset, 351 if(!ParseNonSectionFileRegion(file_offset, section_start_offset,
351 program)) 352 program))
352 return false; 353 return false;
353 354
354 file_offset = section_start_offset; 355 file_offset = section_start_offset;
355 } 356 }
356 uint32 end = file_offset + section->size_of_raw_data; 357 uint32_t end = file_offset + section->size_of_raw_data;
357 if (!ParseFileRegion(section, file_offset, end, program)) 358 if (!ParseFileRegion(section, file_offset, end, program))
358 return false; 359 return false;
359 file_offset = end; 360 file_offset = end;
360 } 361 }
361 362
362 #if COURGETTE_HISTOGRAM_TARGETS 363 #if COURGETTE_HISTOGRAM_TARGETS
363 HistogramTargets("abs32 relocs", abs32_target_rvas_); 364 HistogramTargets("abs32 relocs", abs32_target_rvas_);
364 HistogramTargets("rel32 relocs", rel32_target_rvas_); 365 HistogramTargets("rel32 relocs", rel32_target_rvas_);
365 #endif 366 #endif
366 367
367 return true; 368 return true;
368 } 369 }
369 370
370 bool DisassemblerWin32X64::ParseAbs32Relocs() { 371 bool DisassemblerWin32X64::ParseAbs32Relocs() {
371 abs32_locations_.clear(); 372 abs32_locations_.clear();
372 if (!ParseRelocs(&abs32_locations_)) 373 if (!ParseRelocs(&abs32_locations_))
373 return false; 374 return false;
374 375
375 #if COURGETTE_HISTOGRAM_TARGETS 376 #if COURGETTE_HISTOGRAM_TARGETS
376 for (size_t i = 0; i < abs32_locations_.size(); ++i) { 377 for (size_t i = 0; i < abs32_locations_.size(); ++i) {
377 RVA rva = abs32_locations_[i]; 378 RVA rva = abs32_locations_[i];
378 // The 4 bytes at the relocation are a reference to some address. 379 // The 4 bytes at the relocation are a reference to some address.
379 uint32 target_address = Read32LittleEndian(RVAToPointer(rva)); 380 uint32_t target_address = Read32LittleEndian(RVAToPointer(rva));
380 ++abs32_target_rvas_[target_address - image_base()]; 381 ++abs32_target_rvas_[target_address - image_base()];
381 } 382 }
382 #endif 383 #endif
383 return true; 384 return true;
384 } 385 }
385 386
386 void DisassemblerWin32X64::ParseRel32RelocsFromSections() { 387 void DisassemblerWin32X64::ParseRel32RelocsFromSections() {
387 uint32 file_offset = 0; 388 uint32_t file_offset = 0;
388 while (file_offset < length()) { 389 while (file_offset < length()) {
389 const Section* section = FindNextSection(file_offset); 390 const Section* section = FindNextSection(file_offset);
390 if (section == NULL) 391 if (section == NULL)
391 break; 392 break;
392 if (file_offset < section->file_offset_of_raw_data) 393 if (file_offset < section->file_offset_of_raw_data)
393 file_offset = section->file_offset_of_raw_data; 394 file_offset = section->file_offset_of_raw_data;
394 ParseRel32RelocsFromSection(section); 395 ParseRel32RelocsFromSection(section);
395 file_offset += section->size_of_raw_data; 396 file_offset += section->size_of_raw_data;
396 } 397 }
397 std::sort(rel32_locations_.begin(), rel32_locations_.end()); 398 std::sort(rel32_locations_.begin(), rel32_locations_.end());
(...skipping 22 matching lines...) Expand all
420 VLOG(1) << "common " << common; 421 VLOG(1) << "common " << common;
421 #endif 422 #endif
422 } 423 }
423 424
424 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) { 425 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) {
425 // TODO(sra): use characteristic. 426 // TODO(sra): use characteristic.
426 bool isCode = strcmp(section->name, ".text") == 0; 427 bool isCode = strcmp(section->name, ".text") == 0;
427 if (!isCode) 428 if (!isCode)
428 return; 429 return;
429 430
430 uint32 start_file_offset = section->file_offset_of_raw_data; 431 uint32_t start_file_offset = section->file_offset_of_raw_data;
431 uint32 end_file_offset = start_file_offset + section->size_of_raw_data; 432 uint32_t end_file_offset = start_file_offset + section->size_of_raw_data;
432 RVA relocs_start_rva = base_relocation_table().address_; 433 RVA relocs_start_rva = base_relocation_table().address_;
433 434
434 const uint8* start_pointer = OffsetToPointer(start_file_offset); 435 const uint8_t* start_pointer = OffsetToPointer(start_file_offset);
435 const uint8* end_pointer = OffsetToPointer(end_file_offset); 436 const uint8_t* end_pointer = OffsetToPointer(end_file_offset);
436 437
437 RVA start_rva = FileOffsetToRVA(start_file_offset); 438 RVA start_rva = FileOffsetToRVA(start_file_offset);
438 RVA end_rva = start_rva + section->virtual_size; 439 RVA end_rva = start_rva + section->virtual_size;
439 440
440 // Quick way to convert from Pointer to RVA within a single Section is to 441 // Quick way to convert from Pointer to RVA within a single Section is to
441 // subtract 'pointer_to_rva'. 442 // subtract 'pointer_to_rva'.
442 const uint8* const adjust_pointer_to_rva = start_pointer - start_rva; 443 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva;
443 444
444 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); 445 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
445 446
446 // Find the rel32 relocations. 447 // Find the rel32 relocations.
447 const uint8* p = start_pointer; 448 const uint8_t* p = start_pointer;
448 while (p < end_pointer) { 449 while (p < end_pointer) {
449 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); 450 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
450 if (current_rva == relocs_start_rva) { 451 if (current_rva == relocs_start_rva) {
451 uint32 relocs_size = base_relocation_table().size_; 452 uint32_t relocs_size = base_relocation_table().size_;
452 if (relocs_size) { 453 if (relocs_size) {
453 p += relocs_size; 454 p += relocs_size;
454 continue; 455 continue;
455 } 456 }
456 } 457 }
457 458
458 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) 459 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
459 // ++abs32_pos; 460 // ++abs32_pos;
460 461
461 // Heuristic discovery of rel32 locations in instruction stream: are the 462 // Heuristic discovery of rel32 locations in instruction stream: are the
462 // next few bytes the start of an instruction containing a rel32 463 // next few bytes the start of an instruction containing a rel32
463 // addressing mode? 464 // addressing mode?
464 const uint8* rel32 = NULL; 465 const uint8_t* rel32 = NULL;
465 bool is_rip_relative = false; 466 bool is_rip_relative = false;
466 467
467 if (p + 5 <= end_pointer) { 468 if (p + 5 <= end_pointer) {
468 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32 469 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32
469 rel32 = p + 1; 470 rel32 = p + 1;
470 } 471 }
471 if (p + 6 <= end_pointer) { 472 if (p + 6 <= end_pointer) {
472 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form 473 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form
473 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely 474 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely
474 rel32 = p + 2; 475 rel32 = p + 2;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 #endif 522 #endif
522 p = rel32 + 4; 523 p = rel32 + 4;
523 continue; 524 continue;
524 } 525 }
525 } 526 }
526 p += 1; 527 p += 1;
527 } 528 }
528 } 529 }
529 530
530 CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion( 531 CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion(
531 uint32 start_file_offset, 532 uint32_t start_file_offset,
532 uint32 end_file_offset, 533 uint32_t end_file_offset,
533 AssemblyProgram* program) { 534 AssemblyProgram* program) {
534 if (incomplete_disassembly_) 535 if (incomplete_disassembly_)
535 return true; 536 return true;
536 537
537 if (end_file_offset > start_file_offset) { 538 if (end_file_offset > start_file_offset) {
538 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset), 539 if (!program->EmitBytesInstruction(OffsetToPointer(start_file_offset),
539 end_file_offset - start_file_offset)) { 540 end_file_offset - start_file_offset)) {
540 return false; 541 return false;
541 } 542 }
542 } 543 }
543 544
544 return true; 545 return true;
545 } 546 }
546 547
547 CheckBool DisassemblerWin32X64::ParseFileRegion( 548 CheckBool DisassemblerWin32X64::ParseFileRegion(const Section* section,
548 const Section* section, 549 uint32_t start_file_offset,
549 uint32 start_file_offset, uint32 end_file_offset, 550 uint32_t end_file_offset,
550 AssemblyProgram* program) { 551 AssemblyProgram* program) {
551 RVA relocs_start_rva = base_relocation_table().address_; 552 RVA relocs_start_rva = base_relocation_table().address_;
552 553
553 const uint8* start_pointer = OffsetToPointer(start_file_offset); 554 const uint8_t* start_pointer = OffsetToPointer(start_file_offset);
554 const uint8* end_pointer = OffsetToPointer(end_file_offset); 555 const uint8_t* end_pointer = OffsetToPointer(end_file_offset);
555 556
556 RVA start_rva = FileOffsetToRVA(start_file_offset); 557 RVA start_rva = FileOffsetToRVA(start_file_offset);
557 RVA end_rva = start_rva + section->virtual_size; 558 RVA end_rva = start_rva + section->virtual_size;
558 559
559 // Quick way to convert from Pointer to RVA within a single Section is to 560 // Quick way to convert from Pointer to RVA within a single Section is to
560 // subtract 'pointer_to_rva'. 561 // subtract 'pointer_to_rva'.
561 const uint8* const adjust_pointer_to_rva = start_pointer - start_rva; 562 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva;
562 563
563 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin(); 564 std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin();
564 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin(); 565 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
565 566
566 if (!program->EmitOriginInstruction(start_rva)) 567 if (!program->EmitOriginInstruction(start_rva))
567 return false; 568 return false;
568 569
569 const uint8* p = start_pointer; 570 const uint8_t* p = start_pointer;
570 571
571 while (p < end_pointer) { 572 while (p < end_pointer) {
572 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva); 573 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
573 574
574 // The base relocation table is usually in the .relocs section, but it could 575 // The base relocation table is usually in the .relocs section, but it could
575 // actually be anywhere. Make sure we skip it because we will regenerate it 576 // actually be anywhere. Make sure we skip it because we will regenerate it
576 // during assembly. 577 // during assembly.
577 if (current_rva == relocs_start_rva) { 578 if (current_rva == relocs_start_rva) {
578 if (!program->EmitPeRelocsInstruction()) 579 if (!program->EmitPeRelocsInstruction())
579 return false; 580 return false;
580 uint32 relocs_size = base_relocation_table().size_; 581 uint32_t relocs_size = base_relocation_table().size_;
581 if (relocs_size) { 582 if (relocs_size) {
582 p += relocs_size; 583 p += relocs_size;
583 continue; 584 continue;
584 } 585 }
585 } 586 }
586 587
587 while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) 588 while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
588 ++abs32_pos; 589 ++abs32_pos;
589 590
590 if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) { 591 if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) {
591 uint64 target_address = Read64LittleEndian(p); 592 uint64_t target_address = Read64LittleEndian(p);
592 RVA target_rva = base::checked_cast<RVA>(target_address - image_base()); 593 RVA target_rva = base::checked_cast<RVA>(target_address - image_base());
593 // TODO(sra): target could be Label+offset. It is not clear how to guess 594 // TODO(sra): target could be Label+offset. It is not clear how to guess
594 // which it might be. We assume offset==0. 595 // which it might be. We assume offset==0.
595 if (!program->EmitAbs64(program->FindOrMakeAbs32Label(target_rva))) 596 if (!program->EmitAbs64(program->FindOrMakeAbs32Label(target_rva)))
596 return false; 597 return false;
597 p += 8; 598 p += 8;
598 continue; 599 continue;
599 } 600 }
600 601
601 while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva) 602 while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 s << std::hex << rva; 684 s << std::hex << rva;
684 if (section) { 685 if (section) {
685 s << " ("; 686 s << " (";
686 s << SectionName(section) << "+" 687 s << SectionName(section) << "+"
687 << std::hex << (rva - section->virtual_address) 688 << std::hex << (rva - section->virtual_address)
688 << ")"; 689 << ")";
689 } 690 }
690 return s.str(); 691 return s.str();
691 } 692 }
692 693
693 const Section* DisassemblerWin32X64::FindNextSection(uint32 fileOffset) const { 694 const Section* DisassemblerWin32X64::FindNextSection(
695 uint32_t fileOffset) const {
694 const Section* best = 0; 696 const Section* best = 0;
695 for (int i = 0; i < number_of_sections_; i++) { 697 for (int i = 0; i < number_of_sections_; i++) {
696 const Section* section = &sections_[i]; 698 const Section* section = &sections_[i];
697 if (section->size_of_raw_data > 0) { // i.e. has data in file. 699 if (section->size_of_raw_data > 0) { // i.e. has data in file.
698 if (fileOffset <= section->file_offset_of_raw_data) { 700 if (fileOffset <= section->file_offset_of_raw_data) {
699 if (best == 0 || 701 if (best == 0 ||
700 section->file_offset_of_raw_data < best->file_offset_of_raw_data) { 702 section->file_offset_of_raw_data < best->file_offset_of_raw_data) {
701 best = section; 703 best = section;
702 } 704 }
703 } 705 }
704 } 706 }
705 } 707 }
706 return best; 708 return best;
707 } 709 }
708 710
709 RVA DisassemblerWin32X64::FileOffsetToRVA(uint32 file_offset) const { 711 RVA DisassemblerWin32X64::FileOffsetToRVA(uint32_t file_offset) const {
710 for (int i = 0; i < number_of_sections_; i++) { 712 for (int i = 0; i < number_of_sections_; i++) {
711 const Section* section = &sections_[i]; 713 const Section* section = &sections_[i];
712 uint32 offset = file_offset - section->file_offset_of_raw_data; 714 uint32_t offset = file_offset - section->file_offset_of_raw_data;
713 if (offset < section->size_of_raw_data) { 715 if (offset < section->size_of_raw_data) {
714 return section->virtual_address + offset; 716 return section->virtual_address + offset;
715 } 717 }
716 } 718 }
717 return 0; 719 return 0;
718 } 720 }
719 721
720 bool DisassemblerWin32X64::ReadDataDirectory( 722 bool DisassemblerWin32X64::ReadDataDirectory(
721 int index, 723 int index,
722 ImageDataDirectory* directory) { 724 ImageDataDirectory* directory) {
723 725
724 if (index < number_of_data_directories_) { 726 if (index < number_of_data_directories_) {
725 size_t offset = index * 8 + offset_of_data_directories_; 727 size_t offset = index * 8 + offset_of_data_directories_;
726 if (offset >= size_of_optional_header_) 728 if (offset >= size_of_optional_header_)
727 return Bad("number of data directories inconsistent"); 729 return Bad("number of data directories inconsistent");
728 const uint8* data_directory = optional_header_ + offset; 730 const uint8_t* data_directory = optional_header_ + offset;
729 if (data_directory < start() || 731 if (data_directory < start() ||
730 data_directory + 8 >= end()) 732 data_directory + 8 >= end())
731 return Bad("data directory outside image"); 733 return Bad("data directory outside image");
732 RVA rva = ReadU32(data_directory, 0); 734 RVA rva = ReadU32(data_directory, 0);
733 size_t size = ReadU32(data_directory, 4); 735 size_t size = ReadU32(data_directory, 4);
734 if (size > size_of_image_) 736 if (size > size_of_image_)
735 return Bad("data directory size too big"); 737 return Bad("data directory size too big");
736 738
737 // TODO(sra): validate RVA. 739 // TODO(sra): validate RVA.
738 directory->address_ = rva; 740 directory->address_ = rva;
739 directory->size_ = static_cast<uint32>(size); 741 directory->size_ = static_cast<uint32_t>(size);
740 return true; 742 return true;
741 } else { 743 } else {
742 directory->address_ = 0; 744 directory->address_ = 0;
743 directory->size_ = 0; 745 directory->size_ = 0;
744 return true; 746 return true;
745 } 747 }
746 } 748 }
747 749
748 } // namespace courgette 750 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_win32_x64.h ('k') | courgette/disassembler_win32_x64_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698