Breaking out ParamListRegisterOut

This commit is contained in:
caheckman 2021-10-14 19:23:48 -04:00
parent f235e46adc
commit a00de6cbac
7 changed files with 224 additions and 146 deletions

View file

@ -38,12 +38,11 @@ public interface ParamList {
* Given a list of datatypes, calculate the storage locations used for passing those datatypes
* @param prog is the active progra
* @param proto is the list of datatypes
* @param isinput is true if this parameter list is being processed for input arguments, false for output
* @param res is the vector for holding the VariableStorage corresponding to datatypes
* @param addAutoParams if true add/process auto-parameters
*/
public void assignMap(Program prog, DataType[] proto, boolean isinput,
ArrayList<VariableStorage> res, boolean addAutoParams);
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
boolean addAutoParams);
public void saveXml(StringBuilder buffer, boolean isInput);

View file

@ -0,0 +1,44 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.lang;
import java.util.ArrayList;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage;
/**
* A list of resources describing possible storage locations for a function's return value,
* and a strategy for selecting a storage location based on data-types in a function signature.
*
* The assignment strategy for this class is to take the first storage location in the list
* that fits for the given function signature's return data-type.
*/
public class ParamListRegisterOut extends ParamListStandard {
@Override
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
boolean addAutoParams) {
int[] status = new int[numgroup];
for (int i = 0; i < numgroup; ++i) {
status[i] = 0;
}
VariableStorage store = assignAddress(prog, proto[0], status, false, false);
res.add(store);
}
}

View file

@ -143,37 +143,30 @@ public class ParamListStandard implements ParamList {
}
@Override
public void assignMap(Program prog, DataType[] proto, boolean isinput,
ArrayList<VariableStorage> res, boolean addAutoParams) {
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
boolean addAutoParams) {
int[] status = new int[numgroup];
for (int i = 0; i < numgroup; ++i) {
status[i] = 0;
}
if (isinput) {
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
DataTypeManager dtm = prog.getDataTypeManager();
Pointer pointer = dtm.getPointer(proto[0]);
VariableStorage store = assignAddress(prog, pointer, status, true, false);
res.set(1, store);
}
for (int i = 1; i < proto.length; ++i) {
VariableStorage store;
if ((pointermax != 0) && (proto[i] != null) &&
(proto[i].getLength() > pointermax)) { // DataType is too big
// Assume datatype is stored elsewhere and only the pointer is passed
DataTypeManager dtm = prog.getDataTypeManager();
Pointer pointer = dtm.getPointer(proto[i]);
store = assignAddress(prog, pointer, status, false, true);
}
else {
store = assignAddress(prog, proto[i], status, false, false);
}
res.add(store);
}
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
DataTypeManager dtm = prog.getDataTypeManager();
Pointer pointer = dtm.getPointer(proto[0]);
VariableStorage store = assignAddress(prog, pointer, status, true, false);
res.set(1, store);
}
else {
VariableStorage store = assignAddress(prog, proto[0], status, false, false);
for (int i = 1; i < proto.length; ++i) {
VariableStorage store;
if ((pointermax != 0) && (proto[i] != null) && (proto[i].getLength() > pointermax)) { // DataType is too big
// Assume datatype is stored elsewhere and only the pointer is passed
DataTypeManager dtm = prog.getDataTypeManager();
Pointer pointer = dtm.getPointer(proto[i]);
store = assignAddress(prog, pointer, status, false, true);
}
else {
store = assignAddress(prog, proto[i], status, false, false);
}
res.add(store);
}
}
@ -279,11 +272,12 @@ public class ParamListStandard implements ParamList {
throw new XmlParseException(
"<pentry> in the join space not allowed in <group> tag");
}
if (count > 1) {
ParamEntry.orderWithinGroup(pe.get(pe.size() - 2), lastEntry);
if (count > 2) {
ParamEntry.orderWithinGroup(pe.get(pe.size() - 3), lastEntry);
}
}
// Check that all entries in the group are distinguishable
for (int i = 1; i < count; ++i) {
ParamEntry curEntry = pe.get(pe.size() - 1 - i);
for (int j = 0; j < i; ++i) {
ParamEntry.orderWithinGroup(pe.get(pe.size() - 1 - j), curEntry);
}
}
parser.end(el);

View file

@ -24,11 +24,23 @@ import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlParseException;
import ghidra.xml.XmlPullParser;
public class ParamListStandardOut extends ParamListStandard {
/**
* A list of resources describing possible storage locations for a function's return value,
* and a strategy for selecting a storage location based on data-types in a function signature.
*
* Similar to the parent class, when assigning storage, the first entry that matches the data-type
* is chosen. But if this instance fails to find a match (because the return value data-type is too
* big) the data-type is converted to a pointer and storage is assigned based on that pointer.
* Additionally, if configured, this instance will signal that a hidden input parameter is required
* to fully model where the large return value is stored.
*
* The resource list is checked to ensure entries are distinguishable.
*/
public class ParamListStandardOut extends ParamListRegisterOut {
@Override
public void assignMap(Program prog, DataType[] proto, boolean isinput,
ArrayList<VariableStorage> res, boolean addAutoParams) {
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
boolean addAutoParams) {
int[] status = new int[numgroup];
for (int i = 0; i < numgroup; ++i) {
@ -64,11 +76,10 @@ public class ParamListStandardOut extends ParamListStandard {
public void restoreXml(XmlPullParser parser, CompilerSpec cspec) throws XmlParseException {
super.restoreXml(parser, cspec);
// ParamEntry tags in the output list are considered a group
// ParamEntry tags in the output list are considered a group. Check that entries are distinguishable.
for (int i = 1; i < entry.length; ++i) {
ParamEntry.orderWithinGroup(entry[i - 1], entry[i]);
if (i > 1) {
ParamEntry.orderWithinGroup(entry[i - 2], entry[i]);
for (int j = 0; j < i; ++j) {
ParamEntry.orderWithinGroup(entry[j], entry[i]);
}
}
}

View file

@ -199,7 +199,7 @@ public class PrototypeModel {
DataType[] arr = new DataType[1];
arr[0] = clone;
ArrayList<VariableStorage> res = new ArrayList<>();
outputParams.assignMap(program, arr, false, res, false);
outputParams.assignMap(program, arr, res, false);
if (res.size() > 0) {
return res.get(0);
}
@ -247,7 +247,7 @@ public class PrototypeModel {
}
DataType arr[] = new DataType[argIndex + 2];
arr[0] = DataType.VOID; // Assume the return type is void
arr[0] = VoidDataType.dataType; // Assume the return type is void
for (int i = 0; i < argIndex; ++i) {
if (params != null && i < params.length) {
arr[i + 1] = params[i].getDataType(); // Copy in current types if we have them
@ -291,8 +291,8 @@ public class PrototypeModel {
}
ArrayList<VariableStorage> res = new ArrayList<>();
outputParams.assignMap(program, dataTypes, false, res, addAutoParams);
inputParams.assignMap(program, dataTypes, true, res, addAutoParams);
outputParams.assignMap(program, dataTypes, res, addAutoParams);
inputParams.assignMap(program, dataTypes, res, addAutoParams);
VariableStorage[] finalres = new VariableStorage[res.size()];
res.toArray(finalres);
@ -351,7 +351,7 @@ public class PrototypeModel {
}
else if (strategy.equals("register")) {
inputParams = new ParamListStandard();
outputParams = new ParamListStandard();
outputParams = new ParamListRegisterOut();
inputListType = InputListType.REGISTER;
}
else {