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

Side by Side Diff: runtime/vm/code_patcher.cc

Issue 106593002: Write protect executable pages in the VM. Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_patcher.h ('k') | runtime/vm/dart.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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/code_patcher.h" 5 #include "vm/code_patcher.h"
6 #include "vm/cpu.h" 6 #include "vm/cpu.h"
7 #include "vm/instructions.h" 7 #include "vm/instructions.h"
8 #include "vm/object.h" 8 #include "vm/object.h"
9 #include "vm/virtual_memory.h"
9 10
10 namespace dart { 11 namespace dart {
11 12
13 WritableInstructionsScope::WritableInstructionsScope(uword address,
14 intptr_t size)
15 : address_(address), size_(size) {
16 bool status =
17 VirtualMemory::Protect(reinterpret_cast<void*>(address),
18 size,
19 VirtualMemory::kReadWriteExecute);
20 ASSERT(status);
21 }
22
23
24 WritableInstructionsScope::~WritableInstructionsScope() {
25 bool status =
26 VirtualMemory::Protect(reinterpret_cast<void*>(address_),
27 size_,
28 VirtualMemory::kReadExecute);
29 ASSERT(status);
30 }
31
32
12 static void SwapCode(intptr_t num_bytes, char* code, char* buffer) { 33 static void SwapCode(intptr_t num_bytes, char* code, char* buffer) {
13 uword code_address = reinterpret_cast<uword>(code); 34 uword code_address = reinterpret_cast<uword>(code);
14 for (intptr_t i = 0; i < num_bytes; i++) { 35 for (intptr_t i = 0; i < num_bytes; i++) {
15 char tmp = *code; 36 char tmp = *code;
16 *code = *buffer; 37 *code = *buffer;
17 *buffer = tmp; 38 *buffer = tmp;
18 code++; 39 code++;
19 buffer++; 40 buffer++;
20 } 41 }
21 CPU::FlushICache(code_address, num_bytes); 42 CPU::FlushICache(code_address, num_bytes);
22 // The buffer is not executed. No need to flush. 43 // The buffer is not executed. No need to flush.
23 } 44 }
24 45
25 46
26 // The patch code buffer contains the jmp code which will be inserted at 47 // The patch code buffer contains the jmp code which will be inserted at
27 // entry point. 48 // entry point.
28 void CodePatcher::PatchEntry(const Code& code) { 49 void CodePatcher::PatchEntry(const Code& code) {
29 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId, 50 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
30 PcDescriptors::kEntryPatch); 51 PcDescriptors::kEntryPatch);
31 ASSERT(patch_addr != 0); 52 ASSERT(patch_addr != 0);
32 JumpPattern jmp_entry(patch_addr, code); 53 JumpPattern jmp_entry(patch_addr, code);
33 ASSERT(!jmp_entry.IsValid()); 54 ASSERT(!jmp_entry.IsValid());
34 const uword patch_buffer = code.GetPatchCodePc(); 55 const uword patch_buffer = code.GetPatchCodePc();
35 ASSERT(patch_buffer != 0); 56 ASSERT(patch_buffer != 0);
36 JumpPattern jmp_patch(patch_buffer, code); 57 JumpPattern jmp_patch(patch_buffer, code);
37 ASSERT(jmp_patch.IsValid()); 58 ASSERT(jmp_patch.IsValid());
38 const uword jump_target = jmp_patch.TargetAddress(); 59 const uword jump_target = jmp_patch.TargetAddress();
39 SwapCode(jmp_patch.pattern_length_in_bytes(), 60 intptr_t length = jmp_patch.pattern_length_in_bytes();
40 reinterpret_cast<char*>(patch_addr), 61 {
41 reinterpret_cast<char*>(patch_buffer)); 62 WritableInstructionsScope writable_code(patch_addr, length);
42 jmp_entry.SetTargetAddress(jump_target); 63 WritableInstructionsScope writable_buffer(patch_buffer, length);
64 SwapCode(jmp_patch.pattern_length_in_bytes(),
65 reinterpret_cast<char*>(patch_addr),
66 reinterpret_cast<char*>(patch_buffer));
67 jmp_entry.SetTargetAddress(jump_target);
68 }
43 } 69 }
44 70
45 71
46 // The entry point is a jmp instruction, the patch code buffer contains 72 // The entry point is a jmp instruction, the patch code buffer contains
47 // original code, the entry point contains the jump instruction. 73 // original code, the entry point contains the jump instruction.
48 void CodePatcher::RestoreEntry(const Code& code) { 74 void CodePatcher::RestoreEntry(const Code& code) {
49 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId, 75 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
50 PcDescriptors::kEntryPatch); 76 PcDescriptors::kEntryPatch);
51 ASSERT(patch_addr != 0); 77 ASSERT(patch_addr != 0);
52 JumpPattern jmp_entry(patch_addr, code); 78 JumpPattern jmp_entry(patch_addr, code);
53 ASSERT(jmp_entry.IsValid()); 79 ASSERT(jmp_entry.IsValid());
54 const uword jump_target = jmp_entry.TargetAddress(); 80 const uword jump_target = jmp_entry.TargetAddress();
55 const uword patch_buffer = code.GetPatchCodePc(); 81 const uword patch_buffer = code.GetPatchCodePc();
56 ASSERT(patch_buffer != 0); 82 ASSERT(patch_buffer != 0);
57 // 'patch_buffer' contains original entry code. 83 // 'patch_buffer' contains original entry code.
58 JumpPattern jmp_patch(patch_buffer, code); 84 JumpPattern jmp_patch(patch_buffer, code);
59 ASSERT(!jmp_patch.IsValid()); 85 ASSERT(!jmp_patch.IsValid());
60 SwapCode(jmp_patch.pattern_length_in_bytes(), 86 intptr_t length = jmp_patch.pattern_length_in_bytes();
61 reinterpret_cast<char*>(patch_addr), 87 {
62 reinterpret_cast<char*>(patch_buffer)); 88 WritableInstructionsScope writable_code(patch_addr, length);
63 ASSERT(jmp_patch.IsValid()); 89 WritableInstructionsScope writable_buffer(patch_buffer, length);
64 jmp_patch.SetTargetAddress(jump_target); 90 SwapCode(jmp_patch.pattern_length_in_bytes(),
91 reinterpret_cast<char*>(patch_addr),
92 reinterpret_cast<char*>(patch_buffer));
93 ASSERT(jmp_patch.IsValid());
94 jmp_patch.SetTargetAddress(jump_target);
95 }
65 } 96 }
66 97
67 98
68 bool CodePatcher::CodeIsPatchable(const Code& code) { 99 bool CodePatcher::CodeIsPatchable(const Code& code) {
69 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId, 100 const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
70 PcDescriptors::kEntryPatch); 101 PcDescriptors::kEntryPatch);
71 // kEntryPatch may not exist which means the function is not patchable. 102 // kEntryPatch may not exist which means the function is not patchable.
72 if (patch_addr == 0) { 103 if (patch_addr == 0) {
73 return true; 104 return true;
74 } 105 }
75 JumpPattern jmp_entry(patch_addr, code); 106 JumpPattern jmp_entry(patch_addr, code);
76 if (code.Size() < (jmp_entry.pattern_length_in_bytes() * 2)) { 107 if (code.Size() < (jmp_entry.pattern_length_in_bytes() * 2)) {
77 return false; 108 return false;
78 } 109 }
79 const uword limit = patch_addr + jmp_entry.pattern_length_in_bytes(); 110 const uword limit = patch_addr + jmp_entry.pattern_length_in_bytes();
80 // Check no object stored between patch_addr .. limit. 111 // Check no object stored between patch_addr .. limit.
81 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { 112 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) {
82 const uword obj_start = code.GetPointerOffsetAt(i) + code.EntryPoint(); 113 const uword obj_start = code.GetPointerOffsetAt(i) + code.EntryPoint();
83 const uword obj_end = obj_start + kWordSize; 114 const uword obj_end = obj_start + kWordSize;
84 if ((obj_start < limit) && (obj_end > patch_addr)) { 115 if ((obj_start < limit) && (obj_end > patch_addr)) {
85 return false; 116 return false;
86 } 117 }
87 } 118 }
88 return true; 119 return true;
89 } 120 }
90 121
91 } // namespace dart 122 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/code_patcher.h ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698