OLD | NEW |
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/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 call.set_target(new_target); | 153 call.set_target(new_target); |
154 } | 154 } |
155 | 155 |
156 | 156 |
157 void CodePatcher::PatchInstanceCallAt(uword return_address, uword new_target) { | 157 void CodePatcher::PatchInstanceCallAt(uword return_address, uword new_target) { |
158 InstanceCall call(return_address); | 158 InstanceCall call(return_address); |
159 call.set_target(new_target); | 159 call.set_target(new_target); |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 static void SwapCode(intptr_t num_bytes, char* a, char* b) { | |
164 for (intptr_t i = 0; i < num_bytes; i++) { | |
165 char tmp = *a; | |
166 *a = *b; | |
167 *b = tmp; | |
168 a++; | |
169 b++; | |
170 } | |
171 } | |
172 | 163 |
173 | 164 void CodePatcher::InsertCallAt(uword start, uword target) { |
174 // The patch code buffer contains the jmp code which will be inserted at | 165 *reinterpret_cast<uint8_t*>(start) = 0xE8; |
175 // entry point. | 166 CallPattern call(start); |
176 void CodePatcher::PatchEntry(const Code& code) { | 167 call.SetTargetAddress(target); |
177 JumpPattern jmp_entry(code.EntryPoint()); | 168 CPU::FlushICache(start, CallPattern::InstructionLength()); |
178 ASSERT(!jmp_entry.IsValid()); | |
179 const uword patch_buffer = code.GetPatchCodePc(); | |
180 ASSERT(patch_buffer != 0); | |
181 JumpPattern jmp_patch(patch_buffer); | |
182 ASSERT(jmp_patch.IsValid()); | |
183 const uword jump_target = jmp_patch.TargetAddress(); | |
184 SwapCode(jmp_patch.pattern_length_in_bytes(), | |
185 reinterpret_cast<char*>(code.EntryPoint()), | |
186 reinterpret_cast<char*>(patch_buffer)); | |
187 jmp_entry.SetTargetAddress(jump_target); | |
188 } | |
189 | |
190 | |
191 // The entry point is a jmp instruction, the patch code buffer contains | |
192 // original code, the entry point contains the jump instruction. | |
193 void CodePatcher::RestoreEntry(const Code& code) { | |
194 JumpPattern jmp_entry(code.EntryPoint()); | |
195 ASSERT(jmp_entry.IsValid()); | |
196 const uword jump_target = jmp_entry.TargetAddress(); | |
197 const uword patch_buffer = code.GetPatchCodePc(); | |
198 ASSERT(patch_buffer != 0); | |
199 // 'patch_buffer' contains original entry code. | |
200 JumpPattern jmp_patch(patch_buffer); | |
201 ASSERT(!jmp_patch.IsValid()); | |
202 SwapCode(jmp_patch.pattern_length_in_bytes(), | |
203 reinterpret_cast<char*>(code.EntryPoint()), | |
204 reinterpret_cast<char*>(patch_buffer)); | |
205 ASSERT(jmp_patch.IsValid()); | |
206 jmp_patch.SetTargetAddress(jump_target); | |
207 } | |
208 | |
209 | |
210 bool CodePatcher::CodeIsPatchable(const Code& code) { | |
211 JumpPattern jmp_entry(code.EntryPoint()); | |
212 if (code.Size() < (jmp_entry.pattern_length_in_bytes() * 2)) { | |
213 return false; | |
214 } | |
215 uword limit = code.EntryPoint() + jmp_entry.pattern_length_in_bytes(); | |
216 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { | |
217 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | |
218 if (addr < limit) { | |
219 return false; | |
220 } | |
221 } | |
222 return true; | |
223 } | 169 } |
224 | 170 |
225 | 171 |
226 bool CodePatcher::IsDartCall(uword return_address) { | 172 bool CodePatcher::IsDartCall(uword return_address) { |
227 return DartCallPattern::IsValid(return_address); | 173 return DartCallPattern::IsValid(return_address); |
228 } | 174 } |
229 | 175 |
230 | 176 |
231 uword CodePatcher::GetInstanceCallAt(uword return_address, | 177 uword CodePatcher::GetInstanceCallAt(uword return_address, |
232 ICData* ic_data, | 178 ICData* ic_data, |
233 Array* arguments_descriptor) { | 179 Array* arguments_descriptor) { |
234 InstanceCall call(return_address); | 180 InstanceCall call(return_address); |
235 if (ic_data != NULL) { | 181 if (ic_data != NULL) { |
236 *ic_data ^= call.ic_data(); | 182 *ic_data ^= call.ic_data(); |
237 } | 183 } |
238 if (arguments_descriptor != NULL) { | 184 if (arguments_descriptor != NULL) { |
239 *arguments_descriptor ^= call.arguments_descriptor(); | 185 *arguments_descriptor ^= call.arguments_descriptor(); |
240 } | 186 } |
241 return call.target(); | 187 return call.target(); |
242 } | 188 } |
243 | 189 |
244 | 190 |
245 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 191 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
246 return DartCallPattern::kNumInstructions * DartCallPattern::kInstructionSize; | 192 return DartCallPattern::kNumInstructions * DartCallPattern::kInstructionSize; |
247 } | 193 } |
248 | 194 |
249 | |
250 void CodePatcher::InsertCallAt(uword start, uword target) { | |
251 *reinterpret_cast<uint8_t*>(start) = 0xE8; | |
252 CallPattern call(start); | |
253 call.SetTargetAddress(target); | |
254 CPU::FlushICache(start, CallPattern::InstructionLength()); | |
255 } | |
256 | |
257 | |
258 } // namespace dart | 195 } // namespace dart |
259 | 196 |
260 #endif // defined TARGET_ARCH_IA32 | 197 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |