Merge remote-tracking branch 'origin/GP-3214_emteere_duplicateRefMarkupFix--SQUASHED' into patch

This commit is contained in:
Ryan Kurtz 2023-03-22 11:08:22 -04:00
commit 4d8ec78c74
2 changed files with 175 additions and 29 deletions

View File

@ -2486,7 +2486,7 @@ public class SymbolicPropogator {
int numOperands = instruction.getNumOperands();
for (int i = 0; opIndex == Reference.MNEMONIC && i < numOperands; i++) {
for (int i = 0; i < numOperands; i++) {
int opType = instruction.getOperandType(i);
if ((opType & OperandType.ADDRESS) != 0) {
@ -2496,6 +2496,24 @@ public class SymbolicPropogator {
break;
}
}
if ((opType & OperandType.SCALAR) != 0) {
Scalar s = instruction.getScalar(i);
if (s != null) {
long val = s.getUnsignedValue();
// sort of a hack, for memory that is not byte addressable
if (val == wordOffset || val == (wordOffset >> 1)) {
opIndex = i;
break;
}
}
}
// Don't check more complicated operands if already found an operand that matches
// only continue checking for an exact scalar/address operand
if (opIndex != Reference.MNEMONIC) {
continue;
}
// markup the program counter for any flow
if ((opType & OperandType.REGISTER) != 0) {
Register reg = instruction.getRegister(i);
@ -2519,15 +2537,7 @@ public class SymbolicPropogator {
}
}
}
Scalar s = instruction.getScalar(i);
if (s != null) {
long val = s.getUnsignedValue();
// sort of a hack, for memory that is not byte addressable
if (val == wordOffset || val == (wordOffset >> 1)) {
opIndex = i;
break;
}
}
if ((opType & OperandType.DYNAMIC) != 0) {
List<Object> list = instruction.getDefaultOperandRepresentationList(i);
int len = list.size();

View File

@ -17,6 +17,7 @@ package ghidra.program.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.math.BigInteger;
@ -24,13 +25,17 @@ import org.junit.*;
import generic.test.AbstractGenericTest;
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.Reference;
import ghidra.program.util.SymbolicPropogator.Value;
import ghidra.util.exception.NotFoundException;
import ghidra.util.task.TaskMonitor;
/**
@ -44,17 +49,18 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
private ProgramBuilder builder;
private Program program;
private int txID;
private ConstantPropagationAnalyzer analyzer;
public ConstantPropogationReferenceTest() {
super();
}
@Before
public void setUp() throws Exception {
@Test
public void testOperandRef_MIPS6432() throws Exception {
builder = new ProgramBuilder("MIPS_6432", "MIPS:BE:64:64-32addr");
// lui v0, 0x80a8
// addiu v0, v0, -0xdf0
// sw v0, -0x46e8(gp)
@ -66,17 +72,8 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
analyzer = new ConstantPropagationAnalyzer();
program = builder.getProgram();
txID = program.startTransaction("Test");
}
@After
public void tearDown() throws Exception {
program.endTransaction(txID, true);
}
@Test
public void testOperandRef_MIPS6432() throws Exception {
program.startTransaction("Test");
Address codeStart = addr("0x80a7f214");
Listing listing = program.getListing();
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
@ -88,15 +85,154 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
assertOperandReferenceTo(0, instr, addr("0x80a7f210"));
assertNoOperandReference(1, instr);
setRegister(codeStart, 0x90000000L);
setRegister(codeStart, "gp", 0x90000000L);
analyze(addressSet);
assertOperandReferenceTo(1, instr, addr("0x8fffb918"));
}
@Test
public void testBadAddressOffsetTracking() throws Exception {
builder = new ProgramBuilder("thunk", ProgramBuilder._MIPS);
builder.setBytes("0x1000", "3c 1c 00 14 27 9c b3 34 03 99 e0 21 27 bd ff e0" +
"af bc 00 10 3c 07 12 34 24 e7 45 67" +
"ac a7 00 10 3c 06 0a 0b 24 c6 0c 0d" +
"ae 06 00 10 8e 11 00 10 8c b1 00 10" +
"8f b1 00 10 8e 51 00 10 ae 53 00 10" +
"8e 51 00 10" +
"36 92 00 00" +
"8e 51 00 10" +
"8e 92 00 10" +
"3c 11 00 53" +
"8e 51 00 10" +
"03 e0 00 08" +
"27 bd 00 20");
//00001000 lui gp,0x14
//00001004 addiu gp,gp,-0x4ccc
//00001008 addu gp,gp,t9
//0000100c addiu sp,sp,-0x20
//00001010 sw gp,0x10(sp)
//00001014 lui a3,0x1234
//00001018 addiu a3,a3,0x4567
//0000101c sw a3,0x10(a1)
//00001020 lui a2,0xa0b
//00001024 addiu a2,a2,0xc0d
//00001028 sw a2=>DAT_0a0b0c0d,0x10(s0)
//0000102c lw s1,0x10(s0)
//00001030 lw s1,0x10(a1)
//00001034 lw s1,0x10(sp)
//00001038 lw s1,0x10(s2)
//0000103c sw s3,0x10(s2)
//00001040 lw s1,0x10(s2)
//00001044 ori s2,s4,0x0
//00001048 lw s1,0x10(s2)
//0000104c lw s2,0x10(s4)
//00001050 lui s1=>DAT_00530000,0x53
//00001054 lw s1,0x10(s2)
//00001058 jr ra
//0000105c _addiu sp,sp,0x20
builder.disassemble("0x1000", 88, false);
builder.createFunction("0x1000");
analyzer = new ConstantPropagationAnalyzer();
program = builder.getProgram();
program.startTransaction("Test");
Address codeStart = addr("0x1000");
Listing listing = program.getListing();
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
setRegister(addr("0x1000"), "gp", 0x11200000);
// follow all flows building up context
// use context to fill out addresses on certain instructions
ContextEvaluator eval = new ConstantPropagationContextEvaluator(true) {
@Override
public boolean evaluateContextBefore(VarnodeContext context, Instruction instr) {
// TODO Auto-generated method stub
return super.evaluateContextBefore(context, instr);
}
private Varnode regValue(VarnodeContext context, String regName) {
return context.getRegisterVarnodeValue(context.getRegister(regName));
}
@Override
public boolean evaluateContext(VarnodeContext context, Instruction instr) {
String loc = instr.getMinAddress().toString();
Varnode registerVarnode;
switch(loc) {
case "00001010":
// gp should be 0x14 + t9 offset space
registerVarnode = regValue(context,"gp");
assertTrue("symbolic value", context.isSymbol(registerVarnode));
assertEquals("(t9, 0x13b334, 4)", registerVarnode.toString());
break;
// TODO: more tests
}
return super.evaluateContext(context, instr);
}
};
setRegister(addr("0x1000"), "s1", 0);
SymbolicPropogator symEval = new SymbolicPropogator(program);
Function func = program.getFunctionManager().getFunctionAt(builder.addr(0x1000));
symEval.flowConstants(codeStart, func.getBody(), eval, true, TaskMonitor.DUMMY);
Value registerValue = symEval.getRegisterValue(addr("0x1010"), null);
}
@Test
public void testCorrectOperandConstantParam_X86_64() throws Exception {
builder = new ProgramBuilder("thunk", ProgramBuilder._X64, "gcc", this);
// PUSH RBP
// MOV RBP,RSP
// MOV EDI,s_STRING_%s_%s_00040100
// MOV EAX,0x0
// CALL FUN_0004003d
// LEAVE
// RET
builder.setBytes("0x00040000",
"55 48 89 e5 bf 00 01 04 00 b8 00 00 00 00 66 67 e8 2a 00 c9 c3");
builder.setBytes("0x00040100",
"53 54 52 49 4e 47 20 25 73 20 25 73 0a 00 00");
builder.disassemble("0x00040000", 21);
analyzer = new ConstantPropagationAnalyzer();
program = builder.getProgram();
program.startTransaction("Test");
Address codeStart = addr("0x00040000");
Listing listing = program.getListing();
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(21));
analyze(addressSet);
Instruction instr = listing.getInstructionAt(addr("0x00040004"));
assertNoOperandReference(0, instr);
assertOperandReferenceTo(1, instr, addr("0x00040100"));
}
private void assertNoOperandReference(int opIndex, Instruction instr) {
Reference[] refs = instr.getOperandReferences(1);
Reference[] refs = instr.getOperandReferences(opIndex);
assertEquals("No reference on operand " + opIndex, 0, refs.length);
}
@ -110,9 +246,9 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
analyzer.added(program, addrs, TaskMonitor.DUMMY, null);
}
private void setRegister(Address a, long value) throws Exception {
private void setRegister(Address a, String regname, long value) throws Exception {
ProgramContext context = program.getProgramContext();
Register gp = context.getRegister("gp");
Register gp = context.getRegister(regname);
context.setRegisterValue(a, a.add(12), new RegisterValue(gp, BigInteger.valueOf(value)));
}