| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 } | 455 } |
| 456 } | 456 } |
| 457 | 457 |
| 458 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) | 458 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) |
| 459 // ++abs32_pos; | 459 // ++abs32_pos; |
| 460 | 460 |
| 461 // Heuristic discovery of rel32 locations in instruction stream: are the | 461 // Heuristic discovery of rel32 locations in instruction stream: are the |
| 462 // next few bytes the start of an instruction containing a rel32 | 462 // next few bytes the start of an instruction containing a rel32 |
| 463 // addressing mode? | 463 // addressing mode? |
| 464 const uint8* rel32 = NULL; | 464 const uint8* rel32 = NULL; |
| 465 bool is_rip_relative = false; |
| 465 | 466 |
| 466 if (p + 5 <= end_pointer) { | 467 if (p + 5 <= end_pointer) { |
| 467 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 | 468 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32 |
| 468 rel32 = p + 1; | 469 rel32 = p + 1; |
| 470 } |
| 471 if (p + 6 <= end_pointer) { |
| 472 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form |
| 473 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely |
| 474 rel32 = p + 2; |
| 475 } else if (*p == 0xFF && (*(p + 1) == 0x15 || *(p + 1) == 0x25)) { |
| 476 // rip relative call/jmp |
| 477 rel32 = p + 2; |
| 478 is_rip_relative = true; |
| 469 } | 479 } |
| 470 } | 480 } |
| 471 if (p + 6 <= end_pointer) { | 481 if (p + 7 <= end_pointer) { |
| 472 if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form | 482 if ((*p & 0xFB) == 0x48 && *(p + 1) == 0x8D && |
| 473 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely | 483 (*(p + 2) & 0xC7) == 0x05) { |
| 474 rel32 = p + 2; | 484 // rip relative lea |
| 485 rel32 = p + 3; |
| 486 is_rip_relative = true; |
| 487 } else if ((*p & 0xFB) == 0x48 && *(p + 1) == 0x8B && |
| 488 (*(p + 2) & 0xC7) == 0x05) { |
| 489 // rip relative mov |
| 490 rel32 = p + 3; |
| 491 is_rip_relative = true; |
| 475 } | 492 } |
| 476 } | 493 } |
| 494 |
| 477 if (rel32) { | 495 if (rel32) { |
| 478 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); | 496 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); |
| 479 | 497 |
| 480 // Is there an abs32 reloc overlapping the candidate? | 498 // Is there an abs32 reloc overlapping the candidate? |
| 481 while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3) | 499 while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3) |
| 482 ++abs32_pos; | 500 ++abs32_pos; |
| 483 // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte | 501 // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte |
| 484 // region that could overlap rel32_rva. | 502 // region that could overlap rel32_rva. |
| 485 if (abs32_pos != abs32_locations_.end()) { | 503 if (abs32_pos != abs32_locations_.end()) { |
| 486 if (*abs32_pos < rel32_rva + 4) { | 504 if (*abs32_pos < rel32_rva + 4) { |
| 487 // Beginning of abs32 reloc is before end of rel32 reloc so they | 505 // Beginning of abs32 reloc is before end of rel32 reloc so they |
| 488 // overlap. Skip four bytes past the abs32 reloc. | 506 // overlap. Skip four bytes past the abs32 reloc. |
| 489 p += (*abs32_pos + 4) - current_rva; | 507 p += (*abs32_pos + 4) - current_rva; |
| 490 continue; | 508 continue; |
| 491 } | 509 } |
| 492 } | 510 } |
| 493 | 511 |
| 494 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); | 512 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); |
| 495 // To be valid, rel32 target must be within image, and within this | 513 // To be valid, rel32 target must be within image, and within this |
| 496 // section. | 514 // section. |
| 497 if (IsValidRVA(target_rva) && | 515 if (IsValidRVA(target_rva) && |
| 498 start_rva <= target_rva && target_rva < end_rva) { | 516 (is_rip_relative || |
| 517 (start_rva <= target_rva && target_rva < end_rva))) { |
| 499 rel32_locations_.push_back(rel32_rva); | 518 rel32_locations_.push_back(rel32_rva); |
| 500 #if COURGETTE_HISTOGRAM_TARGETS | 519 #if COURGETTE_HISTOGRAM_TARGETS |
| 501 ++rel32_target_rvas_[target_rva]; | 520 ++rel32_target_rvas_[target_rva]; |
| 502 #endif | 521 #endif |
| 503 p = rel32 + 4; | 522 p = rel32 + 4; |
| 504 continue; | 523 continue; |
| 505 } | 524 } |
| 506 } | 525 } |
| 507 p += 1; | 526 p += 1; |
| 508 } | 527 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 directory->size_ = static_cast<uint32>(size); | 739 directory->size_ = static_cast<uint32>(size); |
| 721 return true; | 740 return true; |
| 722 } else { | 741 } else { |
| 723 directory->address_ = 0; | 742 directory->address_ = 0; |
| 724 directory->size_ = 0; | 743 directory->size_ = 0; |
| 725 return true; | 744 return true; |
| 726 } | 745 } |
| 727 } | 746 } |
| 728 | 747 |
| 729 } // namespace courgette | 748 } // namespace courgette |
| OLD | NEW |