From 393e7935af660c07e2139f99468f0f32125fae99 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 26 Aug 2025 08:33:50 -0400 Subject: [PATCH 1/3] GP-5906: Added x86 SSE4a instructions --- Ghidra/Processors/x86/data/languages/ia.sinc | 50 ++++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 602f675cbd..d216d902dc 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -4894,13 +4894,13 @@ define pcodeop verw; # of this instruction is always 64-bits and is always in memory". Is it an error that the "Instruction" entry in the # box giving the definition does not specify m64? :VMPTRST m64 is vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=7 ) ... & m64 { vmptrst(m64); } -:VMREAD rm32, Reg32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0x78; rm32 & check_rm32_dest ... & Reg32 ... { rm32 = vmread(Reg32); build check_rm32_dest; } +:VMREAD rm32, Reg32 is $(PRE_NO) & vexMode=0 & opsize=1 & byte=0x0f; byte=0x78; rm32 & check_rm32_dest ... & Reg32 ... { rm32 = vmread(Reg32); build check_rm32_dest; } @ifdef IA64 -:VMREAD rm64, Reg64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x78; rm64 & Reg64 ... { rm64 = vmread(Reg64); } +:VMREAD rm64, Reg64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x78; rm64 & Reg64 ... { rm64 = vmread(Reg64); } @endif -:VMWRITE Reg32, rm32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0x79; rm32 & Reg32 ... & check_Reg32_dest ... { vmwrite(rm32,Reg32); build check_Reg32_dest; } +:VMWRITE Reg32, rm32 is $(PRE_NO) & vexMode=0 & opsize=1 & byte=0x0f; byte=0x79; rm32 & Reg32 ... & check_Reg32_dest ... { vmwrite(rm32,Reg32); build check_Reg32_dest; } @ifdef IA64 -:VMWRITE Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x79; rm64 & Reg64 ... { vmwrite(rm64,Reg64); } +:VMWRITE Reg64, rm64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x79; rm64 & Reg64 ... { vmwrite(rm64,Reg64); } @endif :VMXOFF is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc4 { vmxoff(); } # NB: this opcode is incorrect in the 2005 edition of the Intel manual. Opcode below is taken from the 2008 version. @@ -10457,4 +10457,46 @@ define pcodeop PackedSwapDWords; define pcodeop MaskedMoveQWord; :MASKMOVQ mmxreg1, mmxreg2 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF7; mmxmod = 3 & mmxreg1 & mmxreg2 { mmxreg1 = MaskedMoveQWord(mmxreg1, mmxreg2); } + +#### +#### SSE4a instructions +#### + +bitLen: val is imm8 [ val=imm8 & 0x3f; ] { export *[const]:1 val; } +lsbOffset: val is imm8 [ val=imm8 & 0x3f; ] { export *[const]:1 val; } +:EXTRQ XmmReg2, bitLen, lsbOffset is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x78; reg_opcode=0 & XmmReg2; bitLen; lsbOffset { + local mask:16 = ((1 << bitLen) - 1) << lsbOffset; + local val:16 = (XmmReg2 & mask) >> lsbOffset; + XmmReg2 = val; +} + +:EXTRQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x79; XmmReg1 & XmmReg2 { + local len = XmmReg2[0,6]; + local offs = XmmReg2[6,6]; + local mask = ((1 << len) - 1) << offs; + local val = (XmmReg1 & mask) >> offs; + XmmReg1 = val; +} + +:INSERTQ XmmReg1, XmmReg2, bitLen, lsbOffset is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x78; XmmReg1 & XmmReg2; bitLen; lsbOffset { + local mask:16 = ((1 << bitLen) - 1) << lsbOffset; + local val:16 = (zext(XmmReg2[0,64]) & ((1 << bitLen) - 1)); + XmmReg1 = (XmmReg1 & ~zext(mask)) | (zext(val) << lsbOffset); +} + +:INSERTQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x79; XmmReg1 & XmmReg2 { + local len = XmmReg2[64,6]; + local offs = XmmReg2[72,6]; + local mask:16 = ((1 << len) - 1) << offs; + local val:16 = (zext(XmmReg2[0,64]) & ((1 << len) - 1)); + XmmReg1 = (XmmReg1 & ~zext(mask)) | (zext(val) << offs); +} + +:MOVNTSD m64, XmmReg1 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x2B; XmmReg1 ... & m64 { + m64 = XmmReg1[0,64]; +} + +:MOVNTSS m32, XmmReg1 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x2B; XmmReg1 ... & m32 { + m32 = XmmReg1[0,32]; +} } # end with : lockprefx=0 From f71ae463d2046a19b0a19433efca2ad76ca61fb6 Mon Sep 17 00:00:00 2001 From: ghidra007 Date: Tue, 26 Aug 2025 16:05:05 +0000 Subject: [PATCH 2/3] GP-5948 Improved auto vt dupe match's operand equivalency check to account for internal function ref operands. --- .../gui/actions/AutoVersionTrackingTask.java | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java index 3bba2d3522..8512304a45 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java @@ -89,14 +89,9 @@ public class AutoVersionTrackingTask extends Task { /** * Constructor for a modal/blocking AutoVersionTrackingTask * - * @param session The Version Tracking session containing the source, destination, correlator * and match information needed for this command. * @param toolOptions the options used when applying matches - * @param minCombinedReferenceCorrelatorScore The minimum score used to limit matches created by - * the Combined Reference Correlator. - * @param minCombinedReferenceCorrelatorConfidence The minimum confidence used to limit matches - * created by the Combined Reference Correlator. */ public AutoVersionTrackingTask(VTSession session, ToolOptions toolOptions) { super(NAME, true, true, true); @@ -378,12 +373,10 @@ public class AutoVersionTrackingTask extends Task { } /** - * Method to create implied matches for the existing applied matches in the current session - * @param applyGoodMatches if true, create applied matches for "good" implied matches based on - * votes/conflict information. For all the applied implied matches, rerun the creation of - * applied matches until no new ones found. + * Method to create implied matches for the existing applied matches in the current session * @param applyGoodMatches if true, apply matches if minVotes met and maxConflicts not exceeded - * for particular match, if false, don't apply any matches + * for particular match, if false, don't apply any matches. For all the applied implied matches, + * rerun the creation of applied matches until no new ones found. * @param minVotes minimum votes needed to apply a match * @param maxConflicts maximum conflicts allowed to apply a match * @param monitor the task monitor @@ -646,7 +639,7 @@ public class AutoVersionTrackingTask extends Task { continue; } - if (hasAcceptedRelatedAssociation(association, monitor)) { + if (hasAcceptedRelatedAssociation(association)) { Msg.warn(AutoVersionTrackingTask.class, "This association has a related association with an accepted match so cannot " + "make this association accepted which would try to block the already accepted " + @@ -702,12 +695,11 @@ public class AutoVersionTrackingTask extends Task { * Method to test whether any related associations (ie associations with either the same source * or the same destination address) have already been accepted * @param association the given association (src/dest match pair) - * @param taskMonitor the task monitor * @return true if any related associations have already been accepted, false otherwise * @throws CancelledException if cancelled */ - private boolean hasAcceptedRelatedAssociation(VTAssociation association, - TaskMonitor taskMonitor) throws CancelledException { + private boolean hasAcceptedRelatedAssociation(VTAssociation association) + throws CancelledException { VTAssociationManager vtAssocManager = session.getAssociationManager(); @@ -745,7 +737,7 @@ public class AutoVersionTrackingTask extends Task { * function pair association or it would have been identified as a unique match by the exact * unique function instruction correltor. This method attempts to find unique matches from * within the related subsets by comparing operand information. - * @param matches The set of matches from the duplicate function instruction correlator + * @param matchSet The set of matches from the duplicate function instruction correlator * @param monitor Allows user to cancel * @return true if there are any markup errors, false if no markup errors * @throws CancelledException if cancelled @@ -1169,7 +1161,8 @@ public class AutoVersionTrackingTask extends Task { * Method to check to see if both addresses have functions at them or the same data type at them * @param addr1 the first Address * @param addr2 the second Address - * @return + * @return true if same operand type (ie both functions, both same data type, same internal + * function reference */ private boolean isSameOperandType(Address addr1, Address addr2) { @@ -1179,9 +1172,22 @@ public class AutoVersionTrackingTask extends Task { if (function2 != null) { return true; } - else { - return false; + return false; + } + + // are both references to same offset in the mapped functions + function1 = sourceProgram.getFunctionManager().getFunctionContaining(addr1); + if (function1 != null) { + Function function2 = + destinationProgram.getFunctionManager().getFunctionContaining(addr2); + if (function2 != null) { + long offsetInFunction1 = getOffsetInFunction(function1, addr1); + long offsetInFunction2 = getOffsetInFunction(function2, addr2); + if (offsetInFunction1 == offsetInFunction2) { + return true; + } } + return false; } Data data1 = sourceProgram.getListing().getDataAt(addr1); @@ -1275,9 +1281,7 @@ public class AutoVersionTrackingTask extends Task { // get offset from top of function to use in function to operandMap map // can be positive or negative offset (positive means instruction address is after // the entry address, negative means instruction address is before entry address) - Long entryOffset = function.getEntryPoint().getOffset(); - Long instOffset = inst.getAddress().getOffset(); - Long offset = instOffset - entryOffset; + long offset = getOffsetInFunction(function, inst.getAddress()); offsetToOperandsMap.put(offset, map); } @@ -1289,6 +1293,15 @@ public class AutoVersionTrackingTask extends Task { return offsetToOperandsMap; } + private long getOffsetInFunction(Function function, Address addressInFunction) { + + long entryOffset = function.getEntryPoint().getOffset(); + long addrOffset = addressInFunction.getOffset(); + long offset = addrOffset - entryOffset; + + return offset; + } + /** * Method to create offset/operand mapping for each function in match set * if more than one identical offset/operand mapping in src or dest piles then remove @@ -1343,7 +1356,7 @@ public class AutoVersionTrackingTask extends Task { // skip already accepted or blocked matches if (association.getStatus() == VTAssociationStatus.AVAILABLE) { - if (hasAcceptedRelatedAssociation(association, monitor)) { + if (hasAcceptedRelatedAssociation(association)) { Msg.warn(AutoVersionTrackingTask.class, "This association has a related association with an accepted match so cannot " + "make this association accepted which would try to block the already accepted " + From c85d7831cced2008ecdeee7fb7749f72a9a0c112 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 27 Aug 2025 11:19:47 -0400 Subject: [PATCH 3/3] GP-0: Upping patch to 11.4.3 --- Ghidra/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/application.properties b/Ghidra/application.properties index f5c62f1219..28262582ac 100644 --- a/Ghidra/application.properties +++ b/Ghidra/application.properties @@ -1,5 +1,5 @@ application.name=Ghidra -application.version=11.4.2 +application.version=11.4.3 application.release.name=DEV application.layout.version=3 application.gradle.min=8.5