diff options
author | comex | 2015-02-24 20:57:12 -0500 |
---|---|---|
committer | comex | 2015-02-24 20:57:12 -0500 |
commit | 11d6f5764e35bdddae7a4aaf23fd859eecb48c8f (patch) | |
tree | 59d1be8a346c15c2e1287d31ce04eabd58eb3104 | |
parent | fix armv7 syscall registers :o (diff) | |
download | substitute-11d6f5764e35bdddae7a4aaf23fd859eecb48c8f.tar.gz |
Add unaligned read/write functions.
I thought I could get away without since I wasn't (presently) targeting
systems without hardware support for unaligned accesses, but on armv7
clang insists on optimizing into the one ARM instruction that requires
alignment anyway - LDM/STM. Oops. Damnit, clang.
-rw-r--r-- | lib/arm/dis-arm.inc.h | 2 | ||||
-rw-r--r-- | lib/arm/dis-main.inc.h | 2 | ||||
-rw-r--r-- | lib/arm/dis-thumb.inc.h | 2 | ||||
-rw-r--r-- | lib/arm/dis-thumb2.inc.h | 2 | ||||
-rw-r--r-- | lib/arm64/dis-main.inc.h | 2 | ||||
-rw-r--r-- | lib/dis.h | 31 | ||||
-rw-r--r-- | lib/substitute-internal.h | 1 |
7 files changed, 34 insertions, 8 deletions
diff --git a/lib/arm/dis-arm.inc.h b/lib/arm/dis-arm.inc.h index ab61877..18285cd 100644 --- a/lib/arm/dis-arm.inc.h +++ b/lib/arm/dis-arm.inc.h @@ -215,7 +215,7 @@ static INLINE void P(bl_target_func_2_BL)(tdis_ctx ctx, struct bitslice func) { } static INLINE void P(dis_arm)(tdis_ctx ctx) { - uint32_t op = ctx->base.op = *(uint32_t *) ctx->base.ptr; + uint32_t op = ctx->base.op = unaligned_r32(ctx->base.ptr); ctx->base.op_size = ctx->base.newop_size = 4; #include "../generated/generic-dis-arm.inc.h" __builtin_abort(); diff --git a/lib/arm/dis-main.inc.h b/lib/arm/dis-main.inc.h index c9fe983..0d87ba5 100644 --- a/lib/arm/dis-main.inc.h +++ b/lib/arm/dis-main.inc.h @@ -4,7 +4,7 @@ static INLINE void P(dis)(tdis_ctx ctx) { if (ctx->arch.pc_low_bit) { - uint16_t op = *(uint16_t *) ctx->base.ptr; + uint16_t op = unaligned_r16(ctx->base.ptr); bool is_32 = (op >> 13 & 7) == 7 && (op >> 11 & 3) != 0; if (is_32) return P(dis_thumb2)(ctx); diff --git a/lib/arm/dis-thumb.inc.h b/lib/arm/dis-thumb.inc.h index 4f758bf..74ae71a 100644 --- a/lib/arm/dis-thumb.inc.h +++ b/lib/arm/dis-thumb.inc.h @@ -86,7 +86,7 @@ static INLINE void P(GPR_func_1_tBLXr)(tdis_ctx ctx, UNUSED struct bitslice func } static INLINE void P(thumb_do_it)(tdis_ctx ctx) { - uint16_t op = ctx->base.op = *(uint16_t *) ctx->base.ptr; + uint16_t op = ctx->base.op = unaligned_r16(ctx->base.ptr); #include "../generated/generic-dis-thumb.inc.h" __builtin_abort(); } diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h index 5f699c9..0a4c12c 100644 --- a/lib/arm/dis-thumb2.inc.h +++ b/lib/arm/dis-thumb2.inc.h @@ -196,7 +196,7 @@ static INLINE void P(thumb2_do_it)(tdis_ctx ctx) { } static INLINE void P(dis_thumb2)(tdis_ctx ctx) { - ctx->base.op = *(uint32_t *) ctx->base.ptr; + ctx->base.op = unaligned_r32(ctx->base.ptr); ctx->base.op_size = ctx->base.newop_size = 2; /* 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... */ diff --git a/lib/arm64/dis-main.inc.h b/lib/arm64/dis-main.inc.h index a009189..cb24065 100644 --- a/lib/arm64/dis-main.inc.h +++ b/lib/arm64/dis-main.inc.h @@ -65,7 +65,7 @@ static INLINE void P(GPR64_Rn_2_BLR)(tdis_ctx ctx, UNUSED struct bitslice Rn) { } static INLINE void P(dis)(tdis_ctx ctx) { - uint32_t op = ctx->base.op = *(uint32_t *) ctx->base.ptr; + uint32_t op = ctx->base.op = unaligned_r32(ctx->base.ptr); ctx->base.op_size = ctx->base.newop_size = 4; /* clang doesn't realize that this is unreachable and generates code like * "and ecx, 0x1f; cmp ecx, 0x1f; ja abort". Yeah, nice job there. */ @@ -9,6 +9,31 @@ #define INLINE __attribute__((always_inline)) #define NOINLINE __attribute__((noinline)) +static INLINE inline void unaligned_w64(void *ptr, uint64_t val) { + __builtin_memcpy(ptr, &val, 8); +} +static INLINE inline void unaligned_w32(void *ptr, uint32_t val) { + __builtin_memcpy(ptr, &val, 4); +} +static INLINE inline void unaligned_w16(void *ptr, uint16_t val) { + __builtin_memcpy(ptr, &val, 2); +} +static INLINE inline uint64_t unaligned_r64(const void *ptr) { + uint64_t val; + __builtin_memcpy(&val, ptr, 8); + return val; +} +static INLINE inline uint32_t unaligned_r32(const void *ptr) { + uint32_t val; + __builtin_memcpy(&val, ptr, 4); + return val; +} +static INLINE inline uint16_t unaligned_r16(const void *ptr) { + uint16_t val; + __builtin_memcpy(&val, ptr, 2); + return val; +} + struct bitslice_run { int inpos, outpos, len; }; @@ -113,17 +138,17 @@ static const unsigned null_op = -0x100; #endif static inline void op64(void **codep, uint64_t op) { - *(uint64_t *) *codep = op; + unaligned_w64(*codep, op); *codep += 8; } static inline void op32(void **codep, uint32_t op) { - *(uint32_t *) *codep = op; + unaligned_w32(*codep, op); *codep += 4; } static inline void op16(void **codep, uint16_t op) { - *(uint16_t *) *codep = op; + unaligned_w16(*codep, op); *codep += 2; } diff --git a/lib/substitute-internal.h b/lib/substitute-internal.h index 9a91516..8f900a4 100644 --- a/lib/substitute-internal.h +++ b/lib/substitute-internal.h @@ -100,3 +100,4 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options, int substitute_ios_unrestrict(task_t task, char **error); #endif + |