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