 Chromium Code Reviews
 Chromium Code Reviews Issue 878043002:
  Add support for RIP relative addresses on x86_64.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 878043002:
  Add support for RIP relative addresses on x86_64.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 } | 454 } | 
| 455 } | 455 } | 
| 456 | 456 | 
| 457 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) | 457 //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva) | 
| 458 // ++abs32_pos; | 458 // ++abs32_pos; | 
| 459 | 459 | 
| 460 // Heuristic discovery of rel32 locations in instruction stream: are the | 460 // Heuristic discovery of rel32 locations in instruction stream: are the | 
| 461 // next few bytes the start of an instruction containing a rel32 | 461 // next few bytes the start of an instruction containing a rel32 | 
| 462 // addressing mode? | 462 // addressing mode? | 
| 463 const uint8* rel32 = NULL; | 463 const uint8* rel32 = NULL; | 
| 464 bool is_rip_relative = false; | |
| 464 | 465 | 
| 465 if (p + 5 <= end_pointer) { | 466 if (p + 5 <= end_pointer) { | 
| 
dgarrett
2015/03/10 03:03:48
This CL isn't introducing the pattern, but shouldn
 
Will Harris
2015/03/12 05:33:28
yes, none of the blocks will ever collide with eac
 
dgarrett
2015/03/12 16:40:54
For some reason, I read the "rel32 = p + 2" type l
 | |
| 466 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 | 467 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 | 
| 467 rel32 = p + 1; | 468 rel32 = p + 1; | 
| 469 is_rip_relative = false; | |
| 
rickyz (no longer on Chrome)
2015/03/10 05:13:50
Fine if you prefer it this way, but no need to set
 
Will Harris
2015/03/12 05:33:28
Done.
 | |
| 468 } | 470 } | 
| 469 } | 471 } | 
| 470 if (p + 6 <= end_pointer) { | 472 if (p + 6 <= end_pointer) { | 
| 471 if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form | 473 if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form | 
| 
rickyz (no longer on Chrome)
2015/03/10 05:13:50
nit: Could we use p[1] or *(p + 1) consistently ev
 
Will Harris
2015/03/12 05:33:28
Done.
 | |
| 472 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely | 474 if (p[1] != 0x8A && p[1] != 0x8B) { // JPE/JPO unlikely | 
| 473 rel32 = p + 2; | 475 rel32 = p + 2; | 
| 476 is_rip_relative = false; | |
| 477 } | |
| 478 } else if (*p == 0xFF && (*(p + 1) == 0x15 || *(p + 1) == 0x25)) { | |
| 479 // rip relative call/jmp | |
| 480 rel32 = p + 2; | |
| 481 is_rip_relative = true; | |
| 474 } | 482 } | 
| 475 } | 483 } | 
| 484 if (p + 7 <= end_pointer) { | |
| 485 if ((*p & 0xFE) == 0x48 && *(p + 1) == 0x8D && | |
| 
rickyz (no longer on Chrome)
2015/03/10 05:13:50
Did you mean to use 0xFB here and below? Otherwise
 
Will Harris
2015/03/12 05:33:28
Done.  Good spot.
 | |
| 486 (*(p + 2) & 0xC7) == 0x05) { | |
| 487 // rip relative lea | |
| 488 rel32 = p + 3; | |
| 489 is_rip_relative = true; | |
| 490 } else if ((*p & 0xFE) == 0x48 && *(p + 1) == 0x8B && | |
| 491 (*(p + 2) & 0xC7) == 0x05) { | |
| 492 // rip relative mov | |
| 493 rel32 = p + 3; | |
| 494 is_rip_relative = true; | |
| 495 } | |
| 496 } | |
| 
rickyz (no longer on Chrome)
2015/03/10 05:13:50
Out of curiosity, how do we decide which instructi
 
Will Harris
2015/03/12 05:33:28
I agree that there is probably still some scope he
 | |
| 497 | |
| 476 if (rel32) { | 498 if (rel32) { | 
| 477 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); | 499 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); | 
| 478 | 500 | 
| 479 // Is there an abs32 reloc overlapping the candidate? | 501 // Is there an abs32 reloc overlapping the candidate? | 
| 480 while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3) | 502 while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3) | 
| 481 ++abs32_pos; | 503 ++abs32_pos; | 
| 482 // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte | 504 // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte | 
| 483 // region that could overlap rel32_rva. | 505 // region that could overlap rel32_rva. | 
| 484 if (abs32_pos != abs32_locations_.end()) { | 506 if (abs32_pos != abs32_locations_.end()) { | 
| 485 if (*abs32_pos < rel32_rva + 4) { | 507 if (*abs32_pos < rel32_rva + 4) { | 
| 486 // Beginning of abs32 reloc is before end of rel32 reloc so they | 508 // Beginning of abs32 reloc is before end of rel32 reloc so they | 
| 487 // overlap. Skip four bytes past the abs32 reloc. | 509 // overlap. Skip four bytes past the abs32 reloc. | 
| 488 p += (*abs32_pos + 4) - current_rva; | 510 p += (*abs32_pos + 4) - current_rva; | 
| 489 continue; | 511 continue; | 
| 490 } | 512 } | 
| 491 } | 513 } | 
| 492 | 514 | 
| 493 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); | 515 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); | 
| 494 // To be valid, rel32 target must be within image, and within this | 516 // To be valid, rel32 target must be within image, and within this | 
| 495 // section. | 517 // section. | 
| 496 if (IsValidRVA(target_rva) && | 518 if (IsValidRVA(target_rva) && | 
| 497 start_rva <= target_rva && target_rva < end_rva) { | 519 (is_rip_relative || | 
| 520 start_rva <= target_rva && target_rva < end_rva)) { | |
| 498 rel32_locations_.push_back(rel32_rva); | 521 rel32_locations_.push_back(rel32_rva); | 
| 499 #if COURGETTE_HISTOGRAM_TARGETS | 522 #if COURGETTE_HISTOGRAM_TARGETS | 
| 500 ++rel32_target_rvas_[target_rva]; | 523 ++rel32_target_rvas_[target_rva]; | 
| 501 #endif | 524 #endif | 
| 502 p = rel32 + 4; | 525 p = rel32 + 4; | 
| 503 continue; | 526 continue; | 
| 504 } | 527 } | 
| 505 } | 528 } | 
| 506 p += 1; | 529 p += 1; | 
| 507 } | 530 } | 
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 directory->size_ = static_cast<uint32>(size); | 748 directory->size_ = static_cast<uint32>(size); | 
| 726 return true; | 749 return true; | 
| 727 } else { | 750 } else { | 
| 728 directory->address_ = 0; | 751 directory->address_ = 0; | 
| 729 directory->size_ = 0; | 752 directory->size_ = 0; | 
| 730 return true; | 753 return true; | 
| 731 } | 754 } | 
| 732 } | 755 } | 
| 733 | 756 | 
| 734 } // namespace courgette | 757 } // namespace courgette | 
| OLD | NEW |