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
12extern "C" {
13
14extern void* memcpy(void*, const void*, size_t);
15extern void* memcpy_erms(void*, const void*, size_t);
16extern void* memcpy_quad(void*, const void*, size_t);
17
18extern void* memset(void*, int, size_t);
19extern void* memset_erms(void*, int, size_t);
20extern void* memset_quad(void*, int, size_t);
21
22void 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
44void 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