OLD | NEW |
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 Loading... |
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 Loading... |
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 = §ions_[i]; | 173 const Section* section = §ions_[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 Loading... |
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 = §ions_[i]; | 290 const Section* section = §ions_[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 Loading... |
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 Loading... |
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 Loading... |
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 = §ions_[i]; | 698 const Section* section = §ions_[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 = §ions_[i]; | 713 const Section* section = §ions_[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 |
OLD | NEW |