summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2019-08-07 18:53:13 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2019-08-07 18:53:13 +0000
commit534e343949a12b33085eabd203075d8f66a5ca93 (patch)
tree52268bcfb37b5bb311416caff7c94f889c572db3 /sys
parentad6dc99c68b915d53bd2816a41461940c2376764 (diff)
Add codepatch_jmp(), like codepath_call() but inserting a jmp instead of a call.
tweaked based on feedback from kettenis@ ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/codepatch.c29
-rw-r--r--sys/arch/amd64/include/codepatch.h5
2 files changed, 26 insertions, 8 deletions
diff --git a/sys/arch/amd64/amd64/codepatch.c b/sys/arch/amd64/amd64/codepatch.c
index 57cc9784f6f..da2b2bb98a9 100644
--- a/sys/arch/amd64/amd64/codepatch.c
+++ b/sys/arch/amd64/amd64/codepatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: codepatch.c,v 1.7 2018/07/13 08:30:34 sf Exp $ */
+/* $OpenBSD: codepatch.c,v 1.8 2019/08/07 18:53:12 guenther Exp $ */
/*
* Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de>
*
@@ -39,6 +39,9 @@ extern struct codepatch codepatch_end;
extern char __cptext_start[];
extern char __cptext_end[];
+void codepatch_control_flow(uint16_t _tag, void *_func, int _opcode,
+ const char *_op);
+
void
codepatch_fill_nop(void *caddr, uint16_t len)
{
@@ -149,28 +152,42 @@ codepatch_replace(uint16_t tag, void *code, size_t len)
DBGPRINT("patched %d places", i);
}
-/* Patch with calls to func */
void
codepatch_call(uint16_t tag, void *func)
{
+ /* 0xe8 == call near */
+ codepatch_control_flow(tag, func, 0xe8, "call");
+}
+
+void
+codepatch_jmp(uint16_t tag, void *func)
+{
+ /* 0xe9 == jmp near */
+ codepatch_control_flow(tag, func, 0xe9, "jmp");
+}
+
+/* Patch with call or jump to func */
+void
+codepatch_control_flow(uint16_t tag, void *func, int opcode, const char *op)
+{
struct codepatch *patch;
unsigned char *rwaddr;
int32_t offset;
int i = 0;
vaddr_t rwmap = 0;
- DBGPRINT("patching tag %u with call %p", tag, func);
+ DBGPRINT("patching tag %u with %s %p", tag, op, func);
for (patch = &codepatch_begin; patch < &codepatch_end; patch++) {
if (patch->tag != tag)
continue;
if (patch->len < 5)
- panic("%s: can't replace len %u with call at %#lx",
- __func__, patch->len, patch->addr);
+ panic("%s: can't replace len %u with %s at %#lx",
+ __func__, patch->len, op, patch->addr);
offset = (vaddr_t)func - (patch->addr + 5);
rwaddr = codepatch_maprw(&rwmap, patch->addr);
- rwaddr[0] = 0xe8; /* call near */
+ rwaddr[0] = opcode;
memcpy(rwaddr + 1, &offset, sizeof(offset));
codepatch_fill_nop(rwaddr + 5, patch->len - 5);
i++;
diff --git a/sys/arch/amd64/include/codepatch.h b/sys/arch/amd64/include/codepatch.h
index 62348a98dbd..144f2179953 100644
--- a/sys/arch/amd64/include/codepatch.h
+++ b/sys/arch/amd64/include/codepatch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: codepatch.h,v 1.9 2019/05/17 19:07:16 guenther Exp $ */
+/* $OpenBSD: codepatch.h,v 1.10 2019/08/07 18:53:12 guenther Exp $ */
/*
* Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de>
*
@@ -30,7 +30,8 @@ __cptext void codepatch_unmaprw(vaddr_t nva);
__cptext void codepatch_fill_nop(void *caddr, uint16_t len);
__cptext void codepatch_nop(uint16_t tag);
__cptext void codepatch_replace(uint16_t tag, void *code, size_t len);
-__cptext void codepatch_call(uint16_t tag, void *func);
+__cptext void codepatch_call(uint16_t _tag, void *_func);
+__cptext void codepatch_jmp(uint16_t _tag, void *_func);
void codepatch_disable(void);
#endif /* !_LOCORE */