diff --git a/gum/arch-arm64/gumarm64writer.c b/gum/arch-arm64/gumarm64writer.c index 42683f470..219d301db 100644 --- a/gum/arch-arm64/gumarm64writer.c +++ b/gum/arch-arm64/gumarm64writer.c @@ -213,6 +213,7 @@ gum_arm64_writer_init (GumArm64Writer * writer, writer->ref_count = 1; writer->flush_on_destroy = TRUE; + writer->data_endian = G_BYTE_ORDER; writer->target_os = gum_process_get_native_os (); writer->ptrauth_support = gum_query_ptrauth_support (); writer->sign = gum_sign_code_address; @@ -1994,13 +1995,29 @@ gum_arm64_writer_commit_literals (GumArm64Writer * self) for (slot = first_slot; slot != last_slot; slot++) { - if (GINT64_FROM_LE (*slot) == r->val) - break; + if (self->data_endian == G_LITTLE_ENDIAN) + { + if (GINT64_FROM_LE (*slot) == r->val) + break; + } + else + { + if (GINT64_FROM_BE (*slot) == r->val) + break; + } + } if (slot == last_slot) { - *slot = GINT64_TO_LE (r->val); + if (self->data_endian == G_LITTLE_ENDIAN) + { + *slot = GINT64_TO_LE (r->val); + } + else + { + *slot = GINT64_TO_BE (r->val); + } last_slot = slot + 1; } @@ -2026,13 +2043,28 @@ gum_arm64_writer_commit_literals (GumArm64Writer * self) for (slot = first_slot; slot != last_slot; slot++) { - if (GINT32_FROM_LE (*slot) == r->val) - break; + if (self->data_endian == G_LITTLE_ENDIAN) + { + if (GINT32_FROM_LE (*slot) == r->val) + break; + } + else + { + if (GINT32_FROM_BE (*slot) == r->val) + break; + } } if (slot == last_slot) { - *slot = GINT32_TO_LE (r->val); + if (self->data_endian == G_LITTLE_ENDIAN) + { + *slot = GINT32_TO_LE (r->val); + } + else + { + *slot = GINT32_TO_BE (r->val); + } last_slot = slot + 1; } diff --git a/gum/arch-arm64/gumarm64writer.h b/gum/arch-arm64/gumarm64writer.h index 9aa8ac01e..1597ee32d 100644 --- a/gum/arch-arm64/gumarm64writer.h +++ b/gum/arch-arm64/gumarm64writer.h @@ -34,11 +34,26 @@ G_BEGIN_DECLS typedef struct _GumArm64Writer GumArm64Writer; typedef guint GumArm64IndexMode; +/* + * Valid values for this field are: + * - G_LITTLE_ENDIAN + * - G_BIG_ENDIAN + * - G_BYTE_ORDER (an alias for one of the above) + */ +typedef guint GumArm64DataEndian; + struct _GumArm64Writer { volatile gint ref_count; gboolean flush_on_destroy; + /* + * Whilst instructions in AArch64 are always in little endian (even on + * big-endian systems), the data is in native endian. Thus since we wish to + * support writing code for big-endian systems on little-endian targets and + * vice versa, we need to check the writer configuration before writing data. + */ + GumArm64DataEndian data_endian; GumOS target_os; GumPtrauthSupport ptrauth_support; GumAddress (* sign) (GumAddress value); diff --git a/gum/gumdefs.h b/gum/gumdefs.h index afec756d8..d1beb686d 100644 --- a/gum/gumdefs.h +++ b/gum/gumdefs.h @@ -119,9 +119,12 @@ typedef GumMipsCpuContext GumCpuContext; * The only non-legacy big-endian configuration on 32-bit ARM systems is BE8. * In this configuration, whilst the data is in big-endian, the code stream is * still in little-endian. Since Capstone is disassembling the code stream, it - * should work in little-endian even on BE8 systems. + * should work in little-endian even on BE8 systems. On big-endian 64-bit ARM + * systems, the code stream is likewise in little-endian. */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN || defined (__arm__) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN || \ + defined (__arm__) || \ + defined (__aarch64__) # define GUM_DEFAULT_CS_ENDIAN CS_MODE_LITTLE_ENDIAN #else # define GUM_DEFAULT_CS_ENDIAN CS_MODE_BIG_ENDIAN