diff options
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/codepatch.c | 29 | ||||
-rw-r--r-- | sys/arch/amd64/include/codepatch.h | 5 |
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 */ |