mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
InvokeMethodsTest passes
This commit is contained in:
parent
822ea1a376
commit
f4d25ccebb
4 changed files with 97 additions and 70 deletions
|
@ -44,16 +44,16 @@ public class InvokeMethods {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits the pcode for an invoke instruction.
|
* Emits the pcode for an invoke instruction.
|
||||||
|
* @param pCode is the pcode accumulator
|
||||||
* @param offset - the index of the constant pool element containing a symbolic reference
|
* @param offset - the index of the constant pool element containing a symbolic reference
|
||||||
* to a method or a call site specifier.
|
* to a method or a call site specifier.
|
||||||
* @param constantPool - the constant pool
|
* @param constantPool - the constant pool
|
||||||
* @param type - the JavaInvocationType of the invocation
|
* @param type - the JavaInvocationType of the invocation
|
||||||
* @return - the pcode as a string
|
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForInvoke(int offset, AbstractConstantPoolInfoJava[] constantPool,
|
public static void getPcodeForInvoke(PcodeOpEmitter pCode, int offset,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool,
|
||||||
JavaInvocationType type) {
|
JavaInvocationType type) {
|
||||||
|
|
||||||
StringBuilder pCode = new StringBuilder();
|
|
||||||
String descriptor = DescriptorDecoder.getDescriptorForInvoke(offset, constantPool, type);
|
String descriptor = DescriptorDecoder.getDescriptorForInvoke(offset, constantPool, type);
|
||||||
List<JavaComputationalCategory> categories =
|
List<JavaComputationalCategory> categories =
|
||||||
DescriptorDecoder.getParameterCategories(descriptor);
|
DescriptorDecoder.getParameterCategories(descriptor);
|
||||||
|
@ -67,33 +67,31 @@ public class InvokeMethods {
|
||||||
}
|
}
|
||||||
emitPcodeToMoveParams(pCode, categories, includeThisPointer, stackPurge);
|
emitPcodeToMoveParams(pCode, categories, includeThisPointer, stackPurge);
|
||||||
emitPcodeToResolveMethodReference(pCode, offset, constantPool, type);
|
emitPcodeToResolveMethodReference(pCode, offset, constantPool, type);
|
||||||
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
pCode.emitIndirectCall(CALL_TARGET);
|
||||||
|
|
||||||
JavaComputationalCategory retType =
|
JavaComputationalCategory retType =
|
||||||
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(descriptor);
|
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(descriptor);
|
||||||
switch (retType) {
|
switch (retType) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
pCode.emitPushCat1Value(CAT_1_RETURN);
|
||||||
break;
|
break;
|
||||||
case CAT_2:
|
case CAT_2:
|
||||||
PcodeTextEmitter.emitPushCat2Value(pCode, CAT_2_RETURN);
|
pCode.emitPushCat2Value(CAT_2_RETURN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return pCode.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits the pcode for an invoke instruction.
|
* Emits the pcode for an invoke instruction.
|
||||||
|
* @param pCode is the pcode accumulator
|
||||||
* @param offset - the index of the constant pool element containing a symbolic reference
|
* @param offset - the index of the constant pool element containing a symbolic reference
|
||||||
* to a method or a call site specifier.
|
* to a method or a call site specifier.
|
||||||
* @param constantPool - the constant pool
|
* @param constantPool - the constant pool
|
||||||
* @return - the pcode as a string
|
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForInvokeDynamic(int offset,
|
public static void getPcodeForInvokeDynamic(PcodeOpEmitter pCode, int offset,
|
||||||
AbstractConstantPoolInfoJava[] constantPool) {
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
StringBuilder pCode = new StringBuilder();
|
|
||||||
String invokeDynamicDescriptor = DescriptorDecoder.getDescriptorForInvoke(offset,
|
String invokeDynamicDescriptor = DescriptorDecoder.getDescriptorForInvoke(offset,
|
||||||
constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
List<JavaComputationalCategory> categories =
|
List<JavaComputationalCategory> categories =
|
||||||
|
@ -104,21 +102,20 @@ public class InvokeMethods {
|
||||||
emitPcodeToMoveParams(pCode, categories, false, stackPurge);
|
emitPcodeToMoveParams(pCode, categories, false, stackPurge);
|
||||||
emitPcodeToResolveMethodReference(pCode, offset, constantPool,
|
emitPcodeToResolveMethodReference(pCode, offset, constantPool,
|
||||||
JavaInvocationType.INVOKE_DYNAMIC);
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
pCode.emitIndirectCall(CALL_TARGET);
|
||||||
|
|
||||||
JavaComputationalCategory retType =
|
JavaComputationalCategory retType =
|
||||||
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(invokeDynamicDescriptor);
|
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(invokeDynamicDescriptor);
|
||||||
switch (retType) {
|
switch (retType) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
pCode.emitPushCat1Value(CAT_1_RETURN);
|
||||||
break;
|
break;
|
||||||
case CAT_2:
|
case CAT_2:
|
||||||
PcodeTextEmitter.emitPushCat2Value(pCode, CAT_2_RETURN);
|
pCode.emitPushCat2Value(CAT_2_RETURN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return pCode.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,25 +125,26 @@ public class InvokeMethods {
|
||||||
* @param pCode - the pcode buffer
|
* @param pCode - the pcode buffer
|
||||||
* @param categories - the list of computational categories on the top of the stack
|
* @param categories - the list of computational categories on the top of the stack
|
||||||
* @param includeThisPointer - true if the first element on the stack is an implicit this parameter
|
* @param includeThisPointer - true if the first element on the stack is an implicit this parameter
|
||||||
|
* @param totalSize -
|
||||||
*/
|
*/
|
||||||
static void emitPcodeToMoveParams(StringBuilder pCode,
|
static void emitPcodeToMoveParams(PcodeOpEmitter pCode,
|
||||||
List<JavaComputationalCategory> categories, boolean includeThisPointer, int totalSize) {
|
List<JavaComputationalCategory> categories, boolean includeThisPointer, int totalSize) {
|
||||||
|
|
||||||
//pop the parameters off of the stack
|
//pop the parameters off of the stack
|
||||||
for (int i = categories.size() - 1; i >= 0; --i) {
|
for (int i = categories.size() - 1; i >= 0; --i) {
|
||||||
switch (categories.get(i)) {
|
switch (categories.get(i)) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
pCode.emitPopCat1Value(PARAMETER + Integer.toString(i));
|
||||||
totalSize -= 4;
|
totalSize -= 4;
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||||
Integer.toString(totalSize) + ":4", PARAMETER + Integer.toString(i));
|
Integer.toString(totalSize) + ":4", PARAMETER + Integer.toString(i));
|
||||||
break;
|
break;
|
||||||
case CAT_2:
|
case CAT_2:
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
pCode.emitPopCat1Value(PARAMETER + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||||
Integer.toString(totalSize - 8) + ":4", PARAMETER + Integer.toString(i));
|
Integer.toString(totalSize - 8) + ":4", PARAMETER + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER_PART2 + Integer.toString(i));
|
pCode.emitPopCat1Value(PARAMETER_PART2 + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||||
Integer.toString(totalSize - 4) + ":4",
|
Integer.toString(totalSize - 4) + ":4",
|
||||||
PARAMETER_PART2 + Integer.toString(i));
|
PARAMETER_PART2 + Integer.toString(i));
|
||||||
totalSize -= 8;
|
totalSize -= 8;
|
||||||
|
@ -157,9 +155,9 @@ public class InvokeMethods {
|
||||||
}
|
}
|
||||||
//pop off the this pointer if there is one
|
//pop off the this pointer if there is one
|
||||||
if (includeThisPointer) {
|
if (includeThisPointer) {
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, THIS);
|
pCode.emitPopCat1Value(THIS);
|
||||||
totalSize -= 4;
|
totalSize -= 4;
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||||
Integer.toString(totalSize) + ":4", THIS);
|
Integer.toString(totalSize) + ":4", THIS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -172,31 +170,31 @@ public class InvokeMethods {
|
||||||
* @param constantPool - the constant pool
|
* @param constantPool - the constant pool
|
||||||
* @param type - the type of the invocation
|
* @param type - the type of the invocation
|
||||||
*/
|
*/
|
||||||
static void emitPcodeToResolveMethodReference(StringBuilder pCode, int offset,
|
static void emitPcodeToResolveMethodReference(PcodeOpEmitter pCode, int offset,
|
||||||
AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type) {
|
AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INVOKE_DYNAMIC:
|
case INVOKE_DYNAMIC:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||||
ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
||||||
break;
|
break;
|
||||||
case INVOKE_INTERFACE:
|
case INVOKE_INTERFACE:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
||||||
break;
|
break;
|
||||||
case INVOKE_SPECIAL:
|
case INVOKE_SPECIAL:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
||||||
break;
|
break;
|
||||||
case INVOKE_STATIC:
|
case INVOKE_STATIC:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||||
ConstantPoolJava.CPOOL_INVOKESTATIC);
|
ConstantPoolJava.CPOOL_INVOKESTATIC);
|
||||||
break;
|
break;
|
||||||
case INVOKE_VIRTUAL:
|
case INVOKE_VIRTUAL:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -114,6 +114,13 @@ public class PcodeOpEmitter {
|
||||||
defSpaceId = getConstant(defSpace.getSpaceID(), 8);
|
defSpaceId = getConstant(defSpace.getSpaceID(), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void defineTemp(String name, int size) {
|
||||||
|
Varnode vn = findVarnode(name, size);
|
||||||
|
if (!vn.isUnique() || vn.getSize() != size) {
|
||||||
|
throw new IllegalArgumentException("Name is already assigned: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits pcode to push a value of computational category 1 onto the stack.
|
* Emits pcode to push a value of computational category 1 onto the stack.
|
||||||
* @param valueName - name of varnode to push.
|
* @param valueName - name of varnode to push.
|
||||||
|
@ -253,7 +260,7 @@ public class PcodeOpEmitter {
|
||||||
* @param pcodeop
|
* @param pcodeop
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public void emitAssignRegisterFromPcodeOpCall(StringBuilder pCode, String register,
|
public void emitAssignRegisterFromPcodeOpCall(String register,
|
||||||
String pcodeop, String... args) {
|
String pcodeop, String... args) {
|
||||||
Symbol useropSym = language.getSymbolTable().findGlobalSymbol(pcodeop);
|
Symbol useropSym = language.getSymbolTable().findGlobalSymbol(pcodeop);
|
||||||
Varnode out = findRegister(register);
|
Varnode out = findRegister(register);
|
||||||
|
@ -290,7 +297,15 @@ public class PcodeOpEmitter {
|
||||||
AddressSpace spc = language.getAddressFactory().getAddressSpace(space);
|
AddressSpace spc = language.getAddressFactory().getAddressSpace(space);
|
||||||
// TODO: find correct space id
|
// TODO: find correct space id
|
||||||
in[0] = getConstant(spc.getSpaceID(), 8);
|
in[0] = getConstant(spc.getSpaceID(), 8);
|
||||||
in[1] = findRegister(offset);
|
if (offset.charAt(0) <= '9') {
|
||||||
|
String[] piece = offset.split(":");
|
||||||
|
int sz = Integer.parseInt(piece[1]);
|
||||||
|
long val = Long.decode(piece[0]);
|
||||||
|
in[1] = getConstant(val, sz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
in[1] = findRegister(offset);
|
||||||
|
}
|
||||||
in[2] = findVarnode(value, size);
|
in[2] = findVarnode(value, size);
|
||||||
PcodeOp op = new PcodeOp(opAddress, seqnum++, PcodeOp.STORE, in);
|
PcodeOp op = new PcodeOp(opAddress, seqnum++, PcodeOp.STORE, in);
|
||||||
opList.add(op);
|
opList.add(op);
|
||||||
|
|
|
@ -21,12 +21,27 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
import ghidra.javaclass.format.DescriptorDecoder;
|
import ghidra.javaclass.format.DescriptorDecoder;
|
||||||
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.lang.LanguageID;
|
||||||
|
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||||
|
|
||||||
public class InvokeMethodsTest {
|
public class InvokeMethodsTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
|
|
||||||
|
private SleighLanguage language;
|
||||||
|
private Address opAddress;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
language =
|
||||||
|
(SleighLanguage) getLanguageService().getLanguage(new LanguageID("JVM:BE:32:default"));
|
||||||
|
opAddress = language.getAddressFactory().getDefaultAddressSpace().getAddress(0x10000);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmitPcodeToResolveMethodReferenceInvokeDynamic() throws IOException {
|
public void testEmitPcodeToResolveMethodReferenceInvokeDynamic() throws IOException {
|
||||||
|
@ -43,15 +58,14 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_DYNAMIC);
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
||||||
assertEquals("incorrect pcode for dynamic invocation", expected.toString(),
|
assertEquals("incorrect pcode for dynamic invocation", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -70,16 +84,17 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
|
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_INTERFACE);
|
JavaInvocationType.INVOKE_INTERFACE);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||||
|
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||||
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
||||||
assertEquals("incorrect pcode for interface method invocation", expected.toString(),
|
assertEquals("incorrect pcode for interface method invocation", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -98,16 +113,17 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
|
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_SPECIAL);
|
JavaInvocationType.INVOKE_SPECIAL);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||||
|
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||||
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
||||||
assertEquals("incorrect pcode for special method invocation", expected.toString(),
|
assertEquals("incorrect pcode for special method invocation", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -126,15 +142,14 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_STATIC);
|
JavaInvocationType.INVOKE_STATIC);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKESTATIC);
|
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKESTATIC);
|
||||||
assertEquals("incorrect pcode for static method invocation", expected.toString(),
|
assertEquals("incorrect pcode for static method invocation", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -153,25 +168,25 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
|
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_VIRTUAL);
|
JavaInvocationType.INVOKE_VIRTUAL);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||||
|
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||||
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
||||||
assertEquals("incorrect pcode for static method invocation", expected.toString(),
|
assertEquals("incorrect pcode for static method invocation", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmitPcodeToReverseStackNoParamsNoThis() {
|
public void testEmitPcodeToReverseStackNoParamsNoThis() {
|
||||||
StringBuilder pCode = new StringBuilder();
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
//InvokeMethods.emitPcodeToReverseStack(pCode, new ArrayList<JavaComputationalCategory>(), false);
|
//InvokeMethods.emitPcodeToReverseStack(pCode, new ArrayList<JavaComputationalCategory>(), false);
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
assertEquals("incorrect pcode reversing stack: no params no this", expected.toString(),
|
assertEquals("incorrect pcode reversing stack: no params no this", expected, pCode);
|
||||||
pCode.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//test bad category
|
//test bad category
|
||||||
|
@ -190,10 +205,10 @@ public class InvokeMethodsTest {
|
||||||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||||
AbstractConstantPoolInfoJava[] constantPool =
|
AbstractConstantPoolInfoJava[] constantPool =
|
||||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||||
String pCode =
|
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||||
InvokeMethods.getPcodeForInvoke(1, constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
InvokeMethods.getPcodeForInvoke(pCode, 1, constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
|
|
||||||
StringBuilder expected = new StringBuilder();
|
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||||
String descriptor = DescriptorDecoder.getDescriptorForInvoke(1, constantPool,
|
String descriptor = DescriptorDecoder.getDescriptorForInvoke(1, constantPool,
|
||||||
JavaInvocationType.INVOKE_DYNAMIC);
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
List<JavaComputationalCategory> categories =
|
List<JavaComputationalCategory> categories =
|
||||||
|
@ -202,11 +217,10 @@ public class InvokeMethodsTest {
|
||||||
InvokeMethods.emitPcodeToMoveParams(expected, categories, false, 24);
|
InvokeMethods.emitPcodeToMoveParams(expected, categories, false, 24);
|
||||||
InvokeMethods.emitPcodeToResolveMethodReference(expected, 1, constantPool,
|
InvokeMethods.emitPcodeToResolveMethodReference(expected, 1, constantPool,
|
||||||
JavaInvocationType.INVOKE_DYNAMIC);
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
PcodeTextEmitter.emitIndirectCall(expected, InvokeMethods.CALL_TARGET);
|
expected.emitIndirectCall(InvokeMethods.CALL_TARGET);
|
||||||
PcodeTextEmitter.emitPushCat1Value(expected, InvokeMethods.CAT_1_RETURN);
|
expected.emitPushCat1Value(InvokeMethods.CAT_1_RETURN);
|
||||||
|
|
||||||
assertEquals("incorrect pcode for invoke dynamic: (JJII)I", expected.toString(), pCode);
|
|
||||||
|
|
||||||
|
assertEquals("incorrect pcode for invoke dynamic: (JJII)I", expected, pCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||||
|
|
||||||
public class ReferenceMethodsTest extends AbstractGhidraHeadlessIntegrationTest {
|
public class ReferenceMethodsTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
|
|
||||||
SleighLanguage language;
|
private SleighLanguage language;
|
||||||
Address opAddress;
|
private Address opAddress;
|
||||||
|
|
||||||
public ReferenceMethodsTest() {
|
public ReferenceMethodsTest() {
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue