From 757381f3ff207c6a37dbf32bc6e37c6a29c9f6be Mon Sep 17 00:00:00 2001 From: Lin Chen Date: Tue, 27 Aug 2024 08:28:12 -0700 Subject: [PATCH] Add operand keywords in BinExport exporter PiperOrigin-RevId: 667998113 Change-Id: I5b16e54170cc64016d544432ec068a11bf7db664 --- .../security/binexport/BinExport2Builder.java | 77 ++++++++++++++++++- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/java/src/main/java/com/google/security/binexport/BinExport2Builder.java b/java/src/main/java/com/google/security/binexport/BinExport2Builder.java index 7c29eb2b..2483b4c8 100644 --- a/java/src/main/java/com/google/security/binexport/BinExport2Builder.java +++ b/java/src/main/java/com/google/security/binexport/BinExport2Builder.java @@ -14,6 +14,8 @@ package com.google.security.binexport; +import static java.util.stream.Collectors.joining; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -28,6 +30,7 @@ import ghidra.program.model.block.CodeBlock; import ghidra.program.model.block.CodeBlockReference; import ghidra.program.model.data.StringDataInstance; +import ghidra.program.model.lang.OperandType; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CodeUnitFormat; @@ -61,6 +64,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; @@ -165,6 +169,12 @@ private void buildMetaInformation() { "tword ptr ", 10, "xmmword ptr ", 16); + static final ImmutableSet OPERAND_SHIFT_SYMBOLS = + ImmutableSet.of("asr", "lsl", "lsr", "ror", "rrx"); + static final ImmutableSet OPERAND_CONDITION_SYMBOLS = + ImmutableSet.of( + "eq", "ne", "cs", "hs", "cc", "lo", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", + "le", "al"); // Ghidra separates operands of an instruction already for us. // The separators and brackets don't and are difficult to represent any semantically meanings. // Instead, it only helps to determine the priorities of expression tree nodes. @@ -259,6 +269,7 @@ private Optional addCommentedExpression( private void buildOperandExpressions( Integer startOffset, Integer endOffset, + Integer operandType, ImmutableList operandList, ImmutableList operandMarkupList, Integer parentId, @@ -273,6 +284,58 @@ private void buildOperandExpressions( if (parentId != null) { exprBuilder.setParentIndex(parentId); } + + // Find shift keywords + var operandSubstring = + operandMarkupList.subList(startOffset, endOffset).stream() + .map(Object::toString) + .collect(joining("")) + .toLowerCase(Locale.getDefault()); + + for (var symbol : OPERAND_SHIFT_SYMBOLS) { + if (!operandSubstring.startsWith(symbol)) { + continue; + } + var expr = exprBuilder.setType(BinExport2.Expression.Type.OPERATOR).setSymbol(symbol).build(); + var nextParentId = getOrAddExpression(expr); + opExprIndices.add(nextParentId); + buildOperandExpressions( + startOffset + symbol.length(), + endOffset, + operandType, + operandList, + operandMarkupList, + nextParentId, + opExprIndices, + addComment, + comments); + return; + } + + // Find Condition keywords + if (OperandType.isFlag(operandType)) { + for (var symbol : OPERAND_CONDITION_SYMBOLS) { + if (!operandSubstring.startsWith(symbol)) { + continue; + } + var expr = + exprBuilder.setType(BinExport2.Expression.Type.OPERATOR).setSymbol(symbol).build(); + var nextParentId = getOrAddExpression(expr); + opExprIndices.add(nextParentId); + buildOperandExpressions( + startOffset + symbol.length(), + endOffset, + operandType, + operandList, + operandMarkupList, + nextParentId, + opExprIndices, + addComment, + comments); + return; + } + } + // Find first non-enclosing separator var openClosure = 0; for (var i = startOffset; i < endOffset; i++) { @@ -300,6 +363,7 @@ private void buildOperandExpressions( buildOperandExpressions( startOffset, i, + operandType, operandList, operandMarkupList, separatorId, @@ -309,6 +373,7 @@ private void buildOperandExpressions( buildOperandExpressions( i + 1, endOffset, + operandType, operandList, operandMarkupList, separatorId, @@ -334,6 +399,7 @@ private void buildOperandExpressions( buildOperandExpressions( startOffset, endOffset - 1, + operandType, operandList, operandMarkupList, nextParentId, @@ -375,6 +441,7 @@ private void buildOperandExpressions( buildOperandExpressions( startOffset + 1, j, + operandType, operandList, operandMarkupList, nextParentId, @@ -384,6 +451,7 @@ private void buildOperandExpressions( buildOperandExpressions( j + 1, endOffset, + operandType, operandList, operandMarkupList, parentId, @@ -464,6 +532,7 @@ private void buildOperandExpressions( buildOperandExpressions( startOffset + 1, endOffset, + operandType, operandList, operandMarkupList, nextParentId, @@ -484,6 +553,7 @@ private ImmutableList buildInstructionOperands( Boolean addComment = operandMarkupList.size() == operandList.size(); Integer parentId = null; + Integer startOffset = 0; var opExprIndices = new ArrayList(); // Add size prefix if applicable @@ -500,14 +570,13 @@ private ImmutableList buildInstructionOperands( .build(); parentId = getOrAddExpression(expr); opExprIndices.add(parentId); - operandMarkupList = - operandMarkupList.subList(entry.getKey().length(), operandMarkupList.size()); - operandList = operandList.subList(entry.getKey().length(), operandList.size()); + startOffset += entry.getKey().length(); break; } buildOperandExpressions( - 0, + startOffset, operandMarkupList.size(), + instr.getOperandType(i), operandList, operandMarkupList, parentId,