mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Program specific, user-defined, cspec extensions
Documentation for spec extensions Handle extensions with parse errors Export button for spec extensions Pop-up dialog for parse errors in user-defined specification extensions GP-653 corrected some minor issues and established new ProgramDB version make incremental initialization constructor for AddressSized private Make AddressSized fields private More adjustments to AddressSized Review fixes for BasicCompilerSpec Take restoreXml out of DataOrganization interface Remove restoreXml from BitFieldPacking interface More review fixes Prevent callotherfixup extension with non-existent target Suggested export name More documentation for SpecExtension Support for undo/redo with spec extensions Documentation for ConstructTpl Split out ProgramCompilerSpec and other changes for review Changes after next round of reviews
This commit is contained in:
parent
27fbe7278d
commit
a5d4ca3cab
108 changed files with 7997 additions and 1997 deletions
|
@ -18,6 +18,7 @@ package ghidra.dalvik.dex.inject;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.PcodeEmit;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.file.formats.android.dex.analyzer.DexAnalysisState;
|
||||
import ghidra.file.formats.android.dex.format.*;
|
||||
import ghidra.file.formats.android.dex.util.DexUtil;
|
||||
|
@ -30,6 +31,8 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
* The "uponentry" injection for a DEX method. We simulate DEX's register stack by copying values from
|
||||
|
@ -39,17 +42,21 @@ import ghidra.util.Msg;
|
|||
public class InjectPayloadDexParameters implements InjectPayload {
|
||||
public final static int INPUT_REGISTER_START = 0x100;
|
||||
public final static int REGISTER_START = 0x1000;
|
||||
private String name;
|
||||
private String sourceName;
|
||||
private InjectParameter[] noParams;
|
||||
private boolean analysisStateRecoverable;
|
||||
|
||||
public InjectPayloadDexParameters() {
|
||||
public InjectPayloadDexParameters(String nm, String srcName) {
|
||||
name = nm;
|
||||
sourceName = srcName;
|
||||
noParams = new InjectParameter[0];
|
||||
analysisStateRecoverable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "dexparameters";
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,10 +64,9 @@ public class InjectPayloadDexParameters implements InjectPayload {
|
|||
return CALLMECHANISM_TYPE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "dexparameters";
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,6 +84,11 @@ public class InjectPayloadDexParameters implements InjectPayload {
|
|||
return noParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorPlaceholder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(InjectContext context, PcodeEmit emit) {
|
||||
// not used
|
||||
|
@ -101,23 +112,27 @@ public class InjectPayloadDexParameters implements InjectPayload {
|
|||
PcodeOp[] resOps;
|
||||
Function func = program.getFunctionManager().getFunctionContaining(con.baseAddr);
|
||||
EncodedMethod encodedMethod = null;
|
||||
if (func != null)
|
||||
if (func != null) {
|
||||
encodedMethod = analysisState.getEncodedMethod(func.getEntryPoint());
|
||||
if (encodedMethod == null)
|
||||
}
|
||||
if (encodedMethod == null) {
|
||||
return new PcodeOp[0];
|
||||
}
|
||||
int paramCount = 0;
|
||||
if (!encodedMethod.isStatic())
|
||||
if (!encodedMethod.isStatic()) {
|
||||
paramCount += 1; // A this pointer at least
|
||||
}
|
||||
CodeItem codeItem = encodedMethod.getCodeItem();
|
||||
int registerIndex = codeItem.getRegistersSize() - codeItem.getIncomingSize();
|
||||
MethodIDItem methodIDItem = header.getMethods().get( encodedMethod.getMethodIndex() );
|
||||
MethodIDItem methodIDItem = header.getMethods().get(encodedMethod.getMethodIndex());
|
||||
int prototypeIndex = methodIDItem.getProtoIndex() & 0xffff;
|
||||
PrototypesIDItem prototype = header.getPrototypes().get(prototypeIndex);
|
||||
TypeList parameters = prototype.getParameters();
|
||||
if (parameters != null)
|
||||
if (parameters != null) {
|
||||
paramCount += parameters.getItems().size();
|
||||
}
|
||||
AddressSpace registerSpace = program.getAddressFactory().getAddressSpace("register");
|
||||
resOps = new PcodeOp[ paramCount ];
|
||||
resOps = new PcodeOp[paramCount];
|
||||
long fromOffset = INPUT_REGISTER_START; // Base of designated input registers
|
||||
long toOffset = REGISTER_START + 4 * registerIndex; // Base of registers in method's frame
|
||||
int i = 0;
|
||||
|
@ -126,16 +141,16 @@ public class InjectPayloadDexParameters implements InjectPayload {
|
|||
Address toAddr = registerSpace.getAddress(toOffset);
|
||||
fromOffset += 4;
|
||||
toOffset += 4;
|
||||
PcodeOp op = new PcodeOp(con.baseAddr,i,PcodeOp.COPY);
|
||||
op.setInput(new Varnode(fromAddr,4), 0);
|
||||
op.setOutput(new Varnode(toAddr,4));
|
||||
PcodeOp op = new PcodeOp(con.baseAddr, i, PcodeOp.COPY);
|
||||
op.setInput(new Varnode(fromAddr, 4), 0);
|
||||
op.setOutput(new Varnode(toAddr, 4));
|
||||
resOps[i] = op;
|
||||
i += 1;
|
||||
}
|
||||
if (parameters != null) {
|
||||
for (TypeItem parameterTypeItem : parameters.getItems()) {
|
||||
String parameterTypeString = DexUtil.convertTypeIndexToString(
|
||||
header, parameterTypeItem.getType());
|
||||
String parameterTypeString =
|
||||
DexUtil.convertTypeIndexToString(header, parameterTypeItem.getType());
|
||||
int size;
|
||||
char firstChar = parameterTypeString.charAt(0);
|
||||
Address fromAddr = registerSpace.getAddress(fromOffset);
|
||||
|
@ -156,4 +171,42 @@ public class InjectPayloadDexParameters implements InjectPayload {
|
|||
public boolean isFallThru() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncidentalCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(StringBuilder buffer) {
|
||||
// Provide a minimal tag so decompiler can call-back
|
||||
buffer.append("<pcode");
|
||||
SpecXmlUtils.encodeStringAttribute(buffer, "inject", "uponentry");
|
||||
SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true);
|
||||
buffer.append("/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage language) throws XmlParseException {
|
||||
XmlElement el = parser.start();
|
||||
String injectString = el.getAttribute("inject");
|
||||
if (injectString == null || !injectString.equals("uponentry")) {
|
||||
throw new XmlParseException("Expecting inject=\"uponentry\" attribute");
|
||||
}
|
||||
boolean isDynamic = SpecXmlUtils.decodeBoolean(el.getAttribute("dynamic"));
|
||||
if (!isDynamic) {
|
||||
throw new XmlParseException("Expecting dynamic attribute");
|
||||
}
|
||||
parser.end(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof InjectPayloadDexParameters); // All instances are equal
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 123474219; // All instances are equal
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package ghidra.dalvik.dex.inject;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.PcodeEmit;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.InjectContext;
|
||||
import ghidra.program.model.lang.InjectPayload;
|
||||
import ghidra.program.model.lang.InjectPayloadCallother;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
|
@ -31,44 +30,10 @@ import ghidra.program.model.pcode.Varnode;
|
|||
* The registers are moved to the specially designated input registers iv0, iv1, iv2, ...
|
||||
*
|
||||
*/
|
||||
public class InjectPayloadDexRange implements InjectPayload {
|
||||
public class InjectPayloadDexRange extends InjectPayloadCallother {
|
||||
|
||||
public InjectPayloadDexRange() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "dexrange";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return CALLOTHERFIXUP_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "dexrange";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParamShift() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectParameter[] getInput() {
|
||||
return null; // Not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectParameter[] getOutput() {
|
||||
return null; // Not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(InjectContext context, PcodeEmit emit) {
|
||||
// not used
|
||||
super("dexrange");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,10 +61,4 @@ public class InjectPayloadDexRange implements InjectPayload {
|
|||
}
|
||||
return resOps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFallThru() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,35 +23,32 @@ import ghidra.program.model.listing.Program;
|
|||
|
||||
public class PcodeInjectLibraryDex extends PcodeInjectLibrary {
|
||||
|
||||
private InjectPayloadDexParameters paramPayload = null;
|
||||
private InjectPayloadDexRange rangePayload = null;
|
||||
|
||||
public PcodeInjectLibraryDex(SleighLanguage l) {
|
||||
super(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectPayload getPayload(int type, String name, Program program,
|
||||
String context) {
|
||||
if (type == InjectPayload.CALLMECHANISM_TYPE) {
|
||||
if (paramPayload == null) {
|
||||
paramPayload = new InjectPayloadDexParameters();
|
||||
}
|
||||
return paramPayload;
|
||||
}
|
||||
else if (type == InjectPayload.CALLOTHERFIXUP_TYPE && name.equals("moveRangeToIV")) {
|
||||
if (rangePayload == null) {
|
||||
rangePayload = new InjectPayloadDexRange();
|
||||
}
|
||||
return rangePayload;
|
||||
}
|
||||
public PcodeInjectLibraryDex(PcodeInjectLibraryDex op2) {
|
||||
super(op2);
|
||||
}
|
||||
|
||||
return super.getPayload(type, name, program, context);
|
||||
@Override
|
||||
public PcodeInjectLibrary clone() {
|
||||
return new PcodeInjectLibraryDex(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectPayload allocateInject(String sourceName, String name, int tp) {
|
||||
if (tp == InjectPayload.CALLMECHANISM_TYPE) {
|
||||
return new InjectPayloadDexParameters(name, sourceName);
|
||||
}
|
||||
else if (tp == InjectPayload.CALLOTHERFIXUP_TYPE && name.equals("moveRangeToIV")) {
|
||||
return new InjectPayloadDexRange();
|
||||
}
|
||||
return super.allocateInject(sourceName, name, tp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantPool getConstantPool(Program program) throws IOException {
|
||||
return new ConstantPoolDex(program);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectGetField extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.GETFIELD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectGetStatic extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.GETSTATIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectInvokeDynamic extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.INVOKE_DYNAMIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectInvokeInterface extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.INVOKE_INTERFACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectInvokeSpecial extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.INVOKE_SPECIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectInvokeStatic extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.INVOKE_STATIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectInvokeVirtual extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.INVOKE_VIRTUAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectLdc extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.LDC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectMultiANewArray extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.MULTIANEWARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -17,29 +17,26 @@ package ghidra.app.util.pcodeInject;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.PcodeEmit;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.javaclass.format.ClassFileAnalysisState;
|
||||
import ghidra.javaclass.format.ClassFileJava;
|
||||
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
||||
import ghidra.program.model.lang.InjectContext;
|
||||
import ghidra.program.model.lang.InjectPayload;
|
||||
import ghidra.program.model.lang.InjectPayloadCallother;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* Subclasses of this class are used to generate pcode to inject for modeling
|
||||
* java bytecode in pcode.
|
||||
* Subclasses of this class are used to generate p-code to inject for modeling
|
||||
* java bytecode in p-code. Each is attached to CALLOTHER p-code op.
|
||||
*
|
||||
*/
|
||||
|
||||
public abstract class InjectPayloadJava implements InjectPayload {
|
||||
public abstract class InjectPayloadJava extends InjectPayloadCallother {
|
||||
protected SleighLanguage language;
|
||||
protected long uniqueBase;
|
||||
private String sourceName;
|
||||
|
||||
public InjectPayloadJava(String sourceName, SleighLanguage language, long uniqBase) {
|
||||
super(sourceName);
|
||||
this.language = language;
|
||||
this.sourceName = sourceName;
|
||||
this.uniqueBase = uniqBase;
|
||||
}
|
||||
|
||||
|
@ -54,39 +51,4 @@ public abstract class InjectPayloadJava implements InjectPayload {
|
|||
ClassFileJava classFile = analysisState.getClassFile();
|
||||
return classFile.getConstantPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return InjectPayload.CALLOTHERFIXUP_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParamShift() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(InjectContext context, PcodeEmit emit) {
|
||||
// Not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFallThru() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectParameter[] getInput() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InjectParameter[] getOutput() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,13 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.*;
|
||||
|
||||
public class InjectPayloadJavaParameters implements InjectPayload {
|
||||
|
||||
private String name;
|
||||
private String sourceName;
|
||||
private InjectParameter[] noParams;
|
||||
private boolean analysisStateRecoverable;
|
||||
private AddressSpace constantSpace;
|
||||
|
@ -46,7 +50,10 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
private Varnode eight;
|
||||
private Varnode LVA;
|
||||
|
||||
public InjectPayloadJavaParameters(SleighLanguage language, long uniqBase) {
|
||||
public InjectPayloadJavaParameters(String nm, String srcName, SleighLanguage language,
|
||||
long uniqBase) {
|
||||
name = nm;
|
||||
sourceName = srcName;
|
||||
noParams = new InjectParameter[0];
|
||||
analysisStateRecoverable = true;
|
||||
constantSpace = language.getAddressFactory().getConstantSpace();
|
||||
|
@ -70,7 +77,7 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "javaparameters";
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +87,7 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return "javaparameters";
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,6 +105,11 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
return noParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorPlaceholder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(InjectContext context, PcodeEmit emit) {
|
||||
//not used
|
||||
|
@ -119,29 +131,30 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
}
|
||||
ClassFileJava classFile = analysisState.getClassFile();
|
||||
MethodInfoJava methodInfo = analysisState.getMethodInfo(con.baseAddr);
|
||||
if (methodInfo == null){
|
||||
if (methodInfo == null) {
|
||||
return new PcodeOp[0];
|
||||
}
|
||||
int descriptorIndex = methodInfo.getDescriptorIndex();
|
||||
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info)(classFile.getConstantPool()[descriptorIndex]);
|
||||
ConstantPoolUtf8Info descriptorInfo =
|
||||
(ConstantPoolUtf8Info) (classFile.getConstantPool()[descriptorIndex]);
|
||||
String descriptor = descriptorInfo.getString();
|
||||
List<JavaComputationalCategory> paramCategories = new ArrayList<>();
|
||||
if (!methodInfo.isStatic()){
|
||||
if (!methodInfo.isStatic()) {
|
||||
paramCategories.add(JavaComputationalCategory.CAT_1);//for the this pointer
|
||||
}
|
||||
paramCategories.addAll(DescriptorDecoder.getParameterCategories(descriptor));
|
||||
int numOps = paramCategories.size();
|
||||
|
||||
if (paramCategories.size() == 0){
|
||||
if (paramCategories.size() == 0) {
|
||||
//no this pointer, no parameters: nothing to do
|
||||
return new PcodeOp[0];
|
||||
}
|
||||
|
||||
PcodeOp[] resOps = new PcodeOp[1 + 3*numOps];
|
||||
PcodeOp[] resOps = new PcodeOp[1 + 3 * numOps];
|
||||
int seqNum = 0;
|
||||
|
||||
//initialize LVA to contain 0
|
||||
PcodeOp copy = new PcodeOp(con.baseAddr,seqNum, PcodeOp.COPY);
|
||||
PcodeOp copy = new PcodeOp(con.baseAddr, seqNum, PcodeOp.COPY);
|
||||
copy.setInput(zero, 0);
|
||||
copy.setOutput(LVA);
|
||||
resOps[seqNum++] = copy;
|
||||
|
@ -149,8 +162,8 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
Varnode tempLocation = null;
|
||||
Varnode increment = null;
|
||||
|
||||
for (JavaComputationalCategory cat : paramCategories){
|
||||
if (cat.equals(JavaComputationalCategory.CAT_1)){
|
||||
for (JavaComputationalCategory cat : paramCategories) {
|
||||
if (cat.equals(JavaComputationalCategory.CAT_1)) {
|
||||
tempLocation = temp4;
|
||||
increment = four;
|
||||
}
|
||||
|
@ -167,16 +180,16 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
//copy temporary to LVA
|
||||
PcodeOp store = new PcodeOp(con.baseAddr, seqNum, PcodeOp.STORE);
|
||||
store.setInput(new Varnode(constantSpace.getAddress(lvaID), 4), 0);
|
||||
store.setInput(LVA,1);
|
||||
store.setInput(LVA, 1);
|
||||
store.setInput(tempLocation, 2);
|
||||
resOps[seqNum++] = store;
|
||||
resOps[seqNum++] = store;
|
||||
//increment LVA reg
|
||||
PcodeOp add = new PcodeOp(con.baseAddr, seqNum, PcodeOp.INT_ADD);
|
||||
add.setInput(LVA, 0);
|
||||
add.setInput(increment, 1);
|
||||
add.setOutput(LVA);
|
||||
resOps[seqNum++] = add;
|
||||
}
|
||||
resOps[seqNum++] = add;
|
||||
}
|
||||
return resOps;
|
||||
}
|
||||
|
||||
|
@ -184,4 +197,42 @@ public class InjectPayloadJavaParameters implements InjectPayload {
|
|||
public boolean isFallThru() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncidentalCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(StringBuilder buffer) {
|
||||
// Provide a minimal tag so decompiler can call-back
|
||||
buffer.append("<pcode");
|
||||
SpecXmlUtils.encodeStringAttribute(buffer, "inject", "uponentry");
|
||||
SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true);
|
||||
buffer.append("/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage language) throws XmlParseException {
|
||||
XmlElement el = parser.start();
|
||||
String injectString = el.getAttribute("inject");
|
||||
if (injectString == null || !injectString.equals("uponentry")) {
|
||||
throw new XmlParseException("Expecting inject=\"uponentry\" attribute");
|
||||
}
|
||||
boolean isDynamic = SpecXmlUtils.decodeBoolean(el.getAttribute("dynamic"));
|
||||
if (!isDynamic) {
|
||||
throw new XmlParseException("Expecting dynamic attribute");
|
||||
}
|
||||
parser.end(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof InjectPayloadJavaParameters); // All instances are equal
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 123474217; // All instances are equal
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectPutField extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.PUTFIELD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -27,11 +27,6 @@ public class InjectPutStatic extends InjectPayloadJava {
|
|||
super(sourceName, language, uniqBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PcodeInjectLibraryJava.PUTSTATIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(Program program, InjectContext con) {
|
||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||
|
|
|
@ -116,56 +116,60 @@ public class PcodeInjectLibraryJava extends PcodeInjectLibrary {
|
|||
public static final int REFERENCE_SIZE = 4;
|
||||
|
||||
private Map<String, InjectPayloadJava> implementedOps;
|
||||
private InjectPayloadJavaParameters paramPayload;
|
||||
|
||||
public PcodeInjectLibraryJava(SleighLanguage l) {
|
||||
super(l);
|
||||
long offset = l.getUniqueBase();
|
||||
implementedOps = new HashMap<>();
|
||||
implementedOps.put(GETFIELD, new InjectGetField(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(GETSTATIC, new InjectGetStatic(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(INVOKE_DYNAMIC, new InjectInvokeDynamic(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(INVOKE_INTERFACE, new InjectInvokeInterface(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(INVOKE_SPECIAL, new InjectInvokeSpecial(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(INVOKE_STATIC, new InjectInvokeStatic(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(INVOKE_VIRTUAL, new InjectInvokeVirtual(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
InjectPayloadJava ldcInject = new InjectLdc(SOURCENAME, l, offset);
|
||||
offset += 0x100;
|
||||
implementedOps.put(LDC, ldcInject);
|
||||
implementedOps.put(LDC2_W, ldcInject);
|
||||
implementedOps.put(LDC_W, ldcInject);
|
||||
implementedOps.put(MULTIANEWARRAY, new InjectMultiANewArray(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(PUTFIELD, new InjectPutField(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(PUTSTATIC, new InjectPutStatic(SOURCENAME, l, offset));
|
||||
offset += 0x100;
|
||||
implementedOps.put(GETFIELD, new InjectGetField(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(GETSTATIC, new InjectGetStatic(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(INVOKE_DYNAMIC, new InjectInvokeDynamic(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(INVOKE_INTERFACE, new InjectInvokeInterface(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(INVOKE_SPECIAL, new InjectInvokeSpecial(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(INVOKE_STATIC, new InjectInvokeStatic(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(INVOKE_VIRTUAL, new InjectInvokeVirtual(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(LDC, new InjectLdc(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(LDC2_W, new InjectLdc(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(LDC_W, new InjectLdc(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(MULTIANEWARRAY, new InjectMultiANewArray(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(PUTFIELD, new InjectPutField(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
implementedOps.put(PUTSTATIC, new InjectPutStatic(SOURCENAME, l, uniqueBase));
|
||||
uniqueBase += 0x100;
|
||||
}
|
||||
|
||||
paramPayload = new InjectPayloadJavaParameters(l, offset);
|
||||
public PcodeInjectLibraryJava(PcodeInjectLibraryJava op2) {
|
||||
super(op2);
|
||||
implementedOps = op2.implementedOps; // Immutable
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* This method is called by DecompileCallback.getPcodeInject.
|
||||
*/
|
||||
public InjectPayload getPayload(int type, String name, Program program, String context) {
|
||||
if (type == InjectPayload.CALLMECHANISM_TYPE) {
|
||||
return paramPayload;
|
||||
}
|
||||
public PcodeInjectLibrary clone() {
|
||||
return new PcodeInjectLibraryJava(this);
|
||||
}
|
||||
|
||||
InjectPayloadJava payload = implementedOps.get(name);
|
||||
if (payload == null) {
|
||||
return super.getPayload(type, name, program, context);
|
||||
@Override
|
||||
public InjectPayload allocateInject(String sourceName, String name, int tp) {
|
||||
if (tp == InjectPayload.CALLMECHANISM_TYPE) {
|
||||
return new InjectPayloadJavaParameters(name, sourceName, language, tp);
|
||||
}
|
||||
|
||||
return payload;
|
||||
if (tp == InjectPayload.CALLOTHERFIXUP_TYPE) {
|
||||
InjectPayloadJava payload = implementedOps.get(name);
|
||||
if (payload != null) {
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
return super.allocateInject(sourceName, name, tp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,10 +36,10 @@ import ghidra.javaclass.flags.MethodsInfoAccessFlags;
|
|||
import ghidra.javaclass.format.*;
|
||||
import ghidra.javaclass.format.attributes.*;
|
||||
import ghidra.javaclass.format.constantpool.*;
|
||||
import ghidra.program.database.ProgramCompilerSpec;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.listing.Function.FunctionUpdateType;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
@ -138,7 +138,7 @@ public class JavaAnalyzer extends AbstractJavaAnalyzer implements AnalysisWorker
|
|||
disassembleMethods(program, classFile, monitor);
|
||||
processInstructions(program, constantPoolData, classFile, monitor);
|
||||
recordJavaVersionInfo(program, classFile);
|
||||
BasicCompilerSpec.enableJavaLanguageDecompilation(program);
|
||||
ProgramCompilerSpec.enableJavaLanguageDecompilation(program);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue