GP-5127 Alignment fix for MultiSlotAssign

This commit is contained in:
caheckman 2024-11-13 23:45:46 +00:00
parent d5f4d3b9bc
commit ab7684a230
6 changed files with 30 additions and 16 deletions

View File

@ -1252,8 +1252,9 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
AttributeId ATTRIB_VALUE = AttributeId("value",25); AttributeId ATTRIB_VALUE = AttributeId("value",25);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26); AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
AttributeId ATTRIB_STORAGE = AttributeId("storage",149); AttributeId ATTRIB_STORAGE = AttributeId("storage",149);
AttributeId ATTRIB_STACKSPILL = AttributeId("stackspill",150);
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",150); // Number serves as next open index AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",151); // Number serves as next open index
ElementId ELEM_DATA = ElementId("data",1); ElementId ELEM_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2); ElementId ELEM_INPUT = ElementId("input",2);

View File

@ -736,6 +736,7 @@ extern AttributeId ATTRIB_VAL; ///< Marshaling attribute "val"
extern AttributeId ATTRIB_VALUE; ///< Marshaling attribute "value" extern AttributeId ATTRIB_VALUE; ///< Marshaling attribute "value"
extern AttributeId ATTRIB_WORDSIZE; ///< Marshaling attribute "wordsize" extern AttributeId ATTRIB_WORDSIZE; ///< Marshaling attribute "wordsize"
extern AttributeId ATTRIB_STORAGE; ///< Marshaling attribute "storage" extern AttributeId ATTRIB_STORAGE; ///< Marshaling attribute "storage"
extern AttributeId ATTRIB_STACKSPILL; ///< Marshaling attribute "stackspill"
extern ElementId ELEM_DATA; ///< Marshaling element \<data> extern ElementId ELEM_DATA; ///< Marshaling element \<data>
extern ElementId ELEM_INPUT; ///< Marshaling element \<input> extern ElementId ELEM_INPUT; ///< Marshaling element \<input>

View File

@ -689,6 +689,7 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i
vector<int4> tmpStatus = status; vector<int4> tmpStatus = status;
vector<VarnodeData> pieces; vector<VarnodeData> pieces;
int4 sizeLeft = dt->getSize(); int4 sizeLeft = dt->getSize();
int4 align = dt->getAlignment();
list<ParamEntry>::const_iterator iter = firstIter; list<ParamEntry>::const_iterator iter = firstIter;
list<ParamEntry>::const_iterator endIter = resource->getEntry().end(); list<ParamEntry>::const_iterator endIter = resource->getEntry().end();
if (enforceAlignment) { if (enforceAlignment) {
@ -699,7 +700,6 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i
break; // Reached end of resource list break; // Reached end of resource list
if (entry.getType() == resourceType && entry.getAllGroups().size() == 1) { // Single register if (entry.getType() == resourceType && entry.getAllGroups().size() == 1) { // Single register
if (tmpStatus[entry.getGroup()] == 0) { // Not consumed if (tmpStatus[entry.getGroup()] == 0) { // Not consumed
int4 align = dt->getAlignment();
int4 regSize = entry.getSize(); int4 regSize = entry.getSize();
if (align <= regSize || (resourcesConsumed % align) == 0) if (align <= regSize || (resourcesConsumed % align) == 0)
break; break;
@ -720,19 +720,20 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i
if (tmpStatus[entry.getGroup()] != 0) if (tmpStatus[entry.getGroup()] != 0)
continue; // Already consumed continue; // Already consumed
int4 trialSize = entry.getSize(); int4 trialSize = entry.getSize();
Address addr = entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize,1); Address addr = entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize,align);
tmpStatus[entry.getGroup()] = -1; // Consume the register tmpStatus[entry.getGroup()] = -1; // Consume the register
pieces.push_back(VarnodeData()); pieces.push_back(VarnodeData());
pieces.back().space = addr.getSpace(); pieces.back().space = addr.getSpace();
pieces.back().offset = addr.getOffset(); pieces.back().offset = addr.getOffset();
pieces.back().size = trialSize; pieces.back().size = trialSize;
sizeLeft -= trialSize; sizeLeft -= trialSize;
align = 1; // Treat remaining partial pieces as having no alignment requirement
} }
if (sizeLeft > 0) { // Have to use stack to get enough bytes if (sizeLeft > 0) { // Have to use stack to get enough bytes
if (!consumeFromStack) if (!consumeFromStack)
return fail; return fail;
int4 grp = stackEntry->getGroup(); int4 grp = stackEntry->getGroup();
Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,1); // Consume all the space we need Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align); // Consume all the space we need
if (addr.isInvalid()) if (addr.isInvalid())
return fail; return fail;
pieces.push_back(VarnodeData()); pieces.push_back(VarnodeData());
@ -841,6 +842,9 @@ void MultiSlotAssign::decode(Decoder &decoder)
else if (attribId == ATTRIB_ALIGN) { else if (attribId == ATTRIB_ALIGN) {
enforceAlignment = decoder.readBool(); enforceAlignment = decoder.readBool();
} }
else if (attribId == ATTRIB_STACKSPILL) {
consumeFromStack = decoder.readBool();
}
} }
decoder.closeElement(elemId); decoder.closeElement(elemId);
initializeEntries(); // Need new firstIter initializeEntries(); // Need new firstIter

View File

@ -396,6 +396,9 @@
<optional> <optional>
<attribute name="storage"/> <attribute name="storage"/>
</optional> </optional>
<optional>
<attribute name="stackspill"/>
</optional>
</element> </element>
<element name="hidden_return"> <element name="hidden_return">
<optional> <optional>

View File

@ -150,6 +150,7 @@ public class MultiSlotAssign extends AssignAction {
ArrayList<Varnode> pieces = new ArrayList<>(); ArrayList<Varnode> pieces = new ArrayList<>();
ParameterPieces param = new ParameterPieces(); ParameterPieces param = new ParameterPieces();
int sizeLeft = dt.getLength(); int sizeLeft = dt.getLength();
int align = dt.getAlignment();
int iter = firstIter; int iter = firstIter;
int endIter = resource.getNumParamEntry(); int endIter = resource.getNumParamEntry();
if (enforceAlignment) { if (enforceAlignment) {
@ -161,7 +162,6 @@ public class MultiSlotAssign extends AssignAction {
} // Reached end of resource list } // Reached end of resource list
if (entry.getType() == resourceType && entry.getAllGroups().length == 1) { // Single register if (entry.getType() == resourceType && entry.getAllGroups().length == 1) { // Single register
if (tmpStatus[entry.getGroup()] == 0) { // Not consumed if (tmpStatus[entry.getGroup()] == 0) { // Not consumed
int align = dt.getAlignment();
int regSize = entry.getSize(); int regSize = entry.getSize();
if (align <= regSize || (resourcesConsumed % align) == 0) { if (align <= regSize || (resourcesConsumed % align) == 0) {
break; break;
@ -186,11 +186,12 @@ public class MultiSlotAssign extends AssignAction {
continue; continue;
} // Already consumed } // Already consumed
int trialSize = entry.getSize(); int trialSize = entry.getSize();
entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize, 1, param); entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize, align, param);
tmpStatus[entry.getGroup()] = -1; // Consume the register tmpStatus[entry.getGroup()] = -1; // Consume the register
Varnode vn = new Varnode(param.address, trialSize); Varnode vn = new Varnode(param.address, trialSize);
pieces.add(vn); pieces.add(vn);
sizeLeft -= trialSize; sizeLeft -= trialSize;
align = 1; // Treat remaining partial pieces as having no alignment requirement
} }
boolean onePieceJoin = false; boolean onePieceJoin = false;
if (sizeLeft > 0) { // Have to use stack to get enough bytes if (sizeLeft > 0) { // Have to use stack to get enough bytes
@ -198,7 +199,7 @@ public class MultiSlotAssign extends AssignAction {
return FAIL; return FAIL;
} }
int grp = stackEntry.getGroup(); int grp = stackEntry.getGroup();
tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, 1, param); // Consume all the space we need tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param); // Consume all the space we need
if (param.address == null) { if (param.address == null) {
return FAIL; return FAIL;
} }
@ -276,6 +277,9 @@ public class MultiSlotAssign extends AssignAction {
else if (name.equals(ATTRIB_ALIGN.name())) { else if (name.equals(ATTRIB_ALIGN.name())) {
enforceAlignment = SpecXmlUtils.decodeBoolean(attrib.getValue()); enforceAlignment = SpecXmlUtils.decodeBoolean(attrib.getValue());
} }
else if (name.equals(ATTRIB_STACKSPILL.name())) {
consumeFromStack = SpecXmlUtils.decodeBoolean(attrib.getValue());
}
} }
parser.end(elem); parser.end(elem);
try { try {

View File

@ -242,6 +242,7 @@ public record AttributeId(String name, int id) {
// public static final AttributeId ATTRIB_ADDRESS = new AttributeId("address", 148); // public static final AttributeId ATTRIB_ADDRESS = new AttributeId("address", 148);
public static final AttributeId ATTRIB_STORAGE = new AttributeId("storage", 149); public static final AttributeId ATTRIB_STORAGE = new AttributeId("storage", 149);
public static final AttributeId ATTRIB_STACKSPILL = new AttributeId("stackspill", 150);
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 150); public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 151);
} }