aboutsummaryrefslogtreecommitdiff
path: root/lib/transform-dis.c
diff options
context:
space:
mode:
authorcomex2015-02-08 23:45:24 -0500
committercomex2015-02-08 23:45:24 -0500
commiteb93cee2a22cde812ccd6b9bd418d36185c058f5 (patch)
tree43a22ccf021a1513dba3a9c99f7b81822fe950fa /lib/transform-dis.c
parentformatting (diff)
downloadsubstitute-eb93cee2a22cde812ccd6b9bd418d36185c058f5.tar.gz
Refactor disassembly so x86 works, and add x86 transform-dis.
This patch is a monolithic mess, because I was too lazy to do the refactor first (that would require some stash fun, since I wasn't actually sure before doing x86 transform-dis what would be needed). Anyway, the resulting code should be cleaner - less duplication. This breaks ARM/ARM64.
Diffstat (limited to 'lib/transform-dis.c')
-rw-r--r--lib/transform-dis.c55
1 files changed, 21 insertions, 34 deletions
diff --git a/lib/transform-dis.c b/lib/transform-dis.c
index 867a981..8f89fb3 100644
--- a/lib/transform-dis.c
+++ b/lib/transform-dis.c
@@ -1,5 +1,6 @@
#include "substitute-internal.h"
#ifdef TARGET_DIS_SUPPORTED
+#define DIS_MAY_MODIFY 1
#include "substitute.h"
#include "dis.h"
@@ -13,21 +14,15 @@ struct transform_dis_ctx {
/* outputs */
bool modify;
int err;
+ struct dis_ctx_base base;
- uintptr_t pc_patch_start;
+ uint_tptr pc_patch_start;
/* this is only tentative - it will be updated to include parts of
* instructions poking out, and instructions forced to be transformed by IT */
- uintptr_t pc_patch_end;
- uintptr_t pc;
- int op_size;
- unsigned op;
- unsigned newop;
- unsigned newval[4];
-
+ uint_tptr pc_patch_end;
/* for IT - eww */
bool force_keep_transforming;
- const void *ptr;
void **rewritten_ptr_ptr;
void *write_newop_here;
@@ -35,10 +30,6 @@ struct transform_dis_ctx {
};
#define tdis_ctx struct transform_dis_ctx *
-#define TDIS_CTX_MODIFY(ctx) ((ctx)->modify)
-#define TDIS_CTX_NEWVAL(ctx, n) ((ctx)->newval[n])
-#define TDIS_CTX_NEWOP(ctx) ((ctx)->newop)
-#define TDIS_CTX_SET_NEWOP(ctx, new) ((ctx)->newop = (new))
/* largely similar to jump_dis */
@@ -46,14 +37,14 @@ static INLINE UNUSED
void transform_dis_ret(struct transform_dis_ctx *ctx) {
/* ret is okay if it's at the end of the required patch (past the original
* patch size is good too) */
- if (ctx->pc + ctx->op_size < ctx->pc_patch_end)
+ if (ctx->base.pc + ctx->base.op_size < ctx->pc_patch_end)
ctx->err = SUBSTITUTE_ERR_FUNC_TOO_SHORT;
}
static INLINE UNUSED
void transform_dis_unidentified(UNUSED struct transform_dis_ctx *ctx) {
#ifdef TRANSFORM_DIS_VERBOSE
- printf("transform_dis (%p): unidentified\n", (void *) ctx->pc);
+ printf("transform_dis (%p): unidentified\n", (void *) ctx->base.pc);
#endif
/* this isn't exhaustive, so unidentified is fine */
}
@@ -74,15 +65,15 @@ static void transform_dis_post_dis(struct transform_dis_ctx *ctx);
int transform_dis_main(const void *restrict code_ptr,
void **restrict rewritten_ptr_ptr,
- uintptr_t pc_patch_start,
- uintptr_t *pc_patch_end_p,
+ uint_tptr pc_patch_start,
+ uint_tptr *pc_patch_end_p,
struct arch_dis_ctx *arch_ctx_p,
int *offset_by_pcdiff) {
struct transform_dis_ctx ctx;
memset(&ctx, 0, sizeof(ctx));
ctx.pc_patch_start = pc_patch_start;
ctx.pc_patch_end = *pc_patch_end_p;
- ctx.pc = pc_patch_start;
+ ctx.base.pc = pc_patch_start;
ctx.arch = *arch_ctx_p;
/* data is written to rewritten both by this function directly and, in case
* additional scaffolding is needed, by arch-specific transform_dis_* */
@@ -90,10 +81,10 @@ int transform_dis_main(const void *restrict code_ptr,
void *rewritten_start = *rewritten_ptr_ptr;
int written_pcdiff = 0;
offset_by_pcdiff[written_pcdiff++] = 0;
- while (ctx.pc < ctx.pc_patch_end && !ctx.force_keep_transforming) {
- ctx.modify = false;
+ while (ctx.base.pc < ctx.pc_patch_end && !ctx.force_keep_transforming) {
+ ctx.base.modify = false;
ctx.err = 0;
- ctx.ptr = code_ptr + (ctx.pc - pc_patch_start);
+ ctx.base.ptr = code_ptr + (ctx.base.pc - pc_patch_start);
transform_dis_pre_dis(&ctx);
@@ -105,33 +96,29 @@ int transform_dis_main(const void *restrict code_ptr,
if (ctx.err)
return ctx.err;
if (ctx.write_newop_here != NULL) {
- if (!ctx.modify)
- ctx.newop = ctx.op;
- if (ctx.op_size == 4)
- *(uint32_t *) ctx.write_newop_here = ctx.newop;
- else if (ctx.op_size == 2)
- *(uint16_t *) ctx.write_newop_here = ctx.newop;
+ if (ctx.base.modify)
+ memcpy(ctx.write_newop_here, ctx.base.newop, ctx.base.newop_size);
else
- __builtin_abort();
+ memcpy(ctx.write_newop_here, ctx.base.ptr, ctx.base.op_size);
if (*rewritten_ptr_ptr == rewritten_ptr)
- *rewritten_ptr_ptr += ctx.op_size;
+ *rewritten_ptr_ptr += ctx.base.op_size;
}
- ctx.pc += ctx.op_size;
+ ctx.base.pc += ctx.base.op_size;
transform_dis_post_dis(&ctx);
- int pcdiff = ctx.pc - ctx.pc_patch_start;
+ int pcdiff = ctx.base.pc - ctx.pc_patch_start;
while (written_pcdiff < pcdiff)
offset_by_pcdiff[written_pcdiff++] = -1;
offset_by_pcdiff[written_pcdiff++] =
(int) (*rewritten_ptr_ptr - rewritten_start);
}
- *pc_patch_end_p = ctx.pc;
+ *pc_patch_end_p = ctx.base.pc;
*arch_ctx_p = ctx.arch;
return SUBSTITUTE_OK;
}
-#include TARGET_TRANSFORM_DIS_HEADER
-#include TARGET_DIS_HEADER
+#include stringify(TARGET_DIR/arch-transform-dis.inc.h)
+#include stringify(TARGET_DIR/dis-main.inc.h)
#endif /* TARGET_DIS_SUPPORTED */