diff --git a/bindings/dotnet/UnicornManaged/Const/Arm.fs b/bindings/dotnet/UnicornManaged/Const/Arm.fs index a571722b..326b32db 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm.fs @@ -35,13 +35,14 @@ module Arm = let UC_CPU_ARM_PXA260 = 23 let UC_CPU_ARM_PXA261 = 24 let UC_CPU_ARM_PXA262 = 25 - let UC_CPU_ARM_PXA270A0 = 26 - let UC_CPU_ARM_PXA270A1 = 27 - let UC_CPU_ARM_PXA270B0 = 28 - let UC_CPU_ARM_PXA270B1 = 29 - let UC_CPU_ARM_PXA270C0 = 30 - let UC_CPU_ARM_PXA270C5 = 31 - let UC_CPU_ARM_MAX = 32 + let UC_CPU_ARM_PXA270 = 26 + let UC_CPU_ARM_PXA270A0 = 27 + let UC_CPU_ARM_PXA270A1 = 28 + let UC_CPU_ARM_PXA270B0 = 29 + let UC_CPU_ARM_PXA270B1 = 30 + let UC_CPU_ARM_PXA270C0 = 31 + let UC_CPU_ARM_PXA270C5 = 32 + let UC_CPU_ARM_MAX = 33 // ARM registers diff --git a/bindings/dotnet/UnicornManaged/Const/X86.fs b/bindings/dotnet/UnicornManaged/Const/X86.fs index 81c727b2..10973a05 100644 --- a/bindings/dotnet/UnicornManaged/Const/X86.fs +++ b/bindings/dotnet/UnicornManaged/Const/X86.fs @@ -284,7 +284,12 @@ module X86 = let UC_X86_REG_GS_BASE = 231 let UC_X86_REG_FLAGS = 232 let UC_X86_REG_RFLAGS = 233 - let UC_X86_REG_ENDING = 234 + let UC_X86_REG_FIP = 234 + let UC_X86_REG_FCS = 235 + let UC_X86_REG_FDP = 236 + let UC_X86_REG_FDS = 237 + let UC_X86_REG_FOP = 238 + let UC_X86_REG_ENDING = 239 // X86 instructions diff --git a/bindings/go/unicorn/arm_const.go b/bindings/go/unicorn/arm_const.go index 87177e20..81eac268 100644 --- a/bindings/go/unicorn/arm_const.go +++ b/bindings/go/unicorn/arm_const.go @@ -30,13 +30,14 @@ const ( CPU_ARM_PXA260 = 23 CPU_ARM_PXA261 = 24 CPU_ARM_PXA262 = 25 - CPU_ARM_PXA270A0 = 26 - CPU_ARM_PXA270A1 = 27 - CPU_ARM_PXA270B0 = 28 - CPU_ARM_PXA270B1 = 29 - CPU_ARM_PXA270C0 = 30 - CPU_ARM_PXA270C5 = 31 - CPU_ARM_MAX = 32 + CPU_ARM_PXA270 = 26 + CPU_ARM_PXA270A0 = 27 + CPU_ARM_PXA270A1 = 28 + CPU_ARM_PXA270B0 = 29 + CPU_ARM_PXA270B1 = 30 + CPU_ARM_PXA270C0 = 31 + CPU_ARM_PXA270C5 = 32 + CPU_ARM_MAX = 33 // ARM registers diff --git a/bindings/go/unicorn/x86_const.go b/bindings/go/unicorn/x86_const.go index 30157482..f7e97791 100644 --- a/bindings/go/unicorn/x86_const.go +++ b/bindings/go/unicorn/x86_const.go @@ -279,7 +279,12 @@ const ( X86_REG_GS_BASE = 231 X86_REG_FLAGS = 232 X86_REG_RFLAGS = 233 - X86_REG_ENDING = 234 + X86_REG_FIP = 234 + X86_REG_FCS = 235 + X86_REG_FDP = 236 + X86_REG_FDS = 237 + X86_REG_FOP = 238 + X86_REG_ENDING = 239 // X86 instructions diff --git a/bindings/java/unicorn/ArmConst.java b/bindings/java/unicorn/ArmConst.java index 7ae2d9fa..6524a8b3 100644 --- a/bindings/java/unicorn/ArmConst.java +++ b/bindings/java/unicorn/ArmConst.java @@ -32,13 +32,14 @@ public interface ArmConst { public static final int UC_CPU_ARM_PXA260 = 23; public static final int UC_CPU_ARM_PXA261 = 24; public static final int UC_CPU_ARM_PXA262 = 25; - public static final int UC_CPU_ARM_PXA270A0 = 26; - public static final int UC_CPU_ARM_PXA270A1 = 27; - public static final int UC_CPU_ARM_PXA270B0 = 28; - public static final int UC_CPU_ARM_PXA270B1 = 29; - public static final int UC_CPU_ARM_PXA270C0 = 30; - public static final int UC_CPU_ARM_PXA270C5 = 31; - public static final int UC_CPU_ARM_MAX = 32; + public static final int UC_CPU_ARM_PXA270 = 26; + public static final int UC_CPU_ARM_PXA270A0 = 27; + public static final int UC_CPU_ARM_PXA270A1 = 28; + public static final int UC_CPU_ARM_PXA270B0 = 29; + public static final int UC_CPU_ARM_PXA270B1 = 30; + public static final int UC_CPU_ARM_PXA270C0 = 31; + public static final int UC_CPU_ARM_PXA270C5 = 32; + public static final int UC_CPU_ARM_MAX = 33; // ARM registers diff --git a/bindings/java/unicorn/X86Const.java b/bindings/java/unicorn/X86Const.java index a614b06f..b64147b0 100644 --- a/bindings/java/unicorn/X86Const.java +++ b/bindings/java/unicorn/X86Const.java @@ -281,7 +281,12 @@ public interface X86Const { public static final int UC_X86_REG_GS_BASE = 231; public static final int UC_X86_REG_FLAGS = 232; public static final int UC_X86_REG_RFLAGS = 233; - public static final int UC_X86_REG_ENDING = 234; + public static final int UC_X86_REG_FIP = 234; + public static final int UC_X86_REG_FCS = 235; + public static final int UC_X86_REG_FDP = 236; + public static final int UC_X86_REG_FDS = 237; + public static final int UC_X86_REG_FOP = 238; + public static final int UC_X86_REG_ENDING = 239; // X86 instructions diff --git a/bindings/pascal/unicorn/ArmConst.pas b/bindings/pascal/unicorn/ArmConst.pas index 32558aea..c62e9c6c 100644 --- a/bindings/pascal/unicorn/ArmConst.pas +++ b/bindings/pascal/unicorn/ArmConst.pas @@ -33,13 +33,14 @@ const UC_CPU_ARM_PXA260 = 23; UC_CPU_ARM_PXA261 = 24; UC_CPU_ARM_PXA262 = 25; - UC_CPU_ARM_PXA270A0 = 26; - UC_CPU_ARM_PXA270A1 = 27; - UC_CPU_ARM_PXA270B0 = 28; - UC_CPU_ARM_PXA270B1 = 29; - UC_CPU_ARM_PXA270C0 = 30; - UC_CPU_ARM_PXA270C5 = 31; - UC_CPU_ARM_MAX = 32; + UC_CPU_ARM_PXA270 = 26; + UC_CPU_ARM_PXA270A0 = 27; + UC_CPU_ARM_PXA270A1 = 28; + UC_CPU_ARM_PXA270B0 = 29; + UC_CPU_ARM_PXA270B1 = 30; + UC_CPU_ARM_PXA270C0 = 31; + UC_CPU_ARM_PXA270C5 = 32; + UC_CPU_ARM_MAX = 33; // ARM registers diff --git a/bindings/pascal/unicorn/X86Const.pas b/bindings/pascal/unicorn/X86Const.pas index 7301659d..ab0a85f1 100644 --- a/bindings/pascal/unicorn/X86Const.pas +++ b/bindings/pascal/unicorn/X86Const.pas @@ -282,7 +282,12 @@ const UC_X86_REG_GS_BASE = 231; UC_X86_REG_FLAGS = 232; UC_X86_REG_RFLAGS = 233; - UC_X86_REG_ENDING = 234; + UC_X86_REG_FIP = 234; + UC_X86_REG_FCS = 235; + UC_X86_REG_FDP = 236; + UC_X86_REG_FDS = 237; + UC_X86_REG_FOP = 238; + UC_X86_REG_ENDING = 239; // X86 instructions diff --git a/bindings/python/unicorn/arm_const.py b/bindings/python/unicorn/arm_const.py index 36fac155..be63377c 100644 --- a/bindings/python/unicorn/arm_const.py +++ b/bindings/python/unicorn/arm_const.py @@ -28,13 +28,14 @@ UC_CPU_ARM_PXA255 = 22 UC_CPU_ARM_PXA260 = 23 UC_CPU_ARM_PXA261 = 24 UC_CPU_ARM_PXA262 = 25 -UC_CPU_ARM_PXA270A0 = 26 -UC_CPU_ARM_PXA270A1 = 27 -UC_CPU_ARM_PXA270B0 = 28 -UC_CPU_ARM_PXA270B1 = 29 -UC_CPU_ARM_PXA270C0 = 30 -UC_CPU_ARM_PXA270C5 = 31 -UC_CPU_ARM_MAX = 32 +UC_CPU_ARM_PXA270 = 26 +UC_CPU_ARM_PXA270A0 = 27 +UC_CPU_ARM_PXA270A1 = 28 +UC_CPU_ARM_PXA270B0 = 29 +UC_CPU_ARM_PXA270B1 = 30 +UC_CPU_ARM_PXA270C0 = 31 +UC_CPU_ARM_PXA270C5 = 32 +UC_CPU_ARM_MAX = 33 # ARM registers diff --git a/bindings/python/unicorn/x86_const.py b/bindings/python/unicorn/x86_const.py index fd380464..b99f46b1 100644 --- a/bindings/python/unicorn/x86_const.py +++ b/bindings/python/unicorn/x86_const.py @@ -277,7 +277,12 @@ UC_X86_REG_FS_BASE = 230 UC_X86_REG_GS_BASE = 231 UC_X86_REG_FLAGS = 232 UC_X86_REG_RFLAGS = 233 -UC_X86_REG_ENDING = 234 +UC_X86_REG_FIP = 234 +UC_X86_REG_FCS = 235 +UC_X86_REG_FDP = 236 +UC_X86_REG_FDS = 237 +UC_X86_REG_FOP = 238 +UC_X86_REG_ENDING = 239 # X86 instructions diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb index c0e5b049..232e0161 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb @@ -30,13 +30,14 @@ module UnicornEngine UC_CPU_ARM_PXA260 = 23 UC_CPU_ARM_PXA261 = 24 UC_CPU_ARM_PXA262 = 25 - UC_CPU_ARM_PXA270A0 = 26 - UC_CPU_ARM_PXA270A1 = 27 - UC_CPU_ARM_PXA270B0 = 28 - UC_CPU_ARM_PXA270B1 = 29 - UC_CPU_ARM_PXA270C0 = 30 - UC_CPU_ARM_PXA270C5 = 31 - UC_CPU_ARM_MAX = 32 + UC_CPU_ARM_PXA270 = 26 + UC_CPU_ARM_PXA270A0 = 27 + UC_CPU_ARM_PXA270A1 = 28 + UC_CPU_ARM_PXA270B0 = 29 + UC_CPU_ARM_PXA270B1 = 30 + UC_CPU_ARM_PXA270C0 = 31 + UC_CPU_ARM_PXA270C5 = 32 + UC_CPU_ARM_MAX = 33 # ARM registers diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb index 84701acb..76e899df 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb @@ -279,7 +279,12 @@ module UnicornEngine UC_X86_REG_GS_BASE = 231 UC_X86_REG_FLAGS = 232 UC_X86_REG_RFLAGS = 233 - UC_X86_REG_ENDING = 234 + UC_X86_REG_FIP = 234 + UC_X86_REG_FCS = 235 + UC_X86_REG_FDP = 236 + UC_X86_REG_FDS = 237 + UC_X86_REG_FOP = 238 + UC_X86_REG_ENDING = 239 # X86 instructions diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 966aada9..a5b88563 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -43,6 +43,7 @@ typedef enum uc_cpu_arm { UC_CPU_ARM_PXA260, UC_CPU_ARM_PXA261, UC_CPU_ARM_PXA262, + UC_CPU_ARM_PXA270, UC_CPU_ARM_PXA270A0, UC_CPU_ARM_PXA270A1, UC_CPU_ARM_PXA270B0, diff --git a/include/unicorn/ppc.h b/include/unicorn/ppc.h index 14a20498..5705ffff 100644 --- a/include/unicorn/ppc.h +++ b/include/unicorn/ppc.h @@ -370,6 +370,54 @@ typedef enum uc_ppc_reg { UC_PPC_REG_29, UC_PPC_REG_30, UC_PPC_REG_31, + + UC_PPC_REG_CR0, + UC_PPC_REG_CR1, + UC_PPC_REG_CR2, + UC_PPC_REG_CR3, + UC_PPC_REG_CR4, + UC_PPC_REG_CR5, + UC_PPC_REG_CR6, + UC_PPC_REG_CR7, + + UC_PPC_REG_FPR0, + UC_PPC_REG_FPR1, + UC_PPC_REG_FPR2, + UC_PPC_REG_FPR3, + UC_PPC_REG_FPR4, + UC_PPC_REG_FPR5, + UC_PPC_REG_FPR6, + UC_PPC_REG_FPR7, + UC_PPC_REG_FPR8, + UC_PPC_REG_FPR9, + UC_PPC_REG_FPR10, + UC_PPC_REG_FPR11, + UC_PPC_REG_FPR12, + UC_PPC_REG_FPR13, + UC_PPC_REG_FPR14, + UC_PPC_REG_FPR15, + UC_PPC_REG_FPR16, + UC_PPC_REG_FPR17, + UC_PPC_REG_FPR18, + UC_PPC_REG_FPR19, + UC_PPC_REG_FPR20, + UC_PPC_REG_FPR21, + UC_PPC_REG_FPR22, + UC_PPC_REG_FPR23, + UC_PPC_REG_FPR24, + UC_PPC_REG_FPR25, + UC_PPC_REG_FPR26, + UC_PPC_REG_FPR27, + UC_PPC_REG_FPR28, + UC_PPC_REG_FPR29, + UC_PPC_REG_FPR30, + UC_PPC_REG_FPR31, + + UC_PPC_REG_LR, + UC_PPC_REG_XER, + UC_PPC_REG_CTR, + UC_PPC_REG_MSR, + UC_PPC_REG_FPSCR } uc_ppc_reg; #ifdef __cplusplus diff --git a/include/unicorn/x86.h b/include/unicorn/x86.h index a4afcd9c..861844f8 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -319,6 +319,11 @@ typedef enum uc_x86_reg { UC_X86_REG_GS_BASE, UC_X86_REG_FLAGS, UC_X86_REG_RFLAGS, + UC_X86_REG_FIP, + UC_X86_REG_FCS, + UC_X86_REG_FDP, + UC_X86_REG_FDS, + UC_X86_REG_FOP, UC_X86_REG_ENDING // <-- mark the end of the list of registers } uc_x86_reg; diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index c0488ca9..e48670eb 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -985,11 +985,22 @@ static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t l { tb_page_addr_t start, end; - // GVA to GPA + uc->nested_level++; + if (sigsetjmp(uc->jmp_bufs[uc->nested_level - 1], 0) != 0) { + // We a get cpu fault in get_page_addr_code, ignore it. + uc->nested_level--; + return; + } + + // GPA to GVA + // start_addr : GPA + // addr: GVA // (GPA -> HVA via memory_region_get_ram_addr(mr) + GPA + block->host, // HVA->HPA via host mmu) start = get_page_addr_code(uc->cpu->env_ptr, start_addr) & (target_ulong)(-1); - + + uc->nested_level--; + // For 32bit target. end = (start + len) & (target_ulong)(-1); diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index ff8fb705..f5cb2eb7 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -184,13 +184,6 @@ static void arm_cpu_reset(CPUState *dev) } else { env->pstate = PSTATE_MODE_EL1h; } - /* - * Unicorn: Hack to force to enable EL2/EL3 for aarch64 so that we can - * use the full 64bits virtual address space. - * - * See cpu_aarch64_init for details. - */ - env->pstate = PSTATE_MODE_EL1h; env->pc = cpu->rvbar; } @@ -705,6 +698,17 @@ void arm_cpu_post_init(CPUState *obj) cpu->rvbar = 0; } + if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) { + /* Add the has_el3 state CPU property only if EL3 is allowed. This will + * prevent "has_el3" from existing on CPUs which cannot support EL3. + */ + cpu->has_el3 = true; + } + + if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) { + cpu->has_el2 = true; + } + if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) { cpu->has_pmu = true; } @@ -1954,6 +1958,54 @@ static void arm_max_initfn(struct uc_struct *uc, CPUState *obj) /* old-style VFP short-vector support */ FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1, cpu->isar.mvfr0); + +// Unicorn: Enable this on ARM_MAX +//#ifdef CONFIG_USER_ONLY + /* We don't set these in system emulation mode for the moment, + * since we don't correctly set (all of) the ID registers to + * advertise them. + */ + set_feature(&cpu->env, ARM_FEATURE_V8); + { + uint32_t t; + + t = cpu->isar.id_isar5; + FIELD_DP32(t, ID_ISAR5, AES, 2, t); + FIELD_DP32(t, ID_ISAR5, SHA1, 1, t); + FIELD_DP32(t, ID_ISAR5, SHA2, 1, t); + FIELD_DP32(t, ID_ISAR5, CRC32, 1, t); + FIELD_DP32(t, ID_ISAR5, RDM, 1, t); + FIELD_DP32(t, ID_ISAR5, VCMA, 1, t); + cpu->isar.id_isar5 = t; + + t = cpu->isar.id_isar6; + FIELD_DP32(t, ID_ISAR6, JSCVT, 1, t); + FIELD_DP32(t, ID_ISAR6, DP, 1, t); + FIELD_DP32(t, ID_ISAR6, FHM, 1, t); + FIELD_DP32(t, ID_ISAR6, SB, 1, t); + FIELD_DP32(t, ID_ISAR6, SPECRES, 1, t); + cpu->isar.id_isar6 = t; + + t = cpu->isar.mvfr1; + FIELD_DP32(t, MVFR1, FPHP, 2, t); /* v8.0 FP support */ + cpu->isar.mvfr1 = t; + + t = cpu->isar.mvfr2; + FIELD_DP32(t, MVFR2, SIMDMISC, 3, t); /* SIMD MaxNum */ + FIELD_DP32(t, MVFR2, FPMISC, 4, t); /* FP MaxNum */ + cpu->isar.mvfr2 = t; + + t = cpu->isar.id_mmfr3; + FIELD_DP32(t, ID_MMFR3, PAN, 2, t); /* ATS1E1 */ + cpu->isar.id_mmfr3 = t; + + t = cpu->isar.id_mmfr4; + FIELD_DP32(t, ID_MMFR4, HPDS, 1, t); /* AA32HPD */ + FIELD_DP32(t, ID_MMFR4, AC2, 1, t); /* ACTLR2, HACTLR2 */ + FIELD_DP32(t, ID_MMFR4, CNP, 1, t); /* TTCNP */ + cpu->isar.id_mmfr4 = t; + } +//#endif } } #endif @@ -2056,15 +2108,15 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc) #if !defined(TARGET_AARCH64) if (uc->mode & UC_MODE_MCLASS) { - uc->cpu_model = 11; + uc->cpu_model = UC_CPU_ARM_CORTEX_M33; } else if (uc->mode & UC_MODE_ARM926) { - uc->cpu_model = 0; + uc->cpu_model = UC_CPU_ARM_926; } else if (uc->mode & UC_MODE_ARM946) { - uc->cpu_model = 1; + uc->cpu_model = UC_CPU_ARM_946; } else if (uc->mode & UC_MODE_ARM1176) { - uc->cpu_model = 5; + uc->cpu_model = UC_CPU_ARM_1176; } else if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 17; // cortex-a15 + uc->cpu_model = UC_CPU_ARM_CORTEX_A15; // cortex-a15 } else if (uc->cpu_model >= ARR_SIZE(arm_cpus)) { free(cpu); return NULL; diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 2e734a62..3ddb1da6 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -1264,6 +1264,7 @@ typedef enum CPSRWriteType { CPSRWriteExceptionReturn = 1, /* from guest exception return insn */ CPSRWriteRaw = 2, /* trust values, do not switch reg banks */ CPSRWriteByGDBStub = 3, /* from the GDB stub */ + CPSRWriteByUnicorn = 4 /* from uc_reg_write */ } CPSRWriteType; /* Set the CPSR. Note that some bits of mask must be all-set or all-clear.*/ diff --git a/qemu/target/arm/cpu64.c b/qemu/target/arm/cpu64.c index 52933554..95a7ef25 100644 --- a/qemu/target/arm/cpu64.c +++ b/qemu/target/arm/cpu64.c @@ -320,8 +320,6 @@ static const ARMCPUInfo aarch64_cpus[] = { ARMCPU *cpu_aarch64_init(struct uc_struct *uc) { - int i; - char *cpu_model = "cortex-a72"; ARMCPU *cpu; CPUState *cs; CPUClass *cc; @@ -331,6 +329,13 @@ ARMCPU *cpu_aarch64_init(struct uc_struct *uc) return NULL; } + if (uc->cpu_model == INT_MAX) { + uc->cpu_model = UC_CPU_AARCH64_A72; + } else if (uc->cpu_model >= sizeof(aarch64_cpus)) { + free(cpu); + return NULL; + } + cs = (CPUState *)cpu; cc = (CPUClass *)&cpu->cc; cs->cc = cc; @@ -349,33 +354,13 @@ ARMCPU *cpu_aarch64_init(struct uc_struct *uc) /* init ARMCPU */ arm_cpu_initfn(uc, cs); - for (i = 0; i < ARRAY_SIZE(aarch64_cpus); i++) { - if (strcmp(cpu_model, aarch64_cpus[i].name) == 0) { - if (aarch64_cpus[i].initfn) { - aarch64_cpus[i].initfn(uc, cs); - } - break; - } - } - if (i == ARRAY_SIZE(aarch64_cpus)) { - free(cpu); - return NULL; + if (aarch64_cpus[uc->cpu_model].initfn) { + aarch64_cpus[uc->cpu_model].initfn(uc, cs); } /* postinit ARMCPU */ arm_cpu_post_init(cs); - /* - * Unicorn: Hack to force to enable EL2/EL3 for aarch64 so that we can - * use the full 64bits virtual address space. - * - * While EL2/EL3 is enabled but running within EL1, we could - * get somewhat like "x86 flat mode", though aarch64 only allows - * a maximum of 52bits virtual address space. - */ - ARM_CPU(cs)->has_el2 = true; - ARM_CPU(cs)->has_el3 = true; - /* realize ARMCPU */ arm_cpu_realizefn(uc, cs); diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 48c9b013..d9e77e34 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -7983,9 +7983,12 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask, * to switch mode. (Those are caught by translate.c for writes * triggered by guest instructions.) */ - // mask &= ~CPSR_M; - // Unicorn: No, it can also be uc_reg_write - switch_mode(env, val & CPSR_M); + // Unicorn: No, it can also be uc_reg_write, let user switch registers banks. + if (write_type == CPSRWriteByUnicorn) { + switch_mode(env, val & CPSR_M); + } else { + mask &= ~CPSR_M; + } } else if (bad_mode_switch(env, val & CPSR_M, write_type)) { /* Attempt to switch to an invalid mode: this is UNPREDICTABLE in * v7, and has defined behaviour in v8: diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index 95bd93b5..f98a61bb 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -251,17 +251,17 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) case UC_ARM_REG_APSR: if (!arm_feature(env, ARM_FEATURE_M)) { cpsr_write(env, *(uint32_t *)value, - (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByInstr); + (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByUnicorn); } else { // Same with UC_ARM_REG_APSR_NZCVQ v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); } break; case UC_ARM_REG_APSR_NZCV: - cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByInstr); + cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByUnicorn); break; case UC_ARM_REG_CPSR: - cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByInstr); + cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByUnicorn); break; case UC_ARM_REG_SPSR: env->spsr = *(uint32_t *)value; diff --git a/qemu/target/i386/cpu.c b/qemu/target/i386/cpu.c index 3f1756e5..12953daa 100644 --- a/qemu/target/i386/cpu.c +++ b/qemu/target/i386/cpu.c @@ -5083,9 +5083,9 @@ X86CPU *cpu_x86_init(struct uc_struct *uc) if (uc->cpu_model == INT_MAX) { #ifdef TARGET_X86_64 - uc->cpu_model = 0; // qemu64 + uc->cpu_model = UC_CPU_X86_QEMU64; // qemu64 #else - uc->cpu_model = 4; // qemu32 + uc->cpu_model = UC_CPU_X86_QEMU32; // qemu32 #endif } else if (uc->cpu_model >= ARRAY_SIZE(builtin_x86_defs)) { free(cpu); diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index d6d74d92..ded937fe 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -321,6 +321,22 @@ static void reg_read(CPUX86State *env, unsigned int regid, void *value, dst[3] = hi_reg->_d[1]; return; } + + case UC_X86_REG_FIP: + *(uint64_t *)value = env->fpip; + return; + case UC_X86_REG_FCS: + *(uint16_t *)value = env->fpcs; + return; + case UC_X86_REG_FDP: + *(uint64_t *)value = env->fpdp; + return; + case UC_X86_REG_FDS: + *(uint16_t *)value = env->fpds; + return; + case UC_X86_REG_FOP: + *(uint16_t *)value = env->fpop; + return; } switch (mode) { @@ -912,6 +928,22 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, hi_reg->_d[1] = src[3]; return 0; } + + case UC_X86_REG_FIP: + env->fpip = *(uint64_t *)value; + return 0; + case UC_X86_REG_FCS: + env->fpcs = *(uint16_t *)value; + return 0; + case UC_X86_REG_FDP: + env->fpdp = *(uint64_t *)value; + return 0; + case UC_X86_REG_FDS: + env->fpds = *(uint16_t *)value; + return 0; + case UC_X86_REG_FOP: + env->fpop = *(uint16_t *)value; + return 0; } switch (mode) { diff --git a/qemu/target/m68k/cpu.c b/qemu/target/m68k/cpu.c index 8afc0c19..915b82ac 100644 --- a/qemu/target/m68k/cpu.c +++ b/qemu/target/m68k/cpu.c @@ -271,7 +271,7 @@ M68kCPU *cpu_m68k_init(struct uc_struct *uc) } if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 7; // cfv4e + uc->cpu_model = UC_CPU_M68K_CFV4E; // cfv4e } else if (uc->cpu_model >= ARRAY_SIZE(m68k_cpus_type_infos)) { free(cpu); return NULL; diff --git a/qemu/target/mips/cpu.c b/qemu/target/mips/cpu.c index 60fd1b93..4ddf65e0 100644 --- a/qemu/target/mips/cpu.c +++ b/qemu/target/mips/cpu.c @@ -164,14 +164,14 @@ MIPSCPU *cpu_mips_init(struct uc_struct *uc) #ifdef TARGET_MIPS64 if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 17; // R4000 + uc->cpu_model = UC_CPU_MIPS64_R4000; // R4000 } else if (uc->cpu_model + UC_CPU_MIPS32_I7200 + 1 >= mips_defs_number ) { free(cpu); return NULL; } #else if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 10; // 74kf + uc->cpu_model = UC_CPU_MIPS32_74KF; // 74kf } else if (uc->cpu_model >= mips_defs_number) { free(cpu); return NULL; diff --git a/qemu/target/ppc/translate_init.inc.c b/qemu/target/ppc/translate_init.inc.c index 3f40bd60..920ea602 100644 --- a/qemu/target/ppc/translate_init.inc.c +++ b/qemu/target/ppc/translate_init.inc.c @@ -11149,14 +11149,14 @@ PowerPCCPU *cpu_ppc_init(struct uc_struct *uc) memset(cpu, 0, sizeof(*cpu)); #ifdef TARGET_PPC64 if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 18 + UC_CPU_PPC_7457A_V1_2 + 1; // power10_v1.0 + uc->cpu_model = UC_CPU_PPC_POWER10_V1_0 + UC_CPU_PPC_7457A_V1_2 + 1; // power10_v1.0 } else if (uc->cpu_model + UC_CPU_PPC_7457A_V1_2 + 1 >= ARRAY_SIZE(ppc_cpus)) { free(cpu); return NULL; } #else if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 289; // 7457a_v1.2 + uc->cpu_model = UC_CPU_PPC_7457A_V1_2; // 7457a_v1.2 } else if (uc->cpu_model >= ARRAY_SIZE(ppc_cpus)) { free(cpu); return NULL; @@ -11196,5 +11196,7 @@ PowerPCCPU *cpu_ppc_init(struct uc_struct *uc) qemu_init_vcpu(cs); + ppc_cpu_reset((CPUState *)cpu); + return cpu; } diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index d8d50d57..52737f76 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -9,6 +9,8 @@ #include "unicorn_common.h" #include "uc_priv.h" #include "unicorn.h" +#include "helper_regs.h" +#include "cpu.h" #ifdef TARGET_PPC64 typedef uint64_t ppcreg_t; @@ -16,6 +18,65 @@ typedef uint64_t ppcreg_t; typedef uint32_t ppcreg_t; #endif +// Unicorn version to ensure writing MSR without exception +static inline int uc_ppc_store_msr(CPUPPCState *env, target_ulong value, + int alter_hv) +{ + // int excp; + // CPUState *cs = env_cpu(env); + + // excp = 0; + value &= env->msr_mask; + + /* Neither mtmsr nor guest state can alter HV */ + if (!alter_hv || !(env->msr & MSR_HVB)) { + value &= ~MSR_HVB; + value |= env->msr & MSR_HVB; + } + if (((value >> MSR_IR) & 1) != msr_ir || + ((value >> MSR_DR) & 1) != msr_dr) { + // cpu_interrupt_exittb(cs); + } + if ((env->mmu_model & POWERPC_MMU_BOOKE) && + ((value >> MSR_GS) & 1) != msr_gs) { + // cpu_interrupt_exittb(cs); + } + if (unlikely((env->flags & POWERPC_FLAG_TGPR) && + ((value ^ env->msr) & (1 << MSR_TGPR)))) { + /* Swap temporary saved registers with GPRs */ + hreg_swap_gpr_tgpr(env); + } + if (unlikely((value >> MSR_EP) & 1) != msr_ep) { + /* Change the exception prefix on PowerPC 601 */ + env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000; + } + /* + * If PR=1 then EE, IR and DR must be 1 + * + * Note: We only enforce this on 64-bit server processors. + * It appears that: + * - 32-bit implementations supports PR=1 and EE/DR/IR=0 and MacOS + * exploits it. + * - 64-bit embedded implementations do not need any operation to be + * performed when PR is set. + */ + if (is_book3s_arch2x(env) && ((value >> MSR_PR) & 1)) { + value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR); + } + + env->msr = value; + hreg_compute_hflags(env); + + // if (unlikely(msr_pow == 1)) { + // if (!env->pending_interrupts && (*env->check_pow)(env)) { + // cs->halted = 1; + // excp = EXCP_HALTED; + // } + // } + + return 0; +} + static uint64_t ppc_mem_redirect(uint64_t address) { /* // kseg0 range masks off high address bit @@ -79,6 +140,7 @@ void ppc_reg_reset(struct uc_struct *uc) env->nip = 0; } +// http://www.csit-sun.pub.ro/~cpop/Documentatie_SMP/Motorola_PowerPC/PowerPc/GenInfo/pemch2.pdf static void reg_read(CPUPPCState *env, unsigned int regid, void *value) { if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) @@ -90,12 +152,65 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value) case UC_PPC_REG_PC: *(ppcreg_t *)value = env->nip; break; - /* case UC_PPC_REG_CP0_CONFIG3: - *(mipsreg_t *)value = env->CP0_Config3; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; - break; */ + case UC_PPC_REG_FPR0: + case UC_PPC_REG_FPR1: + case UC_PPC_REG_FPR2: + case UC_PPC_REG_FPR3: + case UC_PPC_REG_FPR4: + case UC_PPC_REG_FPR5: + case UC_PPC_REG_FPR6: + case UC_PPC_REG_FPR7: + case UC_PPC_REG_FPR8: + case UC_PPC_REG_FPR9: + case UC_PPC_REG_FPR10: + case UC_PPC_REG_FPR11: + case UC_PPC_REG_FPR12: + case UC_PPC_REG_FPR13: + case UC_PPC_REG_FPR14: + case UC_PPC_REG_FPR15: + case UC_PPC_REG_FPR16: + case UC_PPC_REG_FPR17: + case UC_PPC_REG_FPR18: + case UC_PPC_REG_FPR19: + case UC_PPC_REG_FPR20: + case UC_PPC_REG_FPR21: + case UC_PPC_REG_FPR22: + case UC_PPC_REG_FPR23: + case UC_PPC_REG_FPR24: + case UC_PPC_REG_FPR25: + case UC_PPC_REG_FPR26: + case UC_PPC_REG_FPR27: + case UC_PPC_REG_FPR28: + case UC_PPC_REG_FPR29: + case UC_PPC_REG_FPR30: + case UC_PPC_REG_FPR31: + *(uint64_t *)value = env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0); + break; + case UC_PPC_REG_CR0: + case UC_PPC_REG_CR1: + case UC_PPC_REG_CR2: + case UC_PPC_REG_CR3: + case UC_PPC_REG_CR4: + case UC_PPC_REG_CR5: + case UC_PPC_REG_CR6: + case UC_PPC_REG_CR7: + *(uint32_t *)value = env->crf[regid - UC_PPC_REG_CR0]; + break; + case UC_PPC_REG_LR: + *(ppcreg_t *)value = env->lr; + break; + case UC_PPC_REG_CTR: + *(ppcreg_t *)value = env->ctr; + break; + case UC_PPC_REG_MSR: + *(ppcreg_t *)value = env->msr; + break; + case UC_PPC_REG_XER: + *(uint32_t *)value = env->xer; + break; + case UC_PPC_REG_FPSCR: + *(uint32_t *)value = env->fpscr; + break; } } @@ -113,12 +228,65 @@ static void reg_write(CPUPPCState *env, unsigned int regid, const void *value) case UC_PPC_REG_PC: env->nip = *(ppcreg_t *)value; break; - /* case UC_MIPS_REG_CP0_CONFIG3: - env->CP0_Config3 = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; - break; */ + case UC_PPC_REG_FPR0: + case UC_PPC_REG_FPR1: + case UC_PPC_REG_FPR2: + case UC_PPC_REG_FPR3: + case UC_PPC_REG_FPR4: + case UC_PPC_REG_FPR5: + case UC_PPC_REG_FPR6: + case UC_PPC_REG_FPR7: + case UC_PPC_REG_FPR8: + case UC_PPC_REG_FPR9: + case UC_PPC_REG_FPR10: + case UC_PPC_REG_FPR11: + case UC_PPC_REG_FPR12: + case UC_PPC_REG_FPR13: + case UC_PPC_REG_FPR14: + case UC_PPC_REG_FPR15: + case UC_PPC_REG_FPR16: + case UC_PPC_REG_FPR17: + case UC_PPC_REG_FPR18: + case UC_PPC_REG_FPR19: + case UC_PPC_REG_FPR20: + case UC_PPC_REG_FPR21: + case UC_PPC_REG_FPR22: + case UC_PPC_REG_FPR23: + case UC_PPC_REG_FPR24: + case UC_PPC_REG_FPR25: + case UC_PPC_REG_FPR26: + case UC_PPC_REG_FPR27: + case UC_PPC_REG_FPR28: + case UC_PPC_REG_FPR29: + case UC_PPC_REG_FPR30: + case UC_PPC_REG_FPR31: + env->vsr[regid - UC_PPC_REG_FPR0].VsrD(0) = *(uint64_t *)value; + break; + case UC_PPC_REG_CR0: + case UC_PPC_REG_CR1: + case UC_PPC_REG_CR2: + case UC_PPC_REG_CR3: + case UC_PPC_REG_CR4: + case UC_PPC_REG_CR5: + case UC_PPC_REG_CR6: + case UC_PPC_REG_CR7: + env->crf[regid - UC_PPC_REG_CR0] = *(uint32_t *)value; + break; + case UC_PPC_REG_LR: + env->lr = *(ppcreg_t *)value; + break; + case UC_PPC_REG_CTR: + env->ctr = *(ppcreg_t *)value; + break; + case UC_PPC_REG_MSR: + uc_ppc_store_msr(env, *(ppcreg_t *)value, 0); + break; + case UC_PPC_REG_XER: + env->xer = *(uint32_t *)value; + break; + case UC_PPC_REG_FPSCR: + store_fpscr(env, *(uint32_t *)value, 0xffffffff); + break; } } diff --git a/qemu/target/riscv/cpu.c b/qemu/target/riscv/cpu.c index 15d9349e..d58204ad 100644 --- a/qemu/target/riscv/cpu.c +++ b/qemu/target/riscv/cpu.c @@ -342,12 +342,12 @@ RISCVCPU *cpu_riscv_init(struct uc_struct *uc) #ifdef TARGET_RISCV32 if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 3; + uc->cpu_model = UC_CPU_RISCV32_SIFIVE_U34; } #else /* TARGET_RISCV64 */ if (uc->cpu_model == INT_MAX) { - uc->cpu_model = 3; + uc->cpu_model = UC_CPU_RISCV64_SIFIVE_U54; } #endif diff --git a/qemu/target/sparc/cpu.c b/qemu/target/sparc/cpu.c index 461d7687..489819bc 100644 --- a/qemu/target/sparc/cpu.c +++ b/qemu/target/sparc/cpu.c @@ -525,9 +525,9 @@ SPARCCPU *cpu_sparc_init(struct uc_struct *uc) if (uc->cpu_model == INT_MAX) { #ifdef TARGET_SPARC64 - uc->cpu_model = 11; // Sun UltraSparc IV + uc->cpu_model = UC_CPU_SPARC64_SUN_ULTRASPARC_IV; // Sun UltraSparc IV #else - uc->cpu_model = 12; // Leon 3 + uc->cpu_model = UC_CPU_SPARC32_LEON3; // Leon 3 #endif } else if (uc->cpu_model >= ARRAY_SIZE(sparc_defs)) { free(cpu); diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 84bbb9f1..5176430e 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -58,9 +58,9 @@ static void release_common(void *t) // these function is not available outside qemu // so we keep them here instead of outside uc_close. + memory_free(s->uc); address_space_destroy(&s->uc->address_space_memory); address_space_destroy(&s->uc->address_space_io); - memory_free(s->uc); /* clean up uc->l1_map. */ tb_cleanup(s->uc); /* clean up tcg_ctx->code_gen_buffer. */ diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index b148b204..100f8b5c 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -325,6 +325,8 @@ static void test_arm_usr32_to_svc32() OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); r_sp = 0x12345678; OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); + r_lr = 0x00102220; + OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); r_cpsr = 0x4000009b; // UND32 OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); @@ -332,18 +334,28 @@ static void test_arm_usr32_to_svc32() OK(uc_reg_write(uc, UC_ARM_REG_SPSR, &r_spsr)); r_sp = 0xDEAD0000; OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); - r_lr = code_start + 8; + r_lr = 0x00509998; OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); + OK(uc_reg_read(uc, UC_ARM_REG_CPSR, &r_cpsr)); + TEST_CHECK((r_cpsr & ((1 << 4) - 1)) == 0xb); // We are in UND32 + r_cpsr = 0x40000090; // USR32 OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); r_sp = 0x0010000; OK(uc_reg_write(uc, UC_ARM_REG_R13, &r_sp)); + r_lr = 0x0001234; + OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); + + OK(uc_reg_read(uc, UC_ARM_REG_CPSR, &r_cpsr)); + TEST_CHECK((r_cpsr & ((1 << 4) - 1)) == 0); // We are in USR32 r_cpsr = 0x40000093; // SVC32 OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); + OK(uc_reg_read(uc, UC_ARM_REG_CPSR, &r_cpsr)); OK(uc_reg_read(uc, UC_ARM_REG_SP, &r_sp)); + TEST_CHECK((r_cpsr & ((1 << 4) - 1)) == 3); // We are in SVC32 TEST_CHECK(r_sp == 0x12345678); OK(uc_close(uc)); @@ -398,6 +410,67 @@ static void test_arm_thumb_smlabb() OK(uc_close(uc)); } +static void test_arm_not_allow_privilege_escalation() +{ + uc_engine *uc; + int r_cpsr, r_sp, r_spsr, r_lr; + // E3C6601F : BIC r6, r6, #&1F + // E3866013 : ORR r6, r6, #&13 + // E121F006 : MSR cpsr_c, r6 ; switch to SVC32 (should be ineffective + // from USR32) + // E1A00000 : MOV r0,r0 EF000011 : SWI OS_Exit + char code[] = "\x1f\x60\xc6\xe3\x13\x60\x86\xe3\x06\xf0\x21\xe1\x00\x00\xa0" + "\xe1\x11\x00\x00\xef"; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_ARM_CORTEX_A15); + + // https://www.keil.com/pack/doc/CMSIS/Core_A/html/group__CMSIS__CPSR.html + r_cpsr = 0x40000013; // SVC32 + OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); + r_spsr = 0x40000013; + OK(uc_reg_write(uc, UC_ARM_REG_SPSR, &r_spsr)); + r_sp = 0x12345678; + OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); + r_lr = 0x00102220; + OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); + + r_cpsr = 0x40000010; // USR32 + OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); + r_sp = 0x0010000; + OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); + r_lr = 0x0001234; + OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); + + uc_assert_err( + UC_ERR_EXCEPTION, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_ARM_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_ARM_REG_LR, &r_lr)); + OK(uc_reg_read(uc, UC_ARM_REG_CPSR, &r_cpsr)); + + TEST_CHECK((r_cpsr & ((1 << 4) - 1)) == 0); // Stay in USR32 + TEST_CHECK(r_lr == 0x1234); + TEST_CHECK(r_sp == 0x10000); + + OK(uc_close(uc)); +} + +static void test_arm_mrc() +{ + uc_engine *uc; + // mrc p15, #0, r0, c1, c1, #0 + char code[] = "\x11\x0F\x11\xEE"; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_ARM_MAX); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb_sub", test_arm_thumb_sub}, {"test_armeb_sub", test_armeb_sub}, @@ -410,4 +483,7 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_usr32_to_svc32", test_arm_usr32_to_svc32}, {"test_arm_v8", test_arm_v8}, {"test_arm_thumb_smlabb", test_arm_thumb_smlabb}, + {"test_arm_not_allow_privilege_escalation", + test_arm_not_allow_privilege_escalation}, + {"test_arm_mrc", test_arm_mrc}, {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 9ae38b0f..0c177164 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -4,9 +4,10 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, - const char *code, uint64_t size) + const char *code, uint64_t size, uc_cpu_arm cpu) { OK(uc_open(arch, mode, uc)); + OK(uc_ctl_set_cpu_model(*uc, cpu)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } @@ -27,7 +28,8 @@ static void test_arm64_until() uint64_t r_pc = 0x00000000; uint64_t r_x28 = 0x12341234; - uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_AARCH64_A72); // initialize machine registers OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16)); @@ -54,7 +56,8 @@ static void test_arm64_code_patching() { uc_engine *uc; char code[] = "\x00\x04\x00\x11"; // add w0, w0, 0x1 - uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_AARCH64_A72); // zero out x0 uint64_t r_x0 = 0x0; OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); @@ -83,7 +86,8 @@ static void test_arm64_code_patching_count() { uc_engine *uc; char code[] = "\x00\x04\x00\x11"; // add w0, w0, 0x1 - uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_AARCH64_A72); // zero out x0 uint64_t r_x0 = 0x0; OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); @@ -109,7 +113,33 @@ static void test_arm64_code_patching_count() OK(uc_close(uc)); } +static void test_arm64_v8_pac() +{ + uc_engine *uc; + char code[] = "\x28\xfd\xea\xc8"; // casal x10, x8, [x9] + uint64_t r_x9, r_x8, mem; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_AARCH64_MAX); + + OK(uc_mem_map(uc, 0x40000, 0x1000, UC_PROT_ALL)); + OK(uc_mem_write(uc, 0x40000, "\x00\x00\x00\x00\x00\x00\x00\x00", 8)); + r_x9 = 0x40000; + OK(uc_reg_write(uc, UC_ARM64_REG_X9, &r_x9)); + r_x8 = 0xdeadbeafdeadbeaf; + OK(uc_reg_write(uc, UC_ARM64_REG_X8, &r_x8)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_mem_read(uc, 0x40000, (void *)&mem, 8)); + + TEST_CHECK(mem == r_x8); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, {"test_arm64_code_patching_count", test_arm64_code_patching_count}, + {"test_arm64_v8_pac", test_arm64_v8_pac}, {NULL, NULL}}; diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index 41fed7c4..21ba64fa 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -34,4 +34,35 @@ static void test_ppc32_add() OK(uc_close(uc)); } -TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {NULL, NULL}}; \ No newline at end of file +// https://www.ibm.com/docs/en/aix/7.2?topic=set-fadd-fa-floating-add-instruction +static void test_ppc32_fadd() +{ + uc_engine *uc; + char code[] = "\xfc\xc4\x28\x2a"; // fadd 6, 4, 5 + uint32_t r_msr; + uint64_t r_fpr4, r_fpr5, r_fpr6; + + uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); + + OK(uc_reg_read(uc, UC_PPC_REG_MSR, &r_msr)); + r_msr |= (1 << 13); // Big endian + OK(uc_reg_write(uc, UC_PPC_REG_MSR, &r_msr)); // enable FP + + r_fpr4 = 0xC053400000000000ul; + r_fpr5 = 0x400C000000000000ul; + OK(uc_reg_write(uc, UC_PPC_REG_FPR4, &r_fpr4)); + OK(uc_reg_write(uc, UC_PPC_REG_FPR5, &r_fpr5)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_PPC_REG_FPR6, &r_fpr6)); + + TEST_CHECK(r_fpr6 == 0xC052600000000000ul); + + OK(uc_close(uc)); +} + +TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, + {"test_ppc32_fadd", test_ppc32_fadd}, + {NULL, NULL}}; \ No newline at end of file