From a3dbc571bd2b6168a0cb5da5850a3a0696251b4e Mon Sep 17 00:00:00 2001 From: Galen Williamson Date: Fri, 8 Mar 2024 15:00:02 -0500 Subject: [PATCH 1/2] added lifting for EXTSW LD LDU LDUX LDX SLD SRAD SRADI SRD STD STDU STDUX STDX --- arch/powerpc/arch_ppc.cpp | 16 ++-- arch/powerpc/disassembler.cpp | 2 +- arch/powerpc/disassembler.h | 2 +- arch/powerpc/il.cpp | 147 +++++++++++++++++++++++++++++++--- 4 files changed, 145 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 2f657b7a8f..e44564c414 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -281,6 +281,7 @@ class PowerpcArchitecture: public Architecture { private: BNEndianness endian; + size_t addressSize; /* this can maybe be moved to the API later */ BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, size_t size, bool zeroExtend = false) @@ -296,9 +297,10 @@ class PowerpcArchitecture: public Architecture public: /* initialization list */ - PowerpcArchitecture(const char* name, BNEndianness endian_): Architecture(name) + PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4): Architecture(name) { endian = endian_; + addressSize = addressSize_; } /*************************************************************************/ @@ -312,7 +314,7 @@ class PowerpcArchitecture: public Architecture virtual size_t GetAddressSize() const override { //MYLOG("%s()\n", __func__); - return 4; + return addressSize; } virtual size_t GetDefaultIntegerSize() const override @@ -360,7 +362,7 @@ class PowerpcArchitecture: public Architecture } /* decompose the instruction to get branch info */ - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { MYLOG("ERROR: powerpc_decompose()\n"); return false; } @@ -622,7 +624,7 @@ class PowerpcArchitecture: public Architecture if (DoesQualifyForLocalDisassembly(data)) return PerformLocalDisassembly(data, addr, len, result); - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; } @@ -748,7 +750,7 @@ class PowerpcArchitecture: public Architecture goto cleanup; } - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { MYLOG("ERROR: powerpc_decompose()\n"); il.AddInstruction(il.Undefined()); goto cleanup; @@ -2471,13 +2473,13 @@ extern "C" Architecture* ppc = new PowerpcArchitecture("ppc", BigEndian); Architecture::Register(ppc); - Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian); + Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian, 8); Architecture::Register(ppc64); Architecture* ppc_le = new PowerpcArchitecture("ppc_le", LittleEndian); Architecture::Register(ppc_le); - Architecture* ppc64_le = new PowerpcArchitecture("ppc64_le", LittleEndian); + Architecture* ppc64_le = new PowerpcArchitecture("ppc64_le", LittleEndian, 8); Architecture::Register(ppc64_le); /* calling conventions */ diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 66a8b36dd3..480ab658bc 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -69,7 +69,7 @@ powerpc_release(void) extern "C" int powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, - struct decomp_result *res) + struct decomp_result *res, bool is_64bit) { int rc = -1; res->status = STATUS_ERROR_UNSPEC; diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index e1701687c9..e1d3ca5567 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -62,7 +62,7 @@ struct decomp_result extern "C" int powerpc_init(void); extern "C" void powerpc_release(void); extern "C" int powerpc_decompose(const uint8_t *data, int size, uint32_t addr, - bool lil_end, struct decomp_result *result); + bool lil_end, struct decomp_result *result, bool is_64bit); extern "C" int powerpc_disassemble(struct decomp_result *, char *buf, size_t len); extern "C" const char *powerpc_reg_to_str(uint32_t rid); diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 1de2c5c090..28c95ced39 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -845,6 +845,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; + case PPC_INS_EXTSW: + REQUIRE2OPS + ei0 = il.Register(8, oper1->reg); + ei0 = il.LowPart(4, ei0); + ei0 = il.SignExtend(8, ei0); + ei0 = il.SetRegister(8, oper0->reg, ei0, + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + ); + il.AddInstruction(ei0); + break; + case PPC_INS_ISEL: REQUIRE4OPS { @@ -1030,6 +1041,44 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; + /* + load doubleword [and update] + */ + case PPC_INS_LD: + case PPC_INS_LDU: + REQUIRE2OPS + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = il.Load(8, ei0); // [d(rA)] + ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + il.AddInstruction(ei0); + + // if update, rA is set to effective address (d(rA)) + if(insn->id == PPC_INS_LWZU) { + ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1)); + il.AddInstruction(ei0); + } + + break; + + /* + load doubleword [and update] + */ + case PPC_INS_LDX: + case PPC_INS_LDUX: + REQUIRE3OPS + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = il.Load(8, il.Add(8, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)] + ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + il.AddInstruction(ei0); + + // if update, rA is set to effective address (d(rA)) + if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { + ei0 = il.SetRegister(8, oper1->reg, operToIL(il, oper1)); + il.AddInstruction(ei0); + } + + break; + case PPC_INS_LHBRX: REQUIRE3OPS ByteReversedLoad(il, ppc, 2); @@ -1331,6 +1380,44 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; + /* store double word [with update] */ + case PPC_INS_STD: + case PPC_INS_STDU: /* store(size, addr, val) */ + REQUIRE2OPS + ei0 = il.Store(8, + operToIL(il, oper1, OTI_GPR0_ZERO), + operToIL(il, oper0) + ); + il.AddInstruction(ei0); + + // if update, then rA gets updated address + if(insn->id == PPC_INS_STWU) { + ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1)); + il.AddInstruction(ei0); + } + + break; + + /* store word indexed [with update] */ + case PPC_INS_STDX: + case PPC_INS_STDUX: /* store(size, addr, val) */ + REQUIRE3OPS + ei0 = il.Store(8, + il.Add(8, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)), + operToIL(il, oper0) + ); + il.AddInstruction(ei0); + + // if update, then rA gets updated address + if(insn->id == PPC_INS_STDUX) { + ei0 = il.SetRegister(8, oper1->reg, + il.Add(8, operToIL(il, oper1), operToIL(il, oper2)) + ); + il.AddInstruction(ei0); + } + + break; + case PPC_INS_RLWIMI: REQUIRE5OPS { @@ -1484,6 +1571,21 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, )); break; + case PPC_INS_SLD: + case PPC_INS_SRD: + REQUIRE3OPS + ei0 = il.Register(8, oper1->reg); + // permit bit 25 to survive to enable clearing the whole register + ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x7f)); + if (insn->id == PPC_INS_SLD) + ei0 = il.ShiftLeft(8, ei0, ei1); + else + ei0 = il.LogicalShiftRight(8, ei0, ei1); + il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + )); + break; + case PPC_INS_SRAW: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); @@ -1503,6 +1605,25 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, )); break; + case PPC_INS_SRAD: + REQUIRE3OPS + ei0 = il.Register(8, oper1->reg); + ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x3f)); + ei0 = il.ArithShiftRight(8, ei0, ei1, IL_FLAGWRITE_XER_CA); + il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + )); + break; + + case PPC_INS_SRADI: + REQUIRE3OPS + ei0 = il.Register(8, oper1->reg); + ei0 = il.ArithShiftRight(8, ei0, il.Const(8, oper2->imm), IL_FLAGWRITE_XER_CA); + il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + )); + break; + case PPC_INS_MULLW: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); @@ -1768,7 +1889,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_EVSUBFW: case PPC_INS_EVSUBIFW: case PPC_INS_EVXOR: - case PPC_INS_EXTSW: + // case PPC_INS_EXTSW: case PPC_INS_FABS: case PPC_INS_FADD: case PPC_INS_FADDS: @@ -1815,12 +1936,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ICBI: case PPC_INS_ICCCI: case PPC_INS_ISYNC: - case PPC_INS_LD: + // case PPC_INS_LD: case PPC_INS_LDARX: case PPC_INS_LDBRX: - case PPC_INS_LDU: - case PPC_INS_LDUX: - case PPC_INS_LDX: + // case PPC_INS_LDU: + // case PPC_INS_LDUX: + // case PPC_INS_LDX: case PPC_INS_LFD: case PPC_INS_LFDU: case PPC_INS_LFDUX: @@ -1889,16 +2010,16 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SLBIE: case PPC_INS_SLBMFEE: case PPC_INS_SLBMTE: - case PPC_INS_SLD: - case PPC_INS_SRAD: - case PPC_INS_SRADI: - case PPC_INS_SRD: - case PPC_INS_STD: + // case PPC_INS_SLD: + // case PPC_INS_SRAD: + // case PPC_INS_SRADI: + // case PPC_INS_SRD: + // case PPC_INS_STD: case PPC_INS_STDBRX: case PPC_INS_STDCX: - case PPC_INS_STDU: - case PPC_INS_STDUX: - case PPC_INS_STDX: + // case PPC_INS_STDU: + // case PPC_INS_STDUX: + // case PPC_INS_STDX: case PPC_INS_STFD: case PPC_INS_STFDU: case PPC_INS_STFDUX: From 1c3399a71e3f15b3289efdd44fb9a0b63c641009 Mon Sep 17 00:00:00 2001 From: Galen Williamson Date: Tue, 26 Mar 2024 14:56:35 -0400 Subject: [PATCH 2/2] added lifting for EXTSW LD LDU LDUX LDX SLD SRAD SRADI SRD STD STDU STDUX STDX (cleanup) --- arch/powerpc/il.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 28c95ced39..76cf74199f 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1889,7 +1889,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_EVSUBFW: case PPC_INS_EVSUBIFW: case PPC_INS_EVXOR: - // case PPC_INS_EXTSW: case PPC_INS_FABS: case PPC_INS_FADD: case PPC_INS_FADDS: @@ -1936,12 +1935,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ICBI: case PPC_INS_ICCCI: case PPC_INS_ISYNC: - // case PPC_INS_LD: case PPC_INS_LDARX: case PPC_INS_LDBRX: - // case PPC_INS_LDU: - // case PPC_INS_LDUX: - // case PPC_INS_LDX: case PPC_INS_LFD: case PPC_INS_LFDU: case PPC_INS_LFDUX: @@ -2010,16 +2005,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SLBIE: case PPC_INS_SLBMFEE: case PPC_INS_SLBMTE: - // case PPC_INS_SLD: - // case PPC_INS_SRAD: - // case PPC_INS_SRADI: - // case PPC_INS_SRD: - // case PPC_INS_STD: case PPC_INS_STDBRX: case PPC_INS_STDCX: - // case PPC_INS_STDU: - // case PPC_INS_STDUX: - // case PPC_INS_STDX: case PPC_INS_STFD: case PPC_INS_STFDU: case PPC_INS_STFDUX: