diff --git a/arch/x86/CMakeLists.txt b/arch/x86/CMakeLists.txt index 70dd24cb08..e888c0fd69 100644 --- a/arch/x86/CMakeLists.txt +++ b/arch/x86/CMakeLists.txt @@ -47,7 +47,7 @@ target_include_directories(arch_x86 PRIVATE ${PROJECT_BINARY_DIR}/obj/include-private) add_compile_definitions(XED_DECODER XED_AMD_ENABLED XED_VIA_ENABLED XED_AVX XED_SUPPORTS_AVX512 - XED_MPX XED_CET XED_SUPPORTS_SHA XED_SUPPORTS_WBNOINVD) + XED_MPX XED_CET XED_SUPPORTS_SHA XED_SUPPORTS_WBNOINVD XED_APX) target_link_libraries(arch_x86 binaryninjaapi) diff --git a/arch/x86/arch_x86.cpp b/arch/x86/arch_x86.cpp index b448862334..d81879d18e 100644 --- a/arch/x86/arch_x86.cpp +++ b/arch/x86/arch_x86.cpp @@ -1423,6 +1423,7 @@ void X86CommonArchitecture::GetOperandTextBNIntel(const xed_decoded_inst_t* cons break; } case XED_OPERAND_PTR: + case XED_OPERAND_ABSBR: { stringstream sstream; sstream << "0x" << hex; @@ -3282,6 +3283,8 @@ class X64Architecture: public X86CommonArchitecture XED_REG_RAX, XED_REG_RCX, XED_REG_RDX, XED_REG_RBX, // 64+ XED_REG_R8, XED_REG_R9, XED_REG_R10, XED_REG_R11, XED_REG_R12, XED_REG_R13, XED_REG_R14, XED_REG_R15, // 64+ + XED_REG_R16, XED_REG_R17, XED_REG_R18, XED_REG_R19, XED_REG_R20, XED_REG_R21, XED_REG_R22, XED_REG_R23, // APX + XED_REG_R24, XED_REG_R25, XED_REG_R26, XED_REG_R27, XED_REG_R28, XED_REG_R29, XED_REG_R30, XED_REG_R31, // APX XED_REG_BNDCFGU, XED_REG_BNDSTATUS, // 64 briefly. MPX control registers XED_REG_K0, XED_REG_K1, XED_REG_K2, XED_REG_K3, XED_REG_K4, XED_REG_K5, XED_REG_K6, XED_REG_K7, // 64+ AVX bit-masking registers (also not confident in size) @@ -3310,6 +3313,8 @@ class X64Architecture: public X86CommonArchitecture XED_REG_AH, XED_REG_CH, XED_REG_DH, XED_REG_BH, XED_REG_AL, XED_REG_CL, XED_REG_DL, XED_REG_BL, // 16+ XED_REG_SPL, XED_REG_BPL, XED_REG_SIL, XED_REG_DIL, // 64+ XED_REG_R8B, XED_REG_R9B, XED_REG_R10B, XED_REG_R11B, XED_REG_R12B, XED_REG_R13B, XED_REG_R14B, XED_REG_R15B, // 64+ + XED_REG_R16B, XED_REG_R17B, XED_REG_R18B, XED_REG_R19B, XED_REG_R20B, XED_REG_R21B, XED_REG_R22B, XED_REG_R23B, // APX + XED_REG_R24B, XED_REG_R25B, XED_REG_R26B, XED_REG_R27B, XED_REG_R28B, XED_REG_R29B, XED_REG_R30B, XED_REG_R31B, // APX // 16-Bit XED_REG_IP, // 16+ @@ -3323,6 +3328,8 @@ class X64Architecture: public X86CommonArchitecture XED_REG_AX, XED_REG_CX, XED_REG_DX, XED_REG_BX, // 16+ XED_REG_R8W, XED_REG_R9W, XED_REG_R10W, XED_REG_R11W, XED_REG_R12W, XED_REG_R13W, XED_REG_R14W, XED_REG_R15W, // 64+ + XED_REG_R16W, XED_REG_R17W, XED_REG_R18W, XED_REG_R19W, XED_REG_R20W, XED_REG_R21W, XED_REG_R22W, XED_REG_R23W, // APX + XED_REG_R24W, XED_REG_R25W, XED_REG_R26W, XED_REG_R27W, XED_REG_R28W, XED_REG_R29W, XED_REG_R30W, XED_REG_R31W, // APX // 32-Bit XED_REG_EIP, // 32+ @@ -3331,6 +3338,8 @@ class X64Architecture: public X86CommonArchitecture XED_REG_EAX, XED_REG_ECX, XED_REG_EDX, XED_REG_EBX, // 32+ XED_REG_R8D, XED_REG_R9D, XED_REG_R10D, XED_REG_R11D, XED_REG_R12D, XED_REG_R13D, XED_REG_R14D, XED_REG_R15D, // 64+ + XED_REG_R16D, XED_REG_R17D, XED_REG_R18D, XED_REG_R19D, XED_REG_R20D, XED_REG_R21D, XED_REG_R22D, XED_REG_R23D, // APX + XED_REG_R24D, XED_REG_R25D, XED_REG_R26D, XED_REG_R27D, XED_REG_R28D, XED_REG_R29D, XED_REG_R30D, XED_REG_R31D, // APX // 48-Bit (All 32+) XED_REG_GDTR, // Global Descriptor Table Register @@ -3350,6 +3359,8 @@ class X64Architecture: public X86CommonArchitecture XED_REG_RAX, XED_REG_RCX, XED_REG_RDX, XED_REG_RBX, // 64+ XED_REG_R8, XED_REG_R9, XED_REG_R10, XED_REG_R11, XED_REG_R12, XED_REG_R13, XED_REG_R14, XED_REG_R15, // 64+ + XED_REG_R16, XED_REG_R17, XED_REG_R18, XED_REG_R19, XED_REG_R20, XED_REG_R21, XED_REG_R22, XED_REG_R23, // APX + XED_REG_R24, XED_REG_R25, XED_REG_R26, XED_REG_R27, XED_REG_R28, XED_REG_R29, XED_REG_R30, XED_REG_R31, // APX XED_REG_BNDCFGU, XED_REG_BNDSTATUS, // 64 briefly. MPX control registers XED_REG_K0, XED_REG_K1, XED_REG_K2, XED_REG_K3, XED_REG_K4, XED_REG_K5, XED_REG_K6, XED_REG_K7, // 64+ AVX bit-masking registers (also not confident in size) @@ -3405,6 +3416,23 @@ class X64Architecture: public X86CommonArchitecture case XED_REG_R14B: return RegisterInfo(XED_REG_R14, 0, 1); case XED_REG_R15B: return RegisterInfo(XED_REG_R15, 0, 1); + case XED_REG_R16B: return RegisterInfo(XED_REG_R16, 0, 1); + case XED_REG_R17B: return RegisterInfo(XED_REG_R17, 0, 1); + case XED_REG_R18B: return RegisterInfo(XED_REG_R18, 0, 1); + case XED_REG_R19B: return RegisterInfo(XED_REG_R19, 0, 1); + case XED_REG_R20B: return RegisterInfo(XED_REG_R20, 0, 1); + case XED_REG_R21B: return RegisterInfo(XED_REG_R21, 0, 1); + case XED_REG_R22B: return RegisterInfo(XED_REG_R22, 0, 1); + case XED_REG_R23B: return RegisterInfo(XED_REG_R23, 0, 1); + case XED_REG_R24B: return RegisterInfo(XED_REG_R24, 0, 1); + case XED_REG_R25B: return RegisterInfo(XED_REG_R25, 0, 1); + case XED_REG_R26B: return RegisterInfo(XED_REG_R26, 0, 1); + case XED_REG_R27B: return RegisterInfo(XED_REG_R27, 0, 1); + case XED_REG_R28B: return RegisterInfo(XED_REG_R28, 0, 1); + case XED_REG_R29B: return RegisterInfo(XED_REG_R29, 0, 1); + case XED_REG_R30B: return RegisterInfo(XED_REG_R30, 0, 1); + case XED_REG_R31B: return RegisterInfo(XED_REG_R31, 0, 1); + // 16-Bit case XED_REG_IP: return RegisterInfo(XED_REG_RIP, 0, 2); @@ -3435,6 +3463,23 @@ class X64Architecture: public X86CommonArchitecture case XED_REG_R14W: return RegisterInfo(XED_REG_R14, 0, 2); case XED_REG_R15W: return RegisterInfo(XED_REG_R15, 0, 2); + case XED_REG_R16W: return RegisterInfo(XED_REG_R16, 0, 2); + case XED_REG_R17W: return RegisterInfo(XED_REG_R17, 0, 2); + case XED_REG_R18W: return RegisterInfo(XED_REG_R18, 0, 2); + case XED_REG_R19W: return RegisterInfo(XED_REG_R19, 0, 2); + case XED_REG_R20W: return RegisterInfo(XED_REG_R20, 0, 2); + case XED_REG_R21W: return RegisterInfo(XED_REG_R21, 0, 2); + case XED_REG_R22W: return RegisterInfo(XED_REG_R22, 0, 2); + case XED_REG_R23W: return RegisterInfo(XED_REG_R23, 0, 2); + case XED_REG_R24W: return RegisterInfo(XED_REG_R24, 0, 2); + case XED_REG_R25W: return RegisterInfo(XED_REG_R25, 0, 2); + case XED_REG_R26W: return RegisterInfo(XED_REG_R26, 0, 2); + case XED_REG_R27W: return RegisterInfo(XED_REG_R27, 0, 2); + case XED_REG_R28W: return RegisterInfo(XED_REG_R28, 0, 2); + case XED_REG_R29W: return RegisterInfo(XED_REG_R29, 0, 2); + case XED_REG_R30W: return RegisterInfo(XED_REG_R30, 0, 2); + case XED_REG_R31W: return RegisterInfo(XED_REG_R31, 0, 2); + // 32-Bit case XED_REG_EIP: return RegisterInfo(XED_REG_RIP, 0, 4); @@ -3472,6 +3517,23 @@ class X64Architecture: public X86CommonArchitecture case XED_REG_R14D: return RegisterInfo(XED_REG_R14, 0, 4, true); case XED_REG_R15D: return RegisterInfo(XED_REG_R15, 0, 4, true); + case XED_REG_R16D: return RegisterInfo(XED_REG_R16, 0, 4, true); + case XED_REG_R17D: return RegisterInfo(XED_REG_R17, 0, 4, true); + case XED_REG_R18D: return RegisterInfo(XED_REG_R18, 0, 4, true); + case XED_REG_R19D: return RegisterInfo(XED_REG_R19, 0, 4, true); + case XED_REG_R20D: return RegisterInfo(XED_REG_R20, 0, 4, true); + case XED_REG_R21D: return RegisterInfo(XED_REG_R21, 0, 4, true); + case XED_REG_R22D: return RegisterInfo(XED_REG_R22, 0, 4, true); + case XED_REG_R23D: return RegisterInfo(XED_REG_R23, 0, 4, true); + case XED_REG_R24D: return RegisterInfo(XED_REG_R24, 0, 4, true); + case XED_REG_R25D: return RegisterInfo(XED_REG_R25, 0, 4, true); + case XED_REG_R26D: return RegisterInfo(XED_REG_R26, 0, 4, true); + case XED_REG_R27D: return RegisterInfo(XED_REG_R27, 0, 4, true); + case XED_REG_R28D: return RegisterInfo(XED_REG_R28, 0, 4, true); + case XED_REG_R29D: return RegisterInfo(XED_REG_R29, 0, 4, true); + case XED_REG_R30D: return RegisterInfo(XED_REG_R30, 0, 4, true); + case XED_REG_R31D: return RegisterInfo(XED_REG_R31, 0, 4, true); + // 48-Bit case XED_REG_GDTR: return RegisterInfo(XED_REG_GDTR, 0, 6); case XED_REG_LDTR: return RegisterInfo(XED_REG_LDTR, 0, 6); @@ -3519,6 +3581,24 @@ class X64Architecture: public X86CommonArchitecture case XED_REG_R14: return RegisterInfo(XED_REG_R14, 0, 8); case XED_REG_R15: return RegisterInfo(XED_REG_R15, 0, 8); + case XED_REG_R16: return RegisterInfo(XED_REG_R16, 0, 8); + case XED_REG_R17: return RegisterInfo(XED_REG_R17, 0, 8); + case XED_REG_R18: return RegisterInfo(XED_REG_R18, 0, 8); + case XED_REG_R19: return RegisterInfo(XED_REG_R19, 0, 8); + case XED_REG_R20: return RegisterInfo(XED_REG_R20, 0, 8); + case XED_REG_R21: return RegisterInfo(XED_REG_R21, 0, 8); + case XED_REG_R22: return RegisterInfo(XED_REG_R22, 0, 8); + case XED_REG_R23: return RegisterInfo(XED_REG_R23, 0, 8); + case XED_REG_R24: return RegisterInfo(XED_REG_R24, 0, 8); + case XED_REG_R25: return RegisterInfo(XED_REG_R25, 0, 8); + case XED_REG_R26: return RegisterInfo(XED_REG_R26, 0, 8); + case XED_REG_R27: return RegisterInfo(XED_REG_R27, 0, 8); + case XED_REG_R28: return RegisterInfo(XED_REG_R28, 0, 8); + case XED_REG_R29: return RegisterInfo(XED_REG_R29, 0, 8); + case XED_REG_R30: return RegisterInfo(XED_REG_R30, 0, 8); + case XED_REG_R31: return RegisterInfo(XED_REG_R31, 0, 8); + + case XED_REG_BNDCFGU: return RegisterInfo(XED_REG_BNDCFGU, 0, 8); case XED_REG_BNDSTATUS: return RegisterInfo(XED_REG_BNDSTATUS, 0, 8); diff --git a/arch/x86/il.cpp b/arch/x86/il.cpp index ba36190b2c..7211fc1506 100644 --- a/arch/x86/il.cpp +++ b/arch/x86/il.cpp @@ -198,28 +198,21 @@ static size_t ReadILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* co sizeToRead = xed_decoded_inst_operand_length_bits(xedd, (unsigned)operand_index) / 8; const unsigned int immediateSize = xed_decoded_inst_get_operand_width(xedd) / 8; const int64_t relbr = xed_decoded_inst_get_branch_displacement(xedd) + addr + xed_decoded_inst_get_length(xedd); + const int64_t absbr = xed_decoded_inst_get_branch_displacement(xedd); const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), (unsigned)operand_index)); const auto reg1 = xed_decoded_inst_get_reg(xedd, op_name); const size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8; - switch (op_name) - { // Register cases - case XED_OPERAND_REG0: - case XED_OPERAND_REG1: - case XED_OPERAND_REG2: - case XED_OPERAND_REG3: - case XED_OPERAND_REG4: - case XED_OPERAND_REG5: - case XED_OPERAND_REG6: - case XED_OPERAND_REG7: - case XED_OPERAND_REG8: - case XED_OPERAND_BASE0: - case XED_OPERAND_BASE1: + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) + { if ((reg1 == XED_REG_RIP) || (reg1 == XED_REG_EIP) || (reg1 == XED_REG_IP)) return il.Operand(instruction_index, il.ConstPointer(sizeToRead, addr)); return il.Operand(instruction_index, il.Register(sizeToRead, (uint32_t)reg1)); + } + switch (op_name) + { // Immediates: case XED_OPERAND_IMM0: if (xed_decoded_inst_get_immediate_is_signed(xedd)) @@ -235,6 +228,8 @@ static size_t ReadILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* co case XED_OPERAND_PTR: case XED_OPERAND_RELBR: return il.Operand(instruction_index, il.ConstPointer(addrSize, relbr)); + case XED_OPERAND_ABSBR: + return il.Operand(instruction_index, il.ConstPointer(addrSize, absbr)); // Memory Acesses case XED_OPERAND_AGEN: @@ -256,25 +251,16 @@ static size_t ReadFloatILOperand(LowLevelILFunction& il, const xed_decoded_inst_ const unsigned int operandSize = xed_decoded_inst_operand_length_bits(xedd, (unsigned)operand_index) / 8; const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), (unsigned)operand_index)); - switch (op_name) - { // Register cases - case XED_OPERAND_REG0: - case XED_OPERAND_REG1: - case XED_OPERAND_REG2: - case XED_OPERAND_REG3: - case XED_OPERAND_REG4: - case XED_OPERAND_REG5: - case XED_OPERAND_REG6: - case XED_OPERAND_REG7: - case XED_OPERAND_REG8: - case XED_OPERAND_BASE0: - case XED_OPERAND_BASE1: + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) return il.Operand(instruction_index, il.Register(operandSize, (uint32_t)xed_decoded_inst_get_reg(xedd, op_name))); + switch (op_name) + { // Immediates case XED_OPERAND_IMM0: case XED_OPERAND_PTR: + case XED_OPERAND_ABSBR: case XED_OPERAND_RELBR: if (xed_decoded_inst_get_immediate_is_signed(xedd)) return il.Operand(instruction_index, il.FloatConvert(opLen, il.FloatConstRaw(operandSize, xed_decoded_inst_get_signed_immediate(xedd)))); @@ -312,22 +298,12 @@ static size_t WriteILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* c const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), operand_index)); - switch (op_name) - { // Register cases - case XED_OPERAND_REG0: - case XED_OPERAND_REG1: - case XED_OPERAND_REG2: - case XED_OPERAND_REG3: - case XED_OPERAND_REG4: - case XED_OPERAND_REG5: - case XED_OPERAND_REG6: - case XED_OPERAND_REG7: - case XED_OPERAND_REG8: - case XED_OPERAND_BASE0: - case XED_OPERAND_BASE1: + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) return il.Operand(instruction_index, il.SetRegister(sizeToWrite, xed_decoded_inst_get_reg(xedd, op_name), value)); + switch (op_name) + { // Memory Accesses case XED_OPERAND_AGEN: case XED_OPERAND_MEM0: @@ -446,13 +422,38 @@ static void Repeat( static void CMovFlagCond(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, BNLowLevelILFlagCondition flag) { - // keep the true branch but let the false branch goto doneLabel directly - LowLevelILLabel trueLabel, doneLabel; + bool isCondFault = false; + bool isNdd = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD); + + switch (xed_decoded_inst_get_iclass(xedd)) + { + case XED_ICLASS_CFCMOVB: + case XED_ICLASS_CFCMOVBE: + case XED_ICLASS_CFCMOVL: + case XED_ICLASS_CFCMOVLE: + case XED_ICLASS_CFCMOVNB: + case XED_ICLASS_CFCMOVNBE: + case XED_ICLASS_CFCMOVNL: + case XED_ICLASS_CFCMOVNLE: + case XED_ICLASS_CFCMOVNO: + case XED_ICLASS_CFCMOVNP: + case XED_ICLASS_CFCMOVNS: + case XED_ICLASS_CFCMOVNZ: + case XED_ICLASS_CFCMOVO: + case XED_ICLASS_CFCMOVP: + case XED_ICLASS_CFCMOVS: + case XED_ICLASS_CFCMOVZ: + isCondFault = true; + default: + break; + } + + LowLevelILLabel trueLabel, falseLabel, doneLabel; il.AddInstruction( il.If( il.FlagCondition(flag), - trueLabel, doneLabel)); + trueLabel, falseLabel)); il.MarkLabel(trueLabel); @@ -461,14 +462,68 @@ static void CMovFlagCond(const int64_t addr, const xed_decoded_inst_t* xedd, Low ReadILOperand(il, xedd, addr, 1, 1))); il.AddInstruction(il.Goto(doneLabel)); + + il.MarkLabel(falseLabel); + + if (isNdd) + { + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + ReadILOperand(il, xedd, addr, 2, 2))); + } + else if (isCondFault) + { + const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), 0)); + + // Register cases + if (xed_operand_is_register(op_name)) + { + size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8; + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + il.Const(addrSize, 0))); + } + else + { + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + ReadILOperand(il, xedd, addr, 1, 1))); + } + } + il.MarkLabel(doneLabel); } static void CMovFlagGroup(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t flag) { - // keep the true branch but let the false branch goto doneLabel directly - LowLevelILLabel trueLabel, doneLabel; + bool isCondFault = false; + bool isNdd = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD); + + switch (xed_decoded_inst_get_iclass(xedd)) + { + case XED_ICLASS_CFCMOVB: + case XED_ICLASS_CFCMOVBE: + case XED_ICLASS_CFCMOVL: + case XED_ICLASS_CFCMOVLE: + case XED_ICLASS_CFCMOVNB: + case XED_ICLASS_CFCMOVNBE: + case XED_ICLASS_CFCMOVNL: + case XED_ICLASS_CFCMOVNLE: + case XED_ICLASS_CFCMOVNO: + case XED_ICLASS_CFCMOVNP: + case XED_ICLASS_CFCMOVNS: + case XED_ICLASS_CFCMOVNZ: + case XED_ICLASS_CFCMOVO: + case XED_ICLASS_CFCMOVP: + case XED_ICLASS_CFCMOVS: + case XED_ICLASS_CFCMOVZ: + isCondFault = true; + default: + break; + } + + LowLevelILLabel trueLabel, falseLabel, doneLabel; il.AddInstruction( il.If( @@ -484,10 +539,122 @@ static void CMovFlagGroup(const int64_t addr, const xed_decoded_inst_t* xedd, Lo ReadILOperand(il, xedd, addr, 1, 1))); il.AddInstruction(il.Goto(doneLabel)); + + il.MarkLabel(falseLabel); + + if (isNdd) + { + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + ReadILOperand(il, xedd, addr, 2, 2))); + } + else if (isCondFault) + { + const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), 0)); + + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) + { + size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8; + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + il.Const(addrSize, 0))); + } + else + { + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + ReadILOperand(il, xedd, addr, 1, 1))); + } + } + + il.MarkLabel(doneLabel); +} + +static void AssignEvexDfv(const xed_decoded_inst_t* xedd, LowLevelILFunction& il) +{ + xed_flag_dfv_t defaultFlagValues; + if (!xed_flag_dfv_get_default_flags_values( + xed_decoded_inst_get_dfv_reg(xedd), &defaultFlagValues)) + { + // TODO: better error handling + il.AddInstruction(il.Undefined()); + return; + } + + il.AddInstruction( + il.SetFlag(IL_FLAG_O, + il.Const(1, defaultFlagValues.s.of))); + il.AddInstruction( + il.SetFlag(IL_FLAG_S, + il.Const(1, defaultFlagValues.s.sf))); + il.AddInstruction( + il.SetFlag(IL_FLAG_Z, + il.Const(1, defaultFlagValues.s.zf))); + il.AddInstruction( + il.SetFlag(IL_FLAG_C, + il.Const(1, defaultFlagValues.s.cf))); + il.AddInstruction( + il.SetFlag(IL_FLAG_P, + il.Const(1, defaultFlagValues.s.cf))); + il.AddInstruction( + il.SetFlag(IL_FLAG_A, + il.Const(1, 0))); +} + + +static void ConditionalCmp(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t size, ExprId cond) +{ + LowLevelILLabel trueLabel, falseLabel, doneLabel; + + il.AddInstruction( + il.If( + cond, + trueLabel, falseLabel + ) + ); + + il.MarkLabel(trueLabel); + + il.AddInstruction( + il.Sub(size, + ReadILOperand(il, xedd, addr, 0, 0), + ReadILOperand(il, xedd, addr, 1, 1), + IL_FLAGWRITE_ALL)); + il.AddInstruction(il.Goto(doneLabel)); + + il.MarkLabel(falseLabel); + AssignEvexDfv(xedd, il); + il.MarkLabel(doneLabel); } +static void ConditionalTest(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t size, ExprId cond) +{ + LowLevelILLabel trueLabel, falseLabel, doneLabel; + + il.AddInstruction( + il.If( + cond, + trueLabel, falseLabel + ) + ); + + il.MarkLabel(trueLabel); + + il.AddInstruction( + il.And(size, + ReadILOperand(il, xedd, addr, 0, 0), + ReadILOperand(il, xedd, addr, 1, 1), + IL_FLAGWRITE_ALL)); + il.AddInstruction(il.Goto(doneLabel)); + + il.MarkLabel(falseLabel); + AssignEvexDfv(xedd, il); + + il.MarkLabel(doneLabel); +} + bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLevelILFunction& il, const xed_decoded_inst_t* const xedd) { LowLevelILLabel trueLabel, falseLabel, doneLabel, dirFlagSet, dirFlagClear, dirFlagDone, startLabel; @@ -525,6 +692,10 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev const uint64_t immediateOne = xed_decoded_inst_get_unsigned_immediate(xedd); const int64_t branchDestination = xed_decoded_inst_get_branch_displacement(xedd) + addr + instLen; + const bool newDataDestination = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD); + const bool zeroUpper = xed_decoded_inst_is_apx_zu(xedd); + const bool noFlags = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NF); + auto LiftAsIntrinsic = [& il, xi, xedd, addr, xedd_iForm] () mutable { typedef struct @@ -544,25 +715,13 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev xed_operand_enum_t op_name = xed_operand_name(op); if (xed_operand_written(op)) { - switch(op_name) - { - case XED_OPERAND_REG0: - case XED_OPERAND_REG1: - case XED_OPERAND_REG2: - case XED_OPERAND_REG3: - case XED_OPERAND_REG4: - case XED_OPERAND_REG5: - case XED_OPERAND_REG6: - case XED_OPERAND_REG7: - case XED_OPERAND_REG8: - case XED_OPERAND_BASE0: - case XED_OPERAND_BASE1: + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) { xed_reg_enum_t r = xed_decoded_inst_get_reg(xedd, op_name); outputs.push_back(RegisterOrFlag::Register(r)); - break; } - default: + else + { // The intrinsic system can only accept registers or flags as outputs, // since it might be strange to write to an arbitrary ExprId. // In order to handle intrinsics that write to memory, we create a temp IL register and @@ -577,24 +736,11 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev memoryOperandWrites.push_back({i, operandWidth}); outputs.push_back(RegisterOrFlag::Register(LLIL_TEMP(numTempRegUsed))); numTempRegUsed++; - break; } } if (xed_operand_read(op)) { - switch(op_name) - { - case XED_OPERAND_REG0: - case XED_OPERAND_REG1: - case XED_OPERAND_REG2: - case XED_OPERAND_REG3: - case XED_OPERAND_REG4: - case XED_OPERAND_REG5: - case XED_OPERAND_REG6: - case XED_OPERAND_REG7: - case XED_OPERAND_REG8: - case XED_OPERAND_BASE0: - case XED_OPERAND_BASE1: + if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name)) { // XED includes some things that are not actual registers in // xed_reg_enum_t. We'll just omit those special cases here. @@ -612,9 +758,6 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; } } - default: - break; - } parameters.push_back(ReadILOperand(il, xedd, addr, i, i)); } @@ -635,51 +778,122 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev { case XED_ICLASS_ADC_LOCK: // TODO: Add Lock construct case XED_ICLASS_ADC: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.AddCarry(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); + il.AddCarry(opTwoLen, left, right, + il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_ADCX: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.AddCarry(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_C), IL_FLAG_C))); + il.AddCarry(opOneLen, left, right, + il.Flag(IL_FLAG_C), IL_FLAG_C))); break; + } case XED_ICLASS_ADOX: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.AddCarry(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_O), IL_FLAG_O))); + il.AddCarry(opOneLen, left, right, + il.Flag(IL_FLAG_O), IL_FLAG_O))); break; + } case XED_ICLASS_ADD_LOCK: // TODO: Add Lock construct case XED_ICLASS_ADD: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Add(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.Add(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_AND_LOCK: // TODO: Add Lock construct case XED_ICLASS_AND: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.And(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.And(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } + case XED_ICLASS_PAND: il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, @@ -1267,78 +1481,95 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; case XED_ICLASS_CMOVO: + case XED_ICLASS_CFCMOVO: CMovFlagCond(addr, xedd, il, LLFC_O); break; case XED_ICLASS_CMOVNO: + case XED_ICLASS_CFCMOVNO: CMovFlagCond(addr, xedd, il, LLFC_NO); break; case XED_ICLASS_CMOVB: case XED_ICLASS_FCMOVB: + case XED_ICLASS_CFCMOVB: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_LT); break; case XED_ICLASS_CMOVNB: case XED_ICLASS_FCMOVNB: + case XED_ICLASS_CFCMOVNB: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_GE); break; case XED_ICLASS_CMOVZ: case XED_ICLASS_FCMOVE: + case XED_ICLASS_CFCMOVZ: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_E); break; case XED_ICLASS_CMOVNZ: case XED_ICLASS_FCMOVNE: + case XED_ICLASS_CFCMOVNZ: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_NE); break; case XED_ICLASS_CMOVBE: case XED_ICLASS_FCMOVBE: + case XED_ICLASS_CFCMOVBE: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_LE); break; case XED_ICLASS_CMOVNBE: case XED_ICLASS_FCMOVNBE: + case XED_ICLASS_CFCMOVNBE: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_GT); break; case XED_ICLASS_CMOVS: + case XED_ICLASS_CFCMOVS: CMovFlagCond(addr, xedd, il, LLFC_NEG); break; case XED_ICLASS_CMOVNS: + case XED_ICLASS_CFCMOVNS: CMovFlagCond(addr, xedd, il, LLFC_POS); break; case XED_ICLASS_CMOVP: case XED_ICLASS_FCMOVU: + case XED_ICLASS_CFCMOVP: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_PE); break; case XED_ICLASS_CMOVNP: case XED_ICLASS_FCMOVNU: + case XED_ICLASS_CFCMOVNP: CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_PO); break; case XED_ICLASS_CMOVL: + case XED_ICLASS_CFCMOVL: CMovFlagCond(addr, xedd, il, LLFC_SLT); break; case XED_ICLASS_CMOVNL: + case XED_ICLASS_CFCMOVNL: CMovFlagCond(addr, xedd, il, LLFC_SGE); break; case XED_ICLASS_CMOVLE: + case XED_ICLASS_CFCMOVLE: CMovFlagCond(addr, xedd, il, LLFC_SLE); break; case XED_ICLASS_CMOVNLE: + case XED_ICLASS_CFCMOVNLE: CMovFlagCond(addr, xedd, il, LLFC_SGT); break; case XED_ICLASS_CMP: + case XED_ICLASS_CCMPT: il.AddInstruction( il.Sub(opOneLen, ReadILOperand(il, xedd, addr, 0, 0), @@ -1346,6 +1577,66 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev IL_FLAGWRITE_ALL)); break; + case XED_ICLASS_CCMPO: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_O)); + break; + + case XED_ICLASS_CCMPNO: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NO)); + break; + + case XED_ICLASS_CCMPB: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LT)); + break; + + case XED_ICLASS_CCMPNB: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GE)); + break; + + case XED_ICLASS_CCMPZ: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_E)); + break; + + case XED_ICLASS_CCMPNZ: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_NE)); + break; + + case XED_ICLASS_CCMPBE: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LE)); + break; + + case XED_ICLASS_CCMPNBE: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GT)); + break; + + case XED_ICLASS_CCMPS: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NEG)); + break; + + case XED_ICLASS_CCMPNS: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_POS)); + break; + + case XED_ICLASS_CCMPL: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT)); + break; + + case XED_ICLASS_CCMPNL: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT)); + break; + + case XED_ICLASS_CCMPLE: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLE)); + break; + + case XED_ICLASS_CCMPNLE: + ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SGT)); + break; + + case XED_ICLASS_CCMPF: + AssignEvexDfv(xedd, il); + break; + case XED_ICLASS_REPE_CMPSQ: case XED_ICLASS_REPNE_CMPSQ: case XED_ICLASS_CMPSQ: @@ -1470,17 +1761,32 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev case XED_ICLASS_DEC_LOCK: // TODO: Handle lock prefix case XED_ICLASS_DEC: + { + ExprId src; + if (!newDataDestination) + { + // nothing special + src = ReadILOperand(il, xedd, addr, 0, 0); + } + else + { + // new data destination + src = ReadILOperand(il, xedd, addr, 1, 1); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, il.Sub(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), + src, il.Const(opOneLen, 1), - IL_FLAGWRITE_NOCARRY) + noFlags ? 0 : IL_FLAGWRITE_NOCARRY) ) ); break; + } case XED_ICLASS_DIV: + // TODO: flags set and handle noFlags? il.AddInstruction( il.SetRegister(opOneLen, LLIL_TEMP(2), @@ -1628,6 +1934,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev } case XED_ICLASS_IDIV: + // TODO: flags set and handle noFlags? switch (opOneLen) { case 1: @@ -1765,7 +2072,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecSigned(1, il.Register(1, XED_REG_AL), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 2: il.AddInstruction( @@ -1775,7 +2082,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecSigned(2, il.Register(2, XED_REG_AX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 4: il.AddInstruction( @@ -1785,7 +2092,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecSigned(4, il.Register(4, XED_REG_EAX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 8: il.AddInstruction( @@ -1795,7 +2102,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecSigned(8, il.Register(8, XED_REG_RAX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; default: il.AddInstruction(il.Undefined()); @@ -1803,40 +2110,73 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev } break; - case XED_IFORM_IMUL_GPRv_GPRv: - case XED_IFORM_IMUL_GPRv_MEMv: + case XED_IFORM_IMUL_GPRv_GPRv: + case XED_IFORM_IMUL_GPRv_MEMv: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Mult(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_CO))); + il.Mult(opOneLen, left, right, + IL_FLAGWRITE_CO))); break; + } - case XED_IFORM_IMUL_GPRv_GPRv_IMMb: - case XED_IFORM_IMUL_GPRv_GPRv_IMMz: - case XED_IFORM_IMUL_GPRv_MEMv_IMMb: - case XED_IFORM_IMUL_GPRv_MEMv_IMMz: + case XED_IFORM_IMUL_GPRv_GPRv_IMMb: + case XED_IFORM_IMUL_GPRv_GPRv_IMMz: + case XED_IFORM_IMUL_GPRv_MEMv_IMMb: + case XED_IFORM_IMUL_GPRv_MEMv_IMMz: default: - il.AddInstruction( - WriteILOperand(il, xedd, addr, 0, 0, - il.Mult(opOneLen, - ReadILOperand(il, xedd, addr, 1, 1), - ReadILOperand(il, xedd, addr, 2, 2), - IL_FLAGWRITE_CO))); + { + ExprId value = il.Mult(opOneLen, + ReadILOperand(il, xedd, addr, 1, 1), + ReadILOperand(il, xedd, addr, 2, 2), + IL_FLAGWRITE_CO); + + if (zeroUpper && (opOneLen == 1 || opOneLen == 2)) + value = il.ZeroExtend(8, value); + + il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, value)); } - break; + } + break; case XED_ICLASS_INC_LOCK: // TODO: Handle lock prefix case XED_ICLASS_INC: + { + ExprId src; + if (!newDataDestination) + { + // nothing special + src = ReadILOperand(il, xedd, addr, 0, 0); + } + else + { + // new data destination + src = ReadILOperand(il, xedd, addr, 1, 1); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Add(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - il.Const(opOneLen, 1), - IL_FLAGWRITE_NOCARRY))); + il.Add(opTwoLen, + src, + il.Const(opTwoLen, 1), + noFlags ? 0 : IL_FLAGWRITE_NOCARRY))); break; + } case XED_ICLASS_INT: switch (immediateOne) @@ -1858,6 +2198,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; case XED_ICLASS_JMP: + case XED_ICLASS_JMPABS: if (opOne_name == XED_OPERAND_RELBR) { BNLowLevelILLabel* label = il.GetLabelForAddress(arch, branchDestination); @@ -2606,7 +2947,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecUnsigned(1, il.Register(1, XED_REG_AL), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 2: il.AddInstruction( @@ -2616,7 +2957,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecUnsigned(2, il.Register(2, XED_REG_AX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 4: il.AddInstruction( @@ -2626,7 +2967,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecUnsigned(4, il.Register(4, XED_REG_EAX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; case 8: il.AddInstruction( @@ -2636,7 +2977,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev il.MultDoublePrecUnsigned(8, il.Register(8, XED_REG_RAX), ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_CO))); + noFlags ? 0 : IL_FLAGWRITE_CO))); break; default: il.AddInstruction(il.Undefined()); @@ -2646,12 +2987,25 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev case XED_ICLASS_NEG_LOCK: // TODO: Handle lock prefix case XED_ICLASS_NEG: - il.AddInstruction( - WriteILOperand(il, xedd, addr, 0, 0, - il.Neg(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - IL_FLAGWRITE_ALL))); + { + ExprId src; + if (!newDataDestination) + { + // nothing special + src = ReadILOperand(il, xedd, addr, 0, 0); + } + else + { + // new data destination + src = ReadILOperand(il, xedd, addr, 1, 1); + } + + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + il.Neg(opOneLen, src, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_NOP: case XED_ICLASS_NOP2: @@ -2691,21 +3045,46 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev case XED_ICLASS_NOT_LOCK: // TODO: Handle lock prefix case XED_ICLASS_NOT: + ExprId src; + if (!newDataDestination) + { + // nothing special + src = ReadILOperand(il, xedd, addr, 0, 0); + } + else + { + // new data destination + src = ReadILOperand(il, xedd, addr, 1, 1); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Not(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0)))); + il.Not(opOneLen, src))); break; case XED_ICLASS_OR_LOCK: // TODO: Handle lock prefix case XED_ICLASS_OR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Or(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.Or(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_POR: il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, @@ -2728,7 +3107,18 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev 0))); // VPOR doesn't modify flags break; + case XED_ICLASS_POP2: + case XED_ICLASS_POP2P: + il.AddInstruction( + WriteILOperand(il, xedd, addr, 0, 0, + il.Pop(8))); + il.AddInstruction( + WriteILOperand(il, xedd, addr, 1, 1, + il.Pop(8))); + break; + case XED_ICLASS_POP: + case XED_ICLASS_POPP: il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, il.Pop(opOneLen))); @@ -2859,7 +3249,14 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev ); break; + case XED_ICLASS_PUSH2: + case XED_ICLASS_PUSH2P: + il.AddInstruction(il.Push(8, ReadILOperand(il, xedd, addr, 0, 0))); + il.AddInstruction(il.Push(8, ReadILOperand(il, xedd, addr, 1, 1))); + break; + case XED_ICLASS_PUSH: + case XED_ICLASS_PUSHP: { // Whe the stack adjustment is different from the operand one size, zero-extend it. Note, a "push r16" in either // x86 or x64 pushes the 2-byte register onto the stack, and there is no need to extend. See @@ -2882,22 +3279,49 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev } case XED_ICLASS_RCL: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.RotateLeftCarry(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); + il.RotateLeftCarry(opOneLen, left, right, + il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); break; - + } case XED_ICLASS_RCR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.RotateRightCarry(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); + il.RotateRightCarry(opOneLen, left, right, + il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_RET_NEAR: if ((opOne_name != XED_OPERAND_IMM0) || (immediateOne == 0)) @@ -2917,23 +3341,49 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; case XED_ICLASS_ROL: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.RotateLeft(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.RotateLeft(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; - + } case XED_ICLASS_ROR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.RotateRight(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.RotateRight(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; - + } // there is no ROLX instruciton case XED_ICLASS_RORX: il.AddInstruction( @@ -2945,13 +3395,27 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; case XED_ICLASS_SAR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.ArithShiftRight(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.ArithShiftRight(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_SARX: il.AddInstruction( @@ -2972,13 +3436,27 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev case XED_ICLASS_SBB_LOCK: // TODO: Handle lock prefix case XED_ICLASS_SBB: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.SubBorrow(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); + il.SubBorrow(opOneLen, left, right, + il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_REPE_SCASB: case XED_ICLASS_REPE_SCASD: @@ -3041,88 +3519,142 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev } case XED_ICLASS_SETO: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Flag(IL_FLAG_O))); - break; - case XED_ICLASS_SETNO: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Not(0, il.Flag(IL_FLAG_O)))); - break; - case XED_ICLASS_SETB: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Flag(IL_FLAG_C))); - break; - case XED_ICLASS_SETNB: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_GE))); - break; - case XED_ICLASS_SETZ: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_E))); - break; - case XED_ICLASS_SETNZ: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_NE))); - break; - case XED_ICLASS_SETBE: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_LE))); - break; - case XED_ICLASS_SETNBE: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_GT))); - break; - case XED_ICLASS_SETS: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_NEG))); - break; - case XED_ICLASS_SETNS: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_POS))); - break; - case XED_ICLASS_SETP: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_PE))); - break; - case XED_ICLASS_SETNP: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_PO))); - break; - case XED_ICLASS_SETL: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SLT))); - break; - case XED_ICLASS_SETNL: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SGE))); - break; - case XED_ICLASS_SETLE: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SLE))); - break; - case XED_ICLASS_SETNLE: - il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SGT))); + { + ExprId flag; + switch (xedd_iClass) + { + case XED_ICLASS_SETO: + flag = il.Flag(IL_FLAG_O); + break; + case XED_ICLASS_SETNO: + flag = il.Not(1, il.Flag(IL_FLAG_O)); + break; + case XED_ICLASS_SETB: + flag = il.Flag(IL_FLAG_C); + break; + + case XED_ICLASS_SETNB: + flag = il.FlagGroup(IL_FLAG_GROUP_GE); + break; + + case XED_ICLASS_SETZ: + flag = il.FlagGroup(IL_FLAG_GROUP_E); + break; + + case XED_ICLASS_SETNZ: + flag = il.FlagGroup(IL_FLAG_GROUP_NE); + break; + + case XED_ICLASS_SETBE: + flag = il.FlagGroup(IL_FLAG_GROUP_LE); + break; + + case XED_ICLASS_SETNBE: + flag = il.FlagGroup(IL_FLAG_GROUP_GT); + break; + + case XED_ICLASS_SETS: + flag = il.FlagCondition(LLFC_NEG); + break; + + case XED_ICLASS_SETNS: + flag = il.FlagCondition(LLFC_POS); + break; + + case XED_ICLASS_SETP: + flag = il.FlagGroup(IL_FLAG_GROUP_PE); + break; + + case XED_ICLASS_SETNP: + flag = il.FlagGroup(IL_FLAG_GROUP_PO); + break; + + case XED_ICLASS_SETL: + flag = il.FlagCondition(LLFC_SLT); + break; + + case XED_ICLASS_SETNL: + flag = il.FlagCondition(LLFC_SGE); + break; + + case XED_ICLASS_SETLE: + flag = il.FlagCondition(LLFC_SLE); + break; + + case XED_ICLASS_SETNLE: + flag = il.FlagCondition(LLFC_SGT); + break; + } + + if (zeroUpper && xed_operand_is_register(opOne_name)) + flag = il.ZeroExtend(8, flag); + + il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, flag)); break; + } case XED_ICLASS_SHL: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.ShiftLeft(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.ShiftLeft(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } // This is imprecise since it does NOT move the last shifted bit into CF // the same problem also happens on SHL, SAR case XED_ICLASS_SHR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.LogicalShiftRight(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.LogicalShiftRight(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_SHLX: il.AddInstruction( @@ -3150,22 +3682,36 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev // Shift left double: operand[0] = operand[0]:operand[1] << operand[3] // this since we can't easily operation on a combined register we do it like this // operand[0] = (operand[0] << operand[3]) | (operand[1] >> (63|32 - operand[3])) - // One final cevate operand[3] must be masked with 63|32 + // One final caveat operand[3] must be masked with 63|32 + ExprId left, right, count; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + + count = il.And(opSize, + il.Const(1, mask), + ReadILOperand(il, xedd, addr, 2, 2)); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + + count = il.And(opSize, + il.Const(1, mask), + ReadILOperand(il, xedd, addr, 3, 3)); + } + il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Or(opSize, - il.ShiftLeft(opSize, - ReadILOperand(il, xedd, addr, 0, 0), - il.And(opSize, - il.Const(1, mask), - ReadILOperand(il, xedd, addr, 2, 2)), - IL_FLAGWRITE_ALL), + il.ShiftLeft(opSize, left, count, + noFlags ? 0 : IL_FLAGWRITE_ALL), il.LogicalShiftRight(opSize, - ReadILOperand(il, xedd, addr, 1, 1), - il.Sub(opSize, - il.And(opSize, - il.Const(1, mask), - ReadILOperand(il, xedd, addr, 2, 2)), - il.Const(1, opSize * 8)))))); + right, + il.Sub(opSize, count, il.Const(1, opSize * 8)))))); break; } case XED_ICLASS_SHRD: @@ -3176,22 +3722,38 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev // Shift right double: operand[0] = operand[0]:operand[1] >> operand[3] // this since we can't easily operation on a combined register we do it like this // operand[0] = (operand[0] >> operand[3]) | (operand[1] << (63|31 - operand[3])) - // One final cevate operand[3] must be masked with 63|31 + // One final caveat operand[3] must be masked with 63|31 + ExprId left, right, count; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + + count = il.And(opSize, + il.Const(1, mask), + ReadILOperand(il, xedd, addr, 2, 2)); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + + count = il.And(opSize, + il.Const(1, mask), + ReadILOperand(il, xedd, addr, 3, 3)); + } + il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Or(opSize, il.LogicalShiftRight(opSize, - ReadILOperand(il, xedd, addr, 0, 0), - il.And(opSize, - il.Const(1, mask), - ReadILOperand(il, xedd, addr, 2, 2)), - IL_FLAGWRITE_ALL), + left, + count, + noFlags ? 0 : IL_FLAGWRITE_ALL), il.ShiftLeft(opSize, - ReadILOperand(il, xedd, addr, 1, 1), - il.Sub(opSize, - il.Const(1, opSize * 8), - il.And(opSize, - il.Const(1, mask), - ReadILOperand(il, xedd, addr, 2, 2))))))); + right, + il.Sub(opSize, il.Const(1, opSize * 8), count))))); break; } case XED_ICLASS_STOSB: @@ -3313,15 +3875,30 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev case XED_ICLASS_SUB_LOCK: // TODO: Handle lock prefix case XED_ICLASS_SUB: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Sub(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.Sub(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } case XED_ICLASS_TEST: + case XED_ICLASS_CTESTT: il.AddInstruction( il.And(opOneLen, ReadILOperand(il, xedd, addr, 0, 0), @@ -3367,6 +3944,66 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev ); break; + case XED_ICLASS_CTESTO: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_O)); + break; + + case XED_ICLASS_CTESTNO: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NO)); + break; + + case XED_ICLASS_CTESTB: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LT)); + break; + + case XED_ICLASS_CTESTNB: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GE)); + break; + + case XED_ICLASS_CTESTZ: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_E)); + break; + + case XED_ICLASS_CTESTNZ: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_NE)); + break; + + case XED_ICLASS_CTESTBE: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LE)); + break; + + case XED_ICLASS_CTESTNBE: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GT)); + break; + + case XED_ICLASS_CTESTS: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NEG)); + break; + + case XED_ICLASS_CTESTNS: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_POS)); + break; + + case XED_ICLASS_CTESTL: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT)); + break; + + case XED_ICLASS_CTESTNL: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT)); + break; + + case XED_ICLASS_CTESTLE: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLE)); + break; + + case XED_ICLASS_CTESTNLE: + ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SGT)); + break; + + case XED_ICLASS_CTESTF: + AssignEvexDfv(xedd, il); + break; + case XED_ICLASS_XCHG: il.AddInstruction(il.SetRegister(opOneLen, LLIL_TEMP(0), ReadILOperand(il, xedd, addr, 0, 0))); il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, ReadILOperand(il, xedd, addr, 1, 1))); @@ -3500,13 +4137,28 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev break; case XED_ICLASS_XOR_LOCK: // TODO: Handle lock prefix case XED_ICLASS_XOR: + { + ExprId left, right; + if (!newDataDestination) + { + // nothing special + left = ReadILOperand(il, xedd, addr, 0, 0); + right = ReadILOperand(il, xedd, addr, 1, 1); + } + else + { + // new data destination + left = ReadILOperand(il, xedd, addr, 1, 1); + right = ReadILOperand(il, xedd, addr, 2, 2); + } + il.AddInstruction( WriteILOperand(il, xedd, addr, 0, 0, - il.Xor(opOneLen, - ReadILOperand(il, xedd, addr, 0, 0), - ReadILOperand(il, xedd, addr, 1, 1), - IL_FLAGWRITE_ALL))); + il.Xor(opOneLen, left, right, + noFlags ? 0 : IL_FLAGWRITE_ALL))); break; + } + case XED_ICLASS_VPXOR: if (xed_classify_avx512(xedd)) { diff --git a/arch/x86/yasm b/arch/x86/yasm index ac85068844..bb619b659e 160000 --- a/arch/x86/yasm +++ b/arch/x86/yasm @@ -1 +1 @@ -Subproject commit ac85068844e29535767c22638af4cc974083226b +Subproject commit bb619b659ed082744ffbe65b0b31367d34e5bd4f diff --git a/vendor/fmt b/vendor/fmt index 40626af88b..0c9fce2ffe 160000 --- a/vendor/fmt +++ b/vendor/fmt @@ -1 +1 @@ -Subproject commit 40626af88bd7df9a5fb80be7b25ac85b122d6c21 +Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592