Removed getCallStackShift() and getCallStackMod() from CompilerSpec

This commit is contained in:
caheckman 2019-08-20 15:31:01 -04:00
parent 5944383088
commit 539ed98e74
10 changed files with 157 additions and 126 deletions

View file

@ -273,8 +273,7 @@ public class CallDepthChangeInfo {
PcodeOp[] pcode = instr.getPcode(); PcodeOp[] pcode = instr.getPcode();
Varnode outVarNode = null; Varnode outVarNode = null;
for (int i = 0; i < pcode.length; i++) { for (PcodeOp op : pcode) {
PcodeOp op = pcode[i];
Varnode input0 = op.getInput(0); Varnode input0 = op.getInput(0);
Varnode input1 = op.getInput(1); Varnode input1 = op.getInput(1);
Varnode output = op.getOutput(); Varnode output = op.getOutput();
@ -317,9 +316,10 @@ public class CallDepthChangeInfo {
break; break;
case PcodeOp.INT_AND: // Assume this is a stack alignment and do the and case PcodeOp.INT_AND: // Assume this is a stack alignment and do the and
if (isStackPointer(input0)) { if (isStackPointer(input0)) {
if (currentStackDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE) if (currentStackDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE) {
possibleDepthChange = possibleDepthChange =
(int) (currentStackDepth & input1.getOffset()) - currentStackDepth; (int) (currentStackDepth & input1.getOffset()) - currentStackDepth;
}
outVarNode = output; outVarNode = output;
} }
else if (input0.equals(outVarNode)) { else if (input0.equals(outVarNode)) {
@ -327,9 +327,10 @@ public class CallDepthChangeInfo {
outVarNode = output; outVarNode = output;
} }
else if (isStackPointer(input1)) { else if (isStackPointer(input1)) {
if (currentStackDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE) if (currentStackDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE) {
possibleDepthChange = possibleDepthChange =
(int) (currentStackDepth & input0.getOffset()) - currentStackDepth; (int) (currentStackDepth & input0.getOffset()) - currentStackDepth;
}
outVarNode = output; outVarNode = output;
} }
else if (input1.equals(outVarNode)) { else if (input1.equals(outVarNode)) {
@ -385,7 +386,7 @@ public class CallDepthChangeInfo {
// TODO: Modify return by normal stack shift.... // TODO: Modify return by normal stack shift....
if (flowType.isTerminal()) { if (flowType.isTerminal()) {
depthChange -= program.getCompilerSpec().getCallStackShift(); depthChange -= program.getCompilerSpec().getDefaultCallingConvention().getStackshift();
} }
// if the current stack depth is still bad, don't return a depth change. // if the current stack depth is still bad, don't return a depth change.
@ -419,8 +420,9 @@ public class CallDepthChangeInfo {
* @return * @return
*/ */
private int getDefaultStackDepthChange(int depth) { private int getDefaultStackDepthChange(int depth) {
int callStackMod = program.getCompilerSpec().getCallStackMod(); PrototypeModel defaultModel = program.getCompilerSpec().getDefaultCallingConvention();
int callStackShift = program.getCompilerSpec().getCallStackShift(); int callStackMod = defaultModel.getExtrapop();
int callStackShift = defaultModel.getStackshift();
if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP && callStackShift >= 0) { if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP && callStackShift >= 0) {
return callStackShift - callStackMod; return callStackShift - callStackMod;
} }
@ -578,8 +580,8 @@ public class CallDepthChangeInfo {
FlowType flow = instr.getFlowType(); FlowType flow = instr.getFlowType();
if (!flow.isCall()) { if (!flow.isCall()) {
Address[] flows = instr.getFlows(); Address[] flows = instr.getFlows();
for (int i = 0; i < flows.length; i++) { for (Address flow2 : flows) {
st.push(flows[i]); st.push(flow2);
st.push(new Integer(stackPointerDepth)); st.push(new Integer(stackPointerDepth));
st.push(stackOK); st.push(stackOK);
} }
@ -653,7 +655,7 @@ public class CallDepthChangeInfo {
return; return;
} }
int purge = (short) program.getCompilerSpec().getCallStackMod(); int purge = (short) program.getCompilerSpec().getDefaultCallingConvention().getExtrapop();
final boolean possiblePurge = purge == -1 || purge > 3200 || purge < -3200; final boolean possiblePurge = purge == -1 || purge > 3200 || purge < -3200;
// follow all flows building up context // follow all flows building up context
@ -948,8 +950,8 @@ public class CallDepthChangeInfo {
FlowType flow = instr.getFlowType(); FlowType flow = instr.getFlowType();
if (!flow.isCall()) { if (!flow.isCall()) {
Address[] flows = instr.getFlows(); Address[] flows = instr.getFlows();
for (int i = 0; i < flows.length; i++) { for (Address flow2 : flows) {
st.push(flows[i]); st.push(flow2);
st.push(new Integer(stackPointerDepth)); st.push(new Integer(stackPointerDepth));
st.push(stackOK); st.push(stackOK);
} }
@ -1027,11 +1029,11 @@ public class CallDepthChangeInfo {
} }
// try to find a call destination that the stack frame is known // try to find a call destination that the stack frame is known
for (int i = 0; i < flows.length; i++) { for (Address flow : flows) {
if (flows[i] == null) { if (flow == null) {
continue; continue;
} }
Function func = program.getListing().getFunctionAt(flows[i]); Function func = program.getListing().getFunctionAt(flow);
if (func != null) { if (func != null) {
int purge = func.getStackPurgeSize(); int purge = func.getStackPurgeSize();
if (func.isStackPurgeSizeValid() && purge != Function.UNKNOWN_STACK_DEPTH_CHANGE && if (func.isStackPurgeSizeValid() && purge != Function.UNKNOWN_STACK_DEPTH_CHANGE &&

View file

@ -169,8 +169,9 @@ public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand {
// Process all the functions identified as needing stack analysis. // Process all the functions identified as needing stack analysis.
// The list will have the lowest level functions analyzed first. // The list will have the lowest level functions analyzed first.
int default_extraPop = program.getCompilerSpec().getCallStackMod(); PrototypeModel defaultModel = program.getCompilerSpec().getDefaultCallingConvention();
int default_stackshift = program.getCompilerSpec().getCallStackShift(); int default_extraPop = defaultModel.getExtrapop();
int default_stackshift = defaultModel.getStackshift();
while (!funcList.isEmpty()) { while (!funcList.isEmpty()) {
monitor.checkCanceled(); monitor.checkCanceled();
@ -256,19 +257,22 @@ public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand {
int storageSpaceID, RefType refType, TaskMonitor monitor1) int storageSpaceID, RefType refType, TaskMonitor monitor1)
throws CancelledException { throws CancelledException {
if (instrOpIndex < 0) if (instrOpIndex < 0) {
return; return;
}
Address fromAddr = op.getSeqnum().getTarget(); Address fromAddr = op.getSeqnum().getTarget();
Instruction instr = listing.getInstructionAt(fromAddr); Instruction instr = listing.getInstructionAt(fromAddr);
if (instr == null) if (instr == null) {
return; return;
}
Address stackAddr = addrFactory.getStackSpace().getAddress(stackOffset); Address stackAddr = addrFactory.getStackSpace().getAddress(stackOffset);
RefType rt = refType; RefType rt = refType;
Reference ref = refMgr.getReference(fromAddr, stackAddr, instrOpIndex); Reference ref = refMgr.getReference(fromAddr, stackAddr, instrOpIndex);
if (ref != null) { if (ref != null) {
RefType existingRefType = ref.getReferenceType(); RefType existingRefType = ref.getReferenceType();
if (existingRefType == rt) if (existingRefType == rt) {
return; return;
}
if (existingRefType == RefType.READ || existingRefType == RefType.WRITE) { if (existingRefType == RefType.READ || existingRefType == RefType.WRITE) {
rt = RefType.READ_WRITE; rt = RefType.READ_WRITE;
} }

View file

@ -892,14 +892,14 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
if (expSym.hasNoReturn()) { if (expSym.hasNoReturn()) {
extFunc.setNoReturn(true); extFunc.setNoReturn(true);
} }
int stackShift = program.getCompilerSpec().getCallStackShift(); // TODO: This should not be done at time of import and should be done
if (stackShift == -1) { // by a late running analyzer (e.g., stack analyzer) if no signature
stackShift = 0; // has been established
} // int stackShift = program.getCompilerSpec().getDefaultCallingConvention().getStackshift();
// if (stackShift == -1) {
// stackShift = 0;
// }
// TODO: This should not be done at time of import and should be done
// by a late running analyzer (e.g., stack analyzer) if no signature
// has been established
// int numParams = expSym.getPurge() / 4; // int numParams = expSym.getPurge() / 4;
// if (numParams > 0) { // if (numParams > 0) {
// // HACK: assumes specific stack-based x86 convention // // HACK: assumes specific stack-based x86 convention

View file

@ -1705,8 +1705,9 @@ public class SymbolicPropogator {
* @return * @return
*/ */
private int getDefaultStackDepthChange(Program prog, int depth) { private int getDefaultStackDepthChange(Program prog, int depth) {
int callStackMod = prog.getCompilerSpec().getCallStackMod(); PrototypeModel defaultModel = prog.getCompilerSpec().getDefaultCallingConvention();
int callStackShift = prog.getCompilerSpec().getCallStackShift(); int callStackMod = defaultModel.getExtrapop();
int callStackShift = defaultModel.getStackshift();
if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP) { if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP) {
return callStackShift; return callStackShift;
} }

View file

@ -46,14 +46,17 @@ public class ResultsState {
private static final Iterator<ContextState> emptyContextStateIterator = private static final Iterator<ContextState> emptyContextStateIterator =
new Iterator<ContextState>() { new Iterator<ContextState>() {
@Override
public boolean hasNext() { public boolean hasNext() {
return false; return false;
} }
@Override
public ContextState next() { public ContextState next() {
return null; return null;
} }
@Override
public void remove() { public void remove() {
} }
}; };
@ -168,10 +171,12 @@ public class ResultsState {
stackGrowsNegative = program.getCompilerSpec().stackGrowsNegative(); stackGrowsNegative = program.getCompilerSpec().stackGrowsNegative();
Long stackOffset = currentPrototype.getStackParameterOffset(); Long stackOffset = currentPrototype.getStackParameterOffset();
if (stackOffset != null) if (stackOffset != null) {
paramBaseStackOffset = stackOffset - currentPrototype.getStackshift(); paramBaseStackOffset = stackOffset - currentPrototype.getStackshift();
else }
else {
paramBaseStackOffset = null; paramBaseStackOffset = null;
}
todoList.add(new BranchDestination(null, entryPt, entryState)); todoList.add(new BranchDestination(null, entryPt, entryState));
} }
@ -253,9 +258,10 @@ public class ResultsState {
currentState = null; currentState = null;
} }
if (DEBUG) if (DEBUG) {
Msg.debug(this, ">>> At " + nextSeq.getTarget() + "/" + nextSeq.getTime() + Msg.debug(this, ">>> At " + nextSeq.getTarget() + "/" + nextSeq.getTime() +
" " + instr); " " + instr);
}
SequenceNumber lastSeq = flowFrom; SequenceNumber lastSeq = flowFrom;
@ -272,9 +278,10 @@ public class ResultsState {
if (existingStates.containsKey(flowFrom)) { if (existingStates.containsKey(flowFrom)) {
// TODO: We have processed this flow before // TODO: We have processed this flow before
// TODO: Should we compare existingState with dest.initialState ? // TODO: Should we compare existingState with dest.initialState ?
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Flow ignored - already processed: " + Msg.debug(this, "Flow ignored - already processed: " +
flowFrom + " -> " + pcodeOp.getSeqnum()); flowFrom + " -> " + pcodeOp.getSeqnum());
}
instr = null; // signal - abort current flow instr = null; // signal - abort current flow
break; break;
} }
@ -284,9 +291,10 @@ public class ResultsState {
// Re-use existing state where register values match // Re-use existing state where register values match
addState(flowFrom, otherEntryState); addState(flowFrom, otherEntryState);
instr = null; // signal - abort current flow instr = null; // signal - abort current flow
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Flow combined - similar state: " + Msg.debug(this, "Flow combined - similar state: " +
flowFrom + " -> " + pcodeOp.getSeqnum()); flowFrom + " -> " + pcodeOp.getSeqnum());
}
break; break;
} }
} }
@ -385,6 +393,7 @@ public class ResultsState {
private static Comparator<Object> CONTEXT_STATE_SET_SEQUENCE_COMPARATOR = private static Comparator<Object> CONTEXT_STATE_SET_SEQUENCE_COMPARATOR =
new Comparator<Object>() { new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) { public int compare(Object o1, Object o2) {
ContextStateSet set = (ContextStateSet) o1; ContextStateSet set = (ContextStateSet) o1;
SequenceNumber seq = (SequenceNumber) o2; SequenceNumber seq = (SequenceNumber) o2;
@ -468,14 +477,16 @@ public class ResultsState {
private ContextState performInlineCall(Address inlineCallAddress, ContextState currentState, private ContextState performInlineCall(Address inlineCallAddress, ContextState currentState,
TaskMonitor monitor) throws CancelledException { TaskMonitor monitor) throws CancelledException {
if (DEBUG) if (DEBUG) {
Msg.debug(this, "*** Start Inline Call to " + inlineCallAddress + " ***"); Msg.debug(this, "*** Start Inline Call to " + inlineCallAddress + " ***");
}
ResultsState inlineState = ResultsState inlineState =
new ResultsState(new SequenceNumber(inlineCallAddress, 0), null, currentState, new ResultsState(new SequenceNumber(inlineCallAddress, 0), null, currentState,
maintainInstructionResults); maintainInstructionResults);
inlineState.processFunction(monitor); inlineState.processFunction(monitor);
if (DEBUG) if (DEBUG) {
Msg.debug(this, "*** End Inline Call to " + inlineCallAddress + " ***"); Msg.debug(this, "*** End Inline Call to " + inlineCallAddress + " ***");
}
// TODO: How should multiple return states be handled ?? // TODO: How should multiple return states be handled ??
@ -746,9 +757,10 @@ public class ResultsState {
if (values[1].isConstant() && values[1].getOffset() == 0) { if (values[1].isConstant() && values[1].getOffset() == 0) {
// TODO: This is a problem, since branch case may never be evaluated! // TODO: This is a problem, since branch case may never be evaluated!
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Conditional Branch to " + inputs[0].getAddress() + Msg.debug(this, "Conditional Branch to " + inputs[0].getAddress() +
" - Not taken due to false condition value"); " - Not taken due to false condition value");
}
break; // Fall-through case - assume that a pre-condition is steering the execution break; // Fall-through case - assume that a pre-condition is steering the execution
} }
@ -762,16 +774,18 @@ public class ResultsState {
SequenceNumber dest = SequenceNumber dest =
new SequenceNumber(seq.getTarget(), seq.getTime() + new SequenceNumber(seq.getTarget(), seq.getTime() +
(int) inputs[0].getOffset()); (int) inputs[0].getOffset());
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Internal " + Msg.debug(this, "Internal " +
(pcodeOp.getOpcode() == PcodeOp.CBRANCH ? "Conditional " : "") + (pcodeOp.getOpcode() == PcodeOp.CBRANCH ? "Conditional " : "") +
"Branch to " + dest); "Branch to " + dest);
}
todoList.add(new BranchDestination(pcodeOp.getSeqnum(), dest, currentState)); todoList.add(new BranchDestination(pcodeOp.getSeqnum(), dest, currentState));
} }
else if (inputs[0].isAddress()) { else if (inputs[0].isAddress()) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, (pcodeOp.getOpcode() == PcodeOp.CBRANCH ? "Conditional " Msg.debug(this, (pcodeOp.getOpcode() == PcodeOp.CBRANCH ? "Conditional "
: "") + "Branch to " + inputs[0].getAddress()); : "") + "Branch to " + inputs[0].getAddress());
}
handleDirectFlow(pcodeOp, inputs[0].getAddress(), currentState, monitor); handleDirectFlow(pcodeOp, inputs[0].getAddress(), currentState, monitor);
} }
else { else {
@ -786,8 +800,9 @@ public class ResultsState {
AddressSpace space = currentState.getEntryPoint().getTarget().getAddressSpace(); AddressSpace space = currentState.getEntryPoint().getTarget().getAddressSpace();
Address destAddr = Address destAddr =
space.getAddress(getUnsignedOffset(values[0], space.getPointerSize())); space.getAddress(getUnsignedOffset(values[0], space.getPointerSize()));
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Branch to " + destAddr); Msg.debug(this, "Branch to " + destAddr);
}
handleDirectFlow(pcodeOp, destAddr, currentState, monitor); handleDirectFlow(pcodeOp, destAddr, currentState, monitor);
} }
else if (values[0].isAddress()) { else if (values[0].isAddress()) {
@ -798,32 +813,36 @@ public class ResultsState {
currentState.getEntryPoint().getTarget().getAddressSpace(); currentState.getEntryPoint().getTarget().getAddressSpace();
Address destAddr = Address destAddr =
space.getAddress(getUnsignedOffset(brOffset, space.getPointerSize())); space.getAddress(getUnsignedOffset(brOffset, space.getPointerSize()));
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Indirect Branch to [" + values[0].getAddress() + Msg.debug(this, "Indirect Branch to [" + values[0].getAddress() +
"] -> " + destAddr); "] -> " + destAddr);
}
handleDirectFlow(pcodeOp, destAddr, currentState, monitor); handleDirectFlow(pcodeOp, destAddr, currentState, monitor);
} }
else { else {
if (DEBUG) if (DEBUG) {
Msg.debug(this, Msg.debug(this,
"Indirect Branch to [" + values[0].toString(program.getLanguage()) + "Indirect Branch to [" + values[0].toString(program.getLanguage()) +
"]"); "]");
}
handleIndirectFlow(pcodeOp, values[0], currentState, monitor); handleIndirectFlow(pcodeOp, values[0], currentState, monitor);
} }
} }
else { else {
if (DEBUG) if (DEBUG) {
Msg.debug(this, Msg.debug(this,
"Indirect Branch to [" + values[0].toString(program.getLanguage()) + "Indirect Branch to [" + values[0].toString(program.getLanguage()) +
"]"); "]");
}
handleIndirectFlow(pcodeOp, values[0], currentState, monitor); handleIndirectFlow(pcodeOp, values[0], currentState, monitor);
} }
return false; return false;
case PcodeOp.CALL: // A call with absolute address case PcodeOp.CALL: // A call with absolute address
if (inputs[0].isAddress()) { if (inputs[0].isAddress()) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Call to " + inputs[0].getAddress()); Msg.debug(this, "Call to " + inputs[0].getAddress());
}
handleCall(pcodeOp, null, inputs[0].getAddress(), currentState, monitor); handleCall(pcodeOp, null, inputs[0].getAddress(), currentState, monitor);
} }
else { else {
@ -839,8 +858,9 @@ public class ResultsState {
AddressSpace space = currentState.getEntryPoint().getTarget().getAddressSpace(); AddressSpace space = currentState.getEntryPoint().getTarget().getAddressSpace();
Address destAddr = Address destAddr =
space.getAddress(getUnsignedOffset(values[0], space.getPointerSize())); space.getAddress(getUnsignedOffset(values[0], space.getPointerSize()));
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Call to " + destAddr); Msg.debug(this, "Call to " + destAddr);
}
handleCall(pcodeOp, indirectPtr, destAddr, currentState, monitor); handleCall(pcodeOp, indirectPtr, destAddr, currentState, monitor);
} }
else if (values[0].isAddress()) { else if (values[0].isAddress()) {
@ -852,23 +872,26 @@ public class ResultsState {
currentState.getEntryPoint().getTarget().getAddressSpace(); currentState.getEntryPoint().getTarget().getAddressSpace();
Address destAddr = Address destAddr =
space.getAddress(getUnsignedOffset(callOffset, space.getPointerSize())); space.getAddress(getUnsignedOffset(callOffset, space.getPointerSize()));
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Indirect Call to [" + values[0].getAddress() + Msg.debug(this, "Indirect Call to [" + values[0].getAddress() +
"] -> " + destAddr); "] -> " + destAddr);
}
handleCall(pcodeOp, indirectPtr, destAddr, currentState, monitor); handleCall(pcodeOp, indirectPtr, destAddr, currentState, monitor);
} }
else { else {
if (DEBUG) if (DEBUG) {
Msg.debug(this, Msg.debug(this,
"Indirect Call to [" + values[0].toString(program.getLanguage()) + "Indirect Call to [" + values[0].toString(program.getLanguage()) +
"]"); "]");
}
handleIndirectCall(pcodeOp, indirectPtr, values[0], currentState, monitor); handleIndirectCall(pcodeOp, indirectPtr, values[0], currentState, monitor);
} }
} }
else { else {
if (DEBUG) if (DEBUG) {
Msg.debug(this, Msg.debug(this,
"Indirect Call to [" + values[0].toString(program.getLanguage()) + "]"); "Indirect Call to [" + values[0].toString(program.getLanguage()) + "]");
}
handleIndirectCall(pcodeOp, indirectPtr, values[0], currentState, monitor); handleIndirectCall(pcodeOp, indirectPtr, values[0], currentState, monitor);
} }
return false; return false;
@ -1737,8 +1760,9 @@ public class ResultsState {
BookmarkType.ERROR, "Instruction Expected", "Expected instruction at " + address); BookmarkType.ERROR, "Instruction Expected", "Expected instruction at " + address);
return; return;
} }
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Disassemble at " + address); Msg.debug(this, "Disassemble at " + address);
}
DisassembleCommand cmd = new DisassembleCommand(address, null, true); DisassembleCommand cmd = new DisassembleCommand(address, null, true);
cmd.applyTo(program, monitor); cmd.applyTo(program, monitor);
monitor.checkCanceled(); monitor.checkCanceled();
@ -1772,8 +1796,9 @@ public class ResultsState {
return; return;
} }
if (addRegister(reg, registersModified)) { if (addRegister(reg, registersModified)) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, "MODIFIED: " + reg + " = " + value); Msg.debug(this, "MODIFIED: " + reg + " = " + value);
}
} }
else { else {
Msg.debug(this, "SET: " + output + " = " + value); Msg.debug(this, "SET: " + output + " = " + value);
@ -2068,10 +2093,11 @@ public class ResultsState {
} }
if (func == null) { if (func == null) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Function not found at " + indirectPtr + Msg.debug(this, "Function not found at " + indirectPtr +
" indirectly called from " + pcodeOp.getSeqnum().getTarget() + " indirectly called from " + pcodeOp.getSeqnum().getTarget() +
" - call affects unknown"); " - call affects unknown");
}
return; return;
} }
@ -2104,9 +2130,10 @@ public class ResultsState {
} }
if (func == null) { if (func == null) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Function not found at " + destAddr + " called from " + Msg.debug(this, "Function not found at " + destAddr + " called from " +
pcodeOp.getSeqnum().getTarget() + " - call affects unknown"); pcodeOp.getSeqnum().getTarget() + " - call affects unknown");
}
return; return;
} }
@ -2133,10 +2160,11 @@ public class ResultsState {
// Must invalidate return varnode // Must invalidate return varnode
DataType returnType = null; DataType returnType = null;
if (func == null) { if (func == null) {
if (DEBUG) if (DEBUG) {
Msg.debug(this, Msg.debug(this,
"No function at " + destAddr + " called from " + calledFrom.getTarget() + "No function at " + destAddr + " called from " + calledFrom.getTarget() +
" - default return/affects assumed"); " - default return/affects assumed");
}
} }
else { else {
returnType = func.getReturnType(); returnType = func.getReturnType();
@ -2147,8 +2175,9 @@ public class ResultsState {
VariableStorage retStorage = callingConvention.getReturnLocation(returnType, program); VariableStorage retStorage = callingConvention.getReturnLocation(returnType, program);
Varnode varnode = null; Varnode varnode = null;
if (retStorage.isValid() && (retStorage.getVarnodeCount()==1)) if (retStorage.isValid() && (retStorage.getVarnodeCount()==1)) {
varnode = retStorage.getFirstVarnode(); varnode = retStorage.getFirstVarnode();
}
if (varnode != null) { if (varnode != null) {
// invalidate stored value // invalidate stored value
currentState.store(varnode, getInvalidatedVarnode(calledFrom, varnode)); currentState.store(varnode, getInvalidatedVarnode(calledFrom, varnode));
@ -2183,9 +2212,10 @@ public class ResultsState {
if (purge == Function.UNKNOWN_STACK_DEPTH_CHANGE || if (purge == Function.UNKNOWN_STACK_DEPTH_CHANGE ||
purge == Function.INVALID_STACK_DEPTH_CHANGE) { purge == Function.INVALID_STACK_DEPTH_CHANGE) {
String name = func != null ? func.getName() : ("at " + destAddr); String name = func != null ? func.getName() : ("at " + destAddr);
if (DEBUG) if (DEBUG) {
Msg.debug(this, "Stack purge unknown for function " + name + " called from " + Msg.debug(this, "Stack purge unknown for function " + name + " called from " +
calledFrom.getTarget() + " - stack pointer invalidated"); calledFrom.getTarget() + " - stack pointer invalidated");
}
currentState.store(getStackPointerVarnode(), currentState.store(getStackPointerVarnode(),
getInvalidatedVarnode(calledFrom, getStackPointerVarnode())); getInvalidatedVarnode(calledFrom, getStackPointerVarnode()));
return; return;
@ -2255,8 +2285,9 @@ public class ResultsState {
* @return * @return
*/ */
private static int getDefaultStackDepthChange(Program depthProgram, int depth) { private static int getDefaultStackDepthChange(Program depthProgram, int depth) {
int callStackMod = depthProgram.getCompilerSpec().getCallStackMod(); PrototypeModel defaultModel = depthProgram.getCompilerSpec().getDefaultCallingConvention();
int callStackShift = depthProgram.getCompilerSpec().getCallStackShift(); int callStackMod = defaultModel.getExtrapop();
int callStackShift = defaultModel.getStackshift();
if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP && callStackShift >= 0) { if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP && callStackShift >= 0) {
return callStackShift - callStackMod; return callStackShift - callStackMod;
} }

View file

@ -80,7 +80,7 @@ public class DecompileCallback {
listing = program.getListing(); listing = program.getListing();
addrfactory = program.getAddressFactory(); addrfactory = program.getAddressFactory();
dtmanage = dt; dtmanage = dt;
default_extrapop = pcodecompilerspec.getCallStackMod(); default_extrapop = pcodecompilerspec.getDefaultCallingConvention().getExtrapop();
cpool = null; cpool = null;
nativeMessage = null; nativeMessage = null;
debug = null; debug = null;

View file

@ -254,16 +254,6 @@ public class BasicCompilerSpec implements CompilerSpec {
ctxsetting.add(new ContextSetting(reg, value, begad, endad)); ctxsetting.add(new ContextSetting(reg, value, begad, endad));
} }
@Override
public int getCallStackMod() {
return defaultModel.getExtrapop();
}
@Override
public int getCallStackShift() {
return defaultModel.getStackshift();
}
@Override @Override
public PrototypeModel[] getCallingConventions() { public PrototypeModel[] getCallingConventions() {
return models; return models;

View file

@ -89,22 +89,6 @@ public interface CompilerSpec {
*/ */
public AddressSpace getStackBaseSpace(); public AddressSpace getStackBaseSpace();
/**
* Number of extra bytes popped from the stack on return
* -1 if it is unknown.
* @return # of bytes popped from the stack by a called function on return.
*/
public int getCallStackMod();
/**
* Get the normal shift in the stack at the call to this routine.
* This will be the things pushed on the stack as part of the calling
* conventions. Normally the return value.
*
* @return entry stack shift or -1 if it is unknown
*/
public int getCallStackShift();
/** /**
* Returns true if stack grows with negative offsets * Returns true if stack grows with negative offsets
*/ */

View file

@ -112,16 +112,17 @@ public class FunctionPrototype {
// function pointer, in which case forcing the void // function pointer, in which case forcing the void
// causes the decompiler to drop real parameters. // causes the decompiler to drop real parameters.
// At the moment, we turn on varargs if there are no params // At the moment, we turn on varargs if there are no params
if (voidimpliesdotdotdot && voidinputlock) if (voidimpliesdotdotdot && voidinputlock) {
dotdotdot = true; dotdotdot = true;
}
} }
/** /**
* Populate Function Prototype from information attached to a function in the Program DB. * Populate Function Prototype from information attached to a function in the Program DB.
* *
* @param f is the function to grab prototype from * @param f is the function to grab prototype from
* @param default_extrapop * @param default_extrapop is the default extrapop to use if the function's is unknown
* @param override_extrapop * @param override_extrapop is true if the extrapop should be overridden
*/ */
void grabFromFunction(Function f, int default_extrapop, boolean override_extrapop) { void grabFromFunction(Function f, int default_extrapop, boolean override_extrapop) {
modelname = f.getCallingConventionName(); modelname = f.getCallingConventionName();
@ -134,10 +135,12 @@ public class FunctionPrototype {
returnstorage = returnparam.getVariableStorage(); returnstorage = returnparam.getVariableStorage();
SourceType sigSource = f.getSignatureSource(); SourceType sigSource = f.getSignatureSource();
if (sigSource != SourceType.DEFAULT) if (sigSource != SourceType.DEFAULT) {
outputlock = DataType.DEFAULT != returntype; outputlock = DataType.DEFAULT != returntype;
else }
else {
outputlock = false; outputlock = false;
}
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
outputlock = false; outputlock = false;
@ -162,7 +165,11 @@ public class FunctionPrototype {
extrapop = default_extrapop; extrapop = default_extrapop;
} }
else { else {
extrapop = purge + f.getProgram().getCompilerSpec().getCallStackShift(); PrototypeModel protoModel = f.getCallingConvention();
if (protoModel == null) {
protoModel = f.getProgram().getCompilerSpec().getDefaultCallingConvention();
}
extrapop = purge + protoModel.getStackshift();
} }
} }
@ -187,8 +194,9 @@ public class FunctionPrototype {
* @return the number of defined parameters for this function prototype * @return the number of defined parameters for this function prototype
*/ */
public int getNumParams() { public int getNumParams() {
if (localsyms != null) if (localsyms != null) {
return localsyms.getNumParams(); return localsyms.getNumParams();
}
return params.length; return params.length;
} }
@ -198,8 +206,9 @@ public class FunctionPrototype {
* if this prototype is not backed by a LocalSymbolMap * if this prototype is not backed by a LocalSymbolMap
*/ */
public HighParam getParam(int i) { public HighParam getParam(int i) {
if (localsyms != null) if (localsyms != null) {
return localsyms.getParam(i); return localsyms.getParam(i);
}
return null; return null;
} }
@ -299,36 +308,50 @@ public class FunctionPrototype {
/** /**
* append an XML string representing this function prototype * append an XML string representing this function prototype
* @param res is where the string should be appended
* @param dtmanage is the DataTypeManager for building type reference tags
*/ */
public void buildPrototypeXML(StringBuilder res, PcodeDataTypeManager dtmanage) { public void buildPrototypeXML(StringBuilder res, PcodeDataTypeManager dtmanage) {
res.append("<prototype"); res.append("<prototype");
if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) {
SpecXmlUtils.encodeStringAttribute(res, "extrapop", "unknown"); SpecXmlUtils.encodeStringAttribute(res, "extrapop", "unknown");
else }
else {
SpecXmlUtils.encodeSignedIntegerAttribute(res, "extrapop", extrapop); SpecXmlUtils.encodeSignedIntegerAttribute(res, "extrapop", extrapop);
}
SpecXmlUtils.encodeStringAttribute(res, "model", modelname); SpecXmlUtils.encodeStringAttribute(res, "model", modelname);
if (modellock) if (modellock) {
SpecXmlUtils.encodeBooleanAttribute(res, "modellock", modellock); SpecXmlUtils.encodeBooleanAttribute(res, "modellock", modellock);
if (dotdotdot) }
if (dotdotdot) {
SpecXmlUtils.encodeBooleanAttribute(res, "dotdotdot", dotdotdot); SpecXmlUtils.encodeBooleanAttribute(res, "dotdotdot", dotdotdot);
if (voidinputlock) }
if (voidinputlock) {
SpecXmlUtils.encodeBooleanAttribute(res, "voidlock", voidinputlock); SpecXmlUtils.encodeBooleanAttribute(res, "voidlock", voidinputlock);
if (isinline) }
if (isinline) {
SpecXmlUtils.encodeBooleanAttribute(res, "inline", isinline); SpecXmlUtils.encodeBooleanAttribute(res, "inline", isinline);
if (noreturn) }
if (noreturn) {
SpecXmlUtils.encodeBooleanAttribute(res, "noreturn", noreturn); SpecXmlUtils.encodeBooleanAttribute(res, "noreturn", noreturn);
if (custom) }
if (custom) {
SpecXmlUtils.encodeBooleanAttribute(res, "custom", custom); SpecXmlUtils.encodeBooleanAttribute(res, "custom", custom);
if (hasThis) }
if (hasThis) {
SpecXmlUtils.encodeBooleanAttribute(res, "hasthis", hasThis); SpecXmlUtils.encodeBooleanAttribute(res, "hasthis", hasThis);
if (isConstruct) }
if (isConstruct) {
SpecXmlUtils.encodeBooleanAttribute(res, "constructor", isConstruct); SpecXmlUtils.encodeBooleanAttribute(res, "constructor", isConstruct);
if (isDestruct) }
if (isDestruct) {
SpecXmlUtils.encodeBooleanAttribute(res, "destructor", isDestruct); SpecXmlUtils.encodeBooleanAttribute(res, "destructor", isDestruct);
}
res.append(">\n"); res.append(">\n");
res.append(" <returnsym"); res.append(" <returnsym");
if (outputlock) if (outputlock) {
SpecXmlUtils.encodeBooleanAttribute(res, "typelock", outputlock); SpecXmlUtils.encodeBooleanAttribute(res, "typelock", outputlock);
}
res.append(">\n "); res.append(">\n ");
int sz = returntype.getLength(); int sz = returntype.getLength();
if (sz < 0) { if (sz < 0) {
@ -338,14 +361,16 @@ public class FunctionPrototype {
if ((returnstorage != null) && returnstorage.isValid() && if ((returnstorage != null) && returnstorage.isValid() &&
(!returnstorage.isVoidStorage())) { (!returnstorage.isVoidStorage())) {
int logicalsize = 0; // Assume logicalsize of return matches datatype size int logicalsize = 0; // Assume logicalsize of return matches datatype size
if (sz != returnstorage.size()) // If the sizes do not match if (sz != returnstorage.size()) { // If the sizes do no match
logicalsize = sz; // force the logical size on the varnode logicalsize = sz; // force the logical size on the varnode
}
String addrstring = Varnode.buildXMLAddress(returnstorage.getVarnodes(), logicalsize); String addrstring = Varnode.buildXMLAddress(returnstorage.getVarnodes(), logicalsize);
res.append(addrstring).append("\n "); res.append(addrstring).append("\n ");
} }
else else {
// Decompiler will use model for storage // Decompiler will use model for storage
res.append("<addr/>\n "); // Don't specify where return type is stored res.append("<addr/>\n "); // Don't specify where return type is stored
}
res.append(dtmanage.buildTypeRef(returntype, sz)); res.append(dtmanage.buildTypeRef(returntype, sz));
res.append(" </returnsym>\n"); res.append(" </returnsym>\n");
@ -370,8 +395,9 @@ public class FunctionPrototype {
res.append("\">\n"); res.append("\">\n");
res.append(" <addr/>\n "); // Blank address res.append(" <addr/>\n "); // Blank address
sz = dt.getLength(); sz = dt.getLength();
if (sz < 0) if (sz < 0) {
sz = 1; sz = 1;
}
res.append(dtmanage.buildTypeRef(dt, sz)); res.append(dtmanage.buildTypeRef(dt, sz));
res.append("</param>\n"); res.append("</param>\n");
} }
@ -381,21 +407,22 @@ public class FunctionPrototype {
} }
/** /**
* Parse the function prototype from an XML tree node. * Parse the function prototype from <prototype> tag.
* * @param parser is the XML document to parse
* @param node XML tree node from a parsing of a larger XML document * @param dtmanage is the DataTypeManager used to parse data-type tags
* * @throws PcodeXMLException for any problems parsing
* @throws PcodeXMLException
*/ */
public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage) public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage)
throws PcodeXMLException { throws PcodeXMLException {
XmlElement node = parser.start("prototype"); XmlElement node = parser.start("prototype");
modelname = node.getAttribute("model"); modelname = node.getAttribute("model");
String val = node.getAttribute("extrapop"); String val = node.getAttribute("extrapop");
if (val.equals("unknown")) if (val.equals("unknown")) {
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP; extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
else }
else {
extrapop = SpecXmlUtils.decodeInt(val); extrapop = SpecXmlUtils.decodeInt(val);
}
modellock = false; modellock = false;
if (node.hasAttribute("modellock")) { if (node.hasAttribute("modellock")) {
modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock")); modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock"));
@ -434,16 +461,18 @@ public class FunctionPrototype {
} }
XmlElement retel = parser.start("returnsym"); XmlElement retel = parser.start("returnsym");
outputlock = false; outputlock = false;
if (retel.hasAttribute("typelock")) if (retel.hasAttribute("typelock")) {
outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock")); outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock"));
}
parser.discardSubTree(); parser.discardSubTree();
returnstorage = null; // For now don't use decompiler's return storage returnstorage = null; // For now don't use decompiler's return storage
returntype = dtmanage.readXMLDataType(parser); returntype = dtmanage.readXMLDataType(parser);
parser.end(retel); parser.end(retel);
XmlElement peeknode = parser.peek(); XmlElement peeknode = parser.peek();
if ((peeknode != null) && peeknode.isStart()) if ((peeknode != null) && peeknode.isStart()) {
parser.discardSubTree(); // The decompiler may return an <inject> tag parser.discardSubTree(); // The decompiler may return an <inject> tag
}
parser.end(node); parser.end(node);
} }

View file

@ -539,16 +539,6 @@ class TemporaryCompilerSpec implements CompilerSpec {
public void applyContextSettings(DefaultProgramContext ctx) { public void applyContextSettings(DefaultProgramContext ctx) {
} }
@Override
public int getCallStackMod() {
return newCompilerSpec.getCallStackMod();
}
@Override
public int getCallStackShift() {
return newCompilerSpec.getCallStackShift();
}
@Override @Override
public PrototypeModel[] getCallingConventions() { public PrototypeModel[] getCallingConventions() {
return new PrototypeModel[0]; return new PrototypeModel[0];