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

Side by Side Diff: courgette/disassembler_win32_x64.cc

Issue 2008253004: Refactor rel32 searching process for x64 to make it more similar to x86. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improve rel32_finder doc Created 4 years, 6 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_win32_x64.h" 5 #include "courgette/disassembler_win32_x64.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h" 10 #include "base/numerics/safe_conversions.h"
11 #include "courgette/assembly_program.h" 11 #include "courgette/assembly_program.h"
12 #include "courgette/courgette.h" 12 #include "courgette/courgette.h"
13 #include "courgette/rel32_finder_x64.h"
13 14
14 #if COURGETTE_HISTOGRAM_TARGETS 15 #if COURGETTE_HISTOGRAM_TARGETS
15 #include <iostream> 16 #include <iostream>
16 #endif 17 #endif
17 18
18 namespace courgette { 19 namespace courgette {
19 20
20 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length) 21 DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length)
21 : DisassemblerWin32(start, length) {} 22 : DisassemblerWin32(start, length) {}
22 23
(...skipping 13 matching lines...) Expand all
36 } 37 }
37 38
38 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) { 39 void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) {
39 // TODO(sra): use characteristic. 40 // TODO(sra): use characteristic.
40 bool isCode = strcmp(section->name, ".text") == 0; 41 bool isCode = strcmp(section->name, ".text") == 0;
41 if (!isCode) 42 if (!isCode)
42 return; 43 return;
43 44
44 FileOffset start_file_offset = section->file_offset_of_raw_data; 45 FileOffset start_file_offset = section->file_offset_of_raw_data;
45 FileOffset end_file_offset = start_file_offset + section->size_of_raw_data; 46 FileOffset end_file_offset = start_file_offset + section->size_of_raw_data;
46 RVA relocs_start_rva = base_relocation_table().address_;
47 47
48 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset); 48 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
49 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset); 49 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
50 50
51 RVA start_rva = FileOffsetToRVA(start_file_offset); 51 RVA start_rva = FileOffsetToRVA(start_file_offset);
52 RVA end_rva = start_rva + section->virtual_size; 52 RVA end_rva = start_rva + section->virtual_size;
53 53
54 // Quick way to convert from Pointer to RVA within a single Section is to 54 Rel32FinderX64 finder(
55 // subtract |pointer_to_rva|. 55 base_relocation_table().address_,
56 const uint8_t* const adjust_pointer_to_rva = start_pointer - start_rva; 56 base_relocation_table().address_ + base_relocation_table().size_,
57 size_of_image_);
58 finder.Find(start_pointer, end_pointer, start_rva, end_rva, abs32_locations_);
59 finder.SwapRel32Locations(&rel32_locations_);
57 60
58 std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
59
60 // Find the rel32 relocations.
61 const uint8_t* p = start_pointer;
62 while (p < end_pointer) {
63 RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
64 if (current_rva == relocs_start_rva) {
65 uint32_t relocs_size = base_relocation_table().size_;
66 if (relocs_size) {
67 p += relocs_size;
68 continue;
69 }
70 }
71
72 // Heuristic discovery of rel32 locations in instruction stream: are the
73 // next few bytes the start of an instruction containing a rel32
74 // addressing mode?
75 const uint8_t* rel32 = nullptr;
76 bool is_rip_relative = false;
77
78 if (p + 5 <= end_pointer) {
79 if (*p == 0xE8 || *p == 0xE9) // jmp rel32 and call rel32
80 rel32 = p + 1;
81 }
82 if (p + 6 <= end_pointer) {
83 if (*p == 0x0F && (*(p + 1) & 0xF0) == 0x80) { // Jcc long form
84 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely
85 rel32 = p + 2;
86 } else if (*p == 0xFF && (*(p + 1) == 0x15 || *(p + 1) == 0x25)) {
87 // rip relative call/jmp
88 rel32 = p + 2;
89 is_rip_relative = true;
90 }
91 }
92 if (p + 7 <= end_pointer) {
93 if ((*p & 0xFB) == 0x48 && *(p + 1) == 0x8D &&
94 (*(p + 2) & 0xC7) == 0x05) {
95 // rip relative lea
96 rel32 = p + 3;
97 is_rip_relative = true;
98 } else if ((*p & 0xFB) == 0x48 && *(p + 1) == 0x8B &&
99 (*(p + 2) & 0xC7) == 0x05) {
100 // rip relative mov
101 rel32 = p + 3;
102 is_rip_relative = true;
103 }
104 }
105
106 if (rel32) {
107 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva);
108
109 // Is there an abs32 reloc overlapping the candidate?
110 while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3)
111 ++abs32_pos;
112 // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte
113 // region that could overlap rel32_rva.
114 if (abs32_pos != abs32_locations_.end()) {
115 if (*abs32_pos < rel32_rva + 4) {
116 // Beginning of abs32 reloc is before end of rel32 reloc so they
117 // overlap. Skip four bytes past the abs32 reloc.
118 p += (*abs32_pos + 4) - current_rva;
119 continue;
120 }
121 }
122
123 // + 4 since offset is relative to start of next instruction.
124 RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32);
125 // To be valid, rel32 target must be within image, and within this
126 // section.
127 if (target_rva < size_of_image_ && // Subsumes rva != kUnassignedRVA.
128 (is_rip_relative ||
129 (start_rva <= target_rva && target_rva < end_rva))) {
130 rel32_locations_.push_back(rel32_rva);
131 #if COURGETTE_HISTOGRAM_TARGETS 61 #if COURGETTE_HISTOGRAM_TARGETS
132 ++rel32_target_rvas_[target_rva]; 62 DCHECK(rel32_target_rvas_.empty());
63 finder.SwapRel32TargetRVAs(&rel32_target_rvas_);
133 #endif 64 #endif
134 p = rel32 + 4;
135 continue;
136 }
137 }
138 p += 1;
139 }
140 } 65 }
141 66
142 } // namespace courgette 67 } // namespace courgette
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698