blob: d8832c63159f4c8ca33ceb8221e72ee87b803f7e [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <arch/x86/feature.h>
#include <assert.h>
#include <lib/code_patching.h>
#include <stddef.h>
extern "C" {
extern void* memcpy(void*, const void*, size_t);
extern void* memcpy_erms(void*, const void*, size_t);
extern void* memcpy_quad(void*, const void*, size_t);
extern void* memset(void*, int, size_t);
extern void* memset_erms(void*, int, size_t);
extern void* memset_quad(void*, int, size_t);
void x86_memcpy_select(const CodePatchInfo* patch) {
// We are patching a jmp rel8 instruction, which is two bytes. The rel8
// value is a signed 8-bit value specifying an offset relative to the
// address of the next instruction in memory after the jmp instruction.
const size_t kSize = 2;
const intptr_t jmp_from_address = reinterpret_cast<intptr_t>(memcpy) + kSize;
DEBUG_ASSERT(patch->dest_size == kSize);
DEBUG_ASSERT(reinterpret_cast<uintptr_t>(patch->dest_addr) ==
reinterpret_cast<uintptr_t>(memcpy));
intptr_t offset;
if (x86_feature_test(X86_FEATURE_ERMS)) {
offset = reinterpret_cast<intptr_t>(memcpy_erms) - jmp_from_address;
} else {
offset = reinterpret_cast<intptr_t>(memcpy_quad) - jmp_from_address;
}
DEBUG_ASSERT(offset >= -128 && offset <= 127);
patch->dest_addr[0] = 0xeb; /* jmp rel8 */
patch->dest_addr[1] = static_cast<uint8_t>(offset);
}
void x86_memset_select(const CodePatchInfo* patch) {
// We are patching a jmp rel8 instruction, which is two bytes. The rel8
// value is a signed 8-bit value specifying an offset relative to the
// address of the next instruction in memory after the jmp instruction.
const size_t kSize = 2;
const intptr_t jmp_from_address = reinterpret_cast<intptr_t>(memset) + kSize;
DEBUG_ASSERT(patch->dest_size == kSize);
DEBUG_ASSERT(reinterpret_cast<uintptr_t>(patch->dest_addr) ==
reinterpret_cast<uintptr_t>(memset));
intptr_t offset;
if (x86_feature_test(X86_FEATURE_ERMS)) {
offset = reinterpret_cast<intptr_t>(memset_erms) - jmp_from_address;
} else {
offset = reinterpret_cast<intptr_t>(memset_quad) - jmp_from_address;
}
DEBUG_ASSERT(offset >= -128 && offset <= 127);
patch->dest_addr[0] = 0xeb; /* jmp rel8 */
patch->dest_addr[1] = static_cast<uint8_t>(offset);
}
}