mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-10-24 06:01:09 +00:00
Merge remote-tracking branch 'origin/GP-3214_emteere_duplicateRefMarkupFix--SQUASHED' into patch
This commit is contained in:
commit
4d8ec78c74
|
@ -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();
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user