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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue