aboutsummaryrefslogtreecommitdiff
path: root/lib/arm
diff options
context:
space:
mode:
authorcomex2015-03-01 23:07:15 -0500
committercomex2015-03-01 23:07:15 -0500
commit7f24621bec0b0a5b3cab9ec2dfc68929a2d49d25 (patch)
tree7c227bfa4d8010e23b726eed8efb6bc51746e3f5 /lib/arm
parentseems to work (diff)
downloadsubstitute-7f24621bec0b0a5b3cab9ec2dfc68929a2d49d25.tar.gz
A number of critical fixes painstakingly discovered in the slowest way possible.
Diffstat (limited to 'lib/arm')
-rw-r--r--lib/arm/arch-transform-dis.inc.h6
-rw-r--r--lib/arm/assemble.h3
-rw-r--r--lib/arm/dis-thumb2.inc.h2
-rw-r--r--lib/arm/jump-patch.h13
4 files changed, 15 insertions, 9 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h
index 8569300..4c44913 100644
--- a/lib/arm/arch-transform-dis.inc.h
+++ b/lib/arm/arch-transform-dis.inc.h
@@ -12,6 +12,7 @@ static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) {
}
return (struct assemble_ctx) {
ctx->rewritten_ptr_ptr,
+ (uint_tptr) (uintptr_t) ctx->rewritten_ptr_ptr,
ctx->arch.pc_low_bit,
cond
};
@@ -121,7 +122,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1,
}
static NOINLINE UNUSED
-void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc,
+void transform_dis_pcrel(struct transform_dis_ctx *ctx, uint_tptr dpc,
struct arch_pcrel_info info) {
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis_pcrel: (0x%llx) dpc=0x%llx reg=%x mode=%d\n",
@@ -149,7 +150,7 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc,
}
static NOINLINE UNUSED
-void transform_dis_branch(struct transform_dis_ctx *ctx, uintptr_t dpc, int cc) {
+void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) {
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis (0x%llx): branch => 0x%llx\n",
(unsigned long long) ctx->base.pc,
@@ -192,6 +193,7 @@ static void transform_dis_pre_dis(struct transform_dis_ctx *ctx) {
static void transform_dis_post_dis(struct transform_dis_ctx *ctx) {
if (ctx->arch.bccrel_p) {
struct assemble_ctx actx = {&ctx->arch.bccrel_p,
+ (uint_tptr) (uintptr_t) ctx->arch.bccrel_p,
/*thumb*/ true,
ctx->arch.bccrel_bits};
Bccrel(actx, *ctx->rewritten_ptr_ptr - ctx->arch.bccrel_p);
diff --git a/lib/arm/assemble.h b/lib/arm/assemble.h
index c0af020..2303a7a 100644
--- a/lib/arm/assemble.h
+++ b/lib/arm/assemble.h
@@ -3,6 +3,7 @@
struct assemble_ctx {
void **codep;
+ uint_tptr pc;
bool thumb;
int cond;
};
@@ -100,6 +101,8 @@ static inline void Bccrel(struct assemble_ctx ctx, int offset) {
}
static inline void LDR_PC(struct assemble_ctx ctx, uint32_t dpc) {
+ if (ctx.pc & 2)
+ op16(ctx.codep, 0xbf00);
if (ctx.thumb)
op32(ctx.codep, 0xf000f8df);
else
diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h
index 0a4c12c..b8082f3 100644
--- a/lib/arm/dis-thumb2.inc.h
+++ b/lib/arm/dis-thumb2.inc.h
@@ -197,7 +197,7 @@ static INLINE void P(thumb2_do_it)(tdis_ctx ctx) {
static INLINE void P(dis_thumb2)(tdis_ctx ctx) {
ctx->base.op = unaligned_r32(ctx->base.ptr);
- ctx->base.op_size = ctx->base.newop_size = 2;
+ ctx->base.op_size = ctx->base.newop_size = 4;
/* LLVM likes to think about Thumb2 instructions the way the ARM manual
* does - 15..0 15..0 rather than 31..0 as actually laid out in memory... */
ctx->base.op = flip16(ctx->base.op);
diff --git a/lib/arm/jump-patch.h b/lib/arm/jump-patch.h
index b65a97d..8787070 100644
--- a/lib/arm/jump-patch.h
+++ b/lib/arm/jump-patch.h
@@ -2,17 +2,18 @@
#include "dis.h"
#include "arm/assemble.h"
#define MAX_JUMP_PATCH_SIZE 8
+#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14)
-static inline int jump_patch_size(UNUSED uintptr_t pc,
- UNUSED uintptr_t dpc,
+static inline int jump_patch_size(uint_tptr pc,
+ UNUSED uint_tptr dpc,
UNUSED struct arch_dis_ctx arch,
UNUSED bool force) {
- return 8;
+ return (pc & 2) ? 10 : 8;
}
-static inline void make_jump_patch(void **codep, UNUSED uintptr_t pc,
- uintptr_t dpc,
+static inline void make_jump_patch(void **codep, uint_tptr pc,
+ uint_tptr dpc,
struct arch_dis_ctx arch) {
- struct assemble_ctx actx = {codep, arch.pc_low_bit, 0xe};
+ struct assemble_ctx actx = {codep, pc, arch.pc_low_bit, 0xe};
LDR_PC(actx, dpc);
}