1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <arch/x86/feature.h>
8 #include <assert.h>
9 #include <lib/code_patching.h>
10 #include <stddef.h>
11
12 extern "C" {
13
14 extern void* memcpy(void*, const void*, size_t);
15 extern void* memcpy_erms(void*, const void*, size_t);
16 extern void* memcpy_quad(void*, const void*, size_t);
17
18 extern void* memset(void*, int, size_t);
19 extern void* memset_erms(void*, int, size_t);
20 extern void* memset_quad(void*, int, size_t);
21
x86_memcpy_select(const CodePatchInfo * patch)22 void x86_memcpy_select(const CodePatchInfo* patch) {
23 // We are patching a jmp rel8 instruction, which is two bytes. The rel8
24 // value is a signed 8-bit value specifying an offset relative to the
25 // address of the next instruction in memory after the jmp instruction.
26 const size_t kSize = 2;
27 const intptr_t jmp_from_address = reinterpret_cast<intptr_t>(memcpy) + kSize;
28
29 DEBUG_ASSERT(patch->dest_size == kSize);
30 DEBUG_ASSERT(reinterpret_cast<uintptr_t>(patch->dest_addr) ==
31 reinterpret_cast<uintptr_t>(memcpy));
32
33 intptr_t offset;
34 if (x86_feature_test(X86_FEATURE_ERMS)) {
35 offset = reinterpret_cast<intptr_t>(memcpy_erms) - jmp_from_address;
36 } else {
37 offset = reinterpret_cast<intptr_t>(memcpy_quad) - jmp_from_address;
38 }
39 DEBUG_ASSERT(offset >= -128 && offset <= 127);
40 patch->dest_addr[0] = 0xeb; /* jmp rel8 */
41 patch->dest_addr[1] = static_cast<uint8_t>(offset);
42 }
43
x86_memset_select(const CodePatchInfo * patch)44 void x86_memset_select(const CodePatchInfo* patch) {
45 // We are patching a jmp rel8 instruction, which is two bytes. The rel8
46 // value is a signed 8-bit value specifying an offset relative to the
47 // address of the next instruction in memory after the jmp instruction.
48 const size_t kSize = 2;
49 const intptr_t jmp_from_address = reinterpret_cast<intptr_t>(memset) + kSize;
50
51 DEBUG_ASSERT(patch->dest_size == kSize);
52 DEBUG_ASSERT(reinterpret_cast<uintptr_t>(patch->dest_addr) ==
53 reinterpret_cast<uintptr_t>(memset));
54
55 intptr_t offset;
56 if (x86_feature_test(X86_FEATURE_ERMS)) {
57 offset = reinterpret_cast<intptr_t>(memset_erms) - jmp_from_address;
58 } else {
59 offset = reinterpret_cast<intptr_t>(memset_quad) - jmp_from_address;
60 }
61 DEBUG_ASSERT(offset >= -128 && offset <= 127);
62 patch->dest_addr[0] = 0xeb; /* jmp rel8 */
63 patch->dest_addr[1] = static_cast<uint8_t>(offset);
64 }
65
66 }
67