mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +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.
|
||||
* @param pCode is the pcode accumulator
|
||||
* @param offset - the index of the constant pool element containing a symbolic reference
|
||||
* to a method or a call site specifier.
|
||||
* @param constantPool - the constant pool
|
||||
* @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) {
|
||||
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
String descriptor = DescriptorDecoder.getDescriptorForInvoke(offset, constantPool, type);
|
||||
List<JavaComputationalCategory> categories =
|
||||
DescriptorDecoder.getParameterCategories(descriptor);
|
||||
|
@ -67,33 +67,31 @@ public class InvokeMethods {
|
|||
}
|
||||
emitPcodeToMoveParams(pCode, categories, includeThisPointer, stackPurge);
|
||||
emitPcodeToResolveMethodReference(pCode, offset, constantPool, type);
|
||||
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
||||
pCode.emitIndirectCall(CALL_TARGET);
|
||||
|
||||
JavaComputationalCategory retType =
|
||||
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(descriptor);
|
||||
switch (retType) {
|
||||
case CAT_1:
|
||||
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
||||
pCode.emitPushCat1Value(CAT_1_RETURN);
|
||||
break;
|
||||
case CAT_2:
|
||||
PcodeTextEmitter.emitPushCat2Value(pCode, CAT_2_RETURN);
|
||||
pCode.emitPushCat2Value(CAT_2_RETURN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return pCode.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* to a method or a call site specifier.
|
||||
* @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) {
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
String invokeDynamicDescriptor = DescriptorDecoder.getDescriptorForInvoke(offset,
|
||||
constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||
List<JavaComputationalCategory> categories =
|
||||
|
@ -104,21 +102,20 @@ public class InvokeMethods {
|
|||
emitPcodeToMoveParams(pCode, categories, false, stackPurge);
|
||||
emitPcodeToResolveMethodReference(pCode, offset, constantPool,
|
||||
JavaInvocationType.INVOKE_DYNAMIC);
|
||||
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
||||
pCode.emitIndirectCall(CALL_TARGET);
|
||||
|
||||
JavaComputationalCategory retType =
|
||||
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(invokeDynamicDescriptor);
|
||||
switch (retType) {
|
||||
case CAT_1:
|
||||
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
||||
pCode.emitPushCat1Value(CAT_1_RETURN);
|
||||
break;
|
||||
case CAT_2:
|
||||
PcodeTextEmitter.emitPushCat2Value(pCode, CAT_2_RETURN);
|
||||
pCode.emitPushCat2Value(CAT_2_RETURN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return pCode.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,25 +125,26 @@ public class InvokeMethods {
|
|||
* @param pCode - the pcode buffer
|
||||
* @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 totalSize -
|
||||
*/
|
||||
static void emitPcodeToMoveParams(StringBuilder pCode,
|
||||
static void emitPcodeToMoveParams(PcodeOpEmitter pCode,
|
||||
List<JavaComputationalCategory> categories, boolean includeThisPointer, int totalSize) {
|
||||
|
||||
//pop the parameters off of the stack
|
||||
for (int i = categories.size() - 1; i >= 0; --i) {
|
||||
switch (categories.get(i)) {
|
||||
case CAT_1:
|
||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
||||
pCode.emitPopCat1Value(PARAMETER + Integer.toString(i));
|
||||
totalSize -= 4;
|
||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||
Integer.toString(totalSize) + ":4", PARAMETER + Integer.toString(i));
|
||||
break;
|
||||
case CAT_2:
|
||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||
pCode.emitPopCat1Value(PARAMETER + Integer.toString(i));
|
||||
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||
Integer.toString(totalSize - 8) + ":4", PARAMETER + Integer.toString(i));
|
||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER_PART2 + Integer.toString(i));
|
||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||
pCode.emitPopCat1Value(PARAMETER_PART2 + Integer.toString(i));
|
||||
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||
Integer.toString(totalSize - 4) + ":4",
|
||||
PARAMETER_PART2 + Integer.toString(i));
|
||||
totalSize -= 8;
|
||||
|
@ -157,9 +155,9 @@ public class InvokeMethods {
|
|||
}
|
||||
//pop off the this pointer if there is one
|
||||
if (includeThisPointer) {
|
||||
PcodeTextEmitter.emitPopCat1Value(pCode, THIS);
|
||||
pCode.emitPopCat1Value(THIS);
|
||||
totalSize -= 4;
|
||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||
pCode.emitWriteToMemory(PARAM_SPACE, 4,
|
||||
Integer.toString(totalSize) + ":4", THIS);
|
||||
|
||||
}
|
||||
|
@ -172,31 +170,31 @@ public class InvokeMethods {
|
|||
* @param constantPool - the constant pool
|
||||
* @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) {
|
||||
switch (type) {
|
||||
case INVOKE_DYNAMIC:
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||
ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
||||
break;
|
||||
case INVOKE_INTERFACE:
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
||||
break;
|
||||
case INVOKE_SPECIAL:
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
||||
break;
|
||||
case INVOKE_STATIC:
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||
ConstantPoolJava.CPOOL_INVOKESTATIC);
|
||||
break;
|
||||
case INVOKE_VIRTUAL:
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||
pCode.emitAssignRegisterFromPcodeOpCall(CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
||||
break;
|
||||
|
|
|
@ -114,6 +114,13 @@ public class PcodeOpEmitter {
|
|||
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.
|
||||
* @param valueName - name of varnode to push.
|
||||
|
@ -253,7 +260,7 @@ public class PcodeOpEmitter {
|
|||
* @param pcodeop
|
||||
* @param args
|
||||
*/
|
||||
public void emitAssignRegisterFromPcodeOpCall(StringBuilder pCode, String register,
|
||||
public void emitAssignRegisterFromPcodeOpCall(String register,
|
||||
String pcodeop, String... args) {
|
||||
Symbol useropSym = language.getSymbolTable().findGlobalSymbol(pcodeop);
|
||||
Varnode out = findRegister(register);
|
||||
|
@ -290,7 +297,15 @@ public class PcodeOpEmitter {
|
|||
AddressSpace spc = language.getAddressFactory().getAddressSpace(space);
|
||||
// TODO: find correct space id
|
||||
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);
|
||||
PcodeOp op = new PcodeOp(opAddress, seqnum++, PcodeOp.STORE, in);
|
||||
opList.add(op);
|
||||
|
|
|
@ -21,12 +21,27 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.javaclass.format.DescriptorDecoder;
|
||||
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
|
||||
public void testEmitPcodeToResolveMethodReferenceInvokeDynamic() throws IOException {
|
||||
|
@ -43,15 +58,14 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_DYNAMIC);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
||||
assertEquals("incorrect pcode for dynamic invocation", expected.toString(),
|
||||
pCode.toString());
|
||||
assertEquals("incorrect pcode for dynamic invocation", expected, pCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -70,16 +84,17 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_INTERFACE);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
||||
assertEquals("incorrect pcode for interface method invocation", expected.toString(),
|
||||
pCode.toString());
|
||||
assertEquals("incorrect pcode for interface method invocation", expected, pCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,16 +113,17 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_SPECIAL);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
||||
assertEquals("incorrect pcode for special method invocation", expected.toString(),
|
||||
pCode.toString());
|
||||
assertEquals("incorrect pcode for special method invocation", expected, pCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -126,15 +142,14 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_STATIC);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, "0", "1", ConstantPoolJava.CPOOL_INVOKESTATIC);
|
||||
assertEquals("incorrect pcode for static method invocation", expected.toString(),
|
||||
pCode.toString());
|
||||
assertEquals("incorrect pcode for static method invocation", expected, pCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -153,25 +168,25 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
pCode.defineTemp(InvokeMethods.THIS, 4);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(pCode, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_VIRTUAL);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(expected, InvokeMethods.CALL_TARGET,
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
expected.defineTemp(InvokeMethods.THIS, 4);
|
||||
expected.emitAssignRegisterFromPcodeOpCall(InvokeMethods.CALL_TARGET,
|
||||
ConstantPoolJava.CPOOL_OP, InvokeMethods.THIS, "1",
|
||||
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
||||
assertEquals("incorrect pcode for static method invocation", expected.toString(),
|
||||
pCode.toString());
|
||||
assertEquals("incorrect pcode for static method invocation", expected, pCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmitPcodeToReverseStackNoParamsNoThis() {
|
||||
StringBuilder pCode = new StringBuilder();
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
//InvokeMethods.emitPcodeToReverseStack(pCode, new ArrayList<JavaComputationalCategory>(), false);
|
||||
StringBuilder expected = new StringBuilder();
|
||||
assertEquals("incorrect pcode reversing stack: no params no this", expected.toString(),
|
||||
pCode.toString());
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
assertEquals("incorrect pcode reversing stack: no params no this", expected, pCode);
|
||||
}
|
||||
|
||||
//test bad category
|
||||
|
@ -190,10 +205,10 @@ public class InvokeMethodsTest {
|
|||
byte[] classFileBytes = TestClassFileCreator.getByteArray(classFile);
|
||||
AbstractConstantPoolInfoJava[] constantPool =
|
||||
TestClassFileCreator.getConstantPoolFromBytes(classFileBytes);
|
||||
String pCode =
|
||||
InvokeMethods.getPcodeForInvoke(1, constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||
PcodeOpEmitter pCode = new PcodeOpEmitter(language, opAddress);
|
||||
InvokeMethods.getPcodeForInvoke(pCode, 1, constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||
|
||||
StringBuilder expected = new StringBuilder();
|
||||
PcodeOpEmitter expected = new PcodeOpEmitter(language, opAddress);
|
||||
String descriptor = DescriptorDecoder.getDescriptorForInvoke(1, constantPool,
|
||||
JavaInvocationType.INVOKE_DYNAMIC);
|
||||
List<JavaComputationalCategory> categories =
|
||||
|
@ -202,11 +217,10 @@ public class InvokeMethodsTest {
|
|||
InvokeMethods.emitPcodeToMoveParams(expected, categories, false, 24);
|
||||
InvokeMethods.emitPcodeToResolveMethodReference(expected, 1, constantPool,
|
||||
JavaInvocationType.INVOKE_DYNAMIC);
|
||||
PcodeTextEmitter.emitIndirectCall(expected, InvokeMethods.CALL_TARGET);
|
||||
PcodeTextEmitter.emitPushCat1Value(expected, InvokeMethods.CAT_1_RETURN);
|
||||
|
||||
assertEquals("incorrect pcode for invoke dynamic: (JJII)I", expected.toString(), pCode);
|
||||
expected.emitIndirectCall(InvokeMethods.CALL_TARGET);
|
||||
expected.emitPushCat1Value(InvokeMethods.CAT_1_RETURN);
|
||||
|
||||
assertEquals("incorrect pcode for invoke dynamic: (JJII)I", expected, pCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
|||
|
||||
public class ReferenceMethodsTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
|
||||
SleighLanguage language;
|
||||
Address opAddress;
|
||||
private SleighLanguage language;
|
||||
private Address opAddress;
|
||||
|
||||
public ReferenceMethodsTest() {
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue