mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-4356_ghintern_avr8_cspec--SQUASHED'
This commit is contained in:
commit
88bfdeb429
17 changed files with 564 additions and 63 deletions
|
@ -773,14 +773,19 @@ void ParamListStandard::assignMap(const PrototypePieces &proto,TypeFactory &type
|
|||
|
||||
if (res.size() == 2) { // Check for hidden parameters defined by the output list
|
||||
Datatype *dt = res.back().type;
|
||||
type_class store;
|
||||
if ((res.back().flags & ParameterPieces::hiddenretparm) != 0)
|
||||
store = TYPECLASS_HIDDENRET;
|
||||
else
|
||||
store = metatype2typeclass(dt->getMetatype());
|
||||
// Reserve first param for hidden return pointer
|
||||
if (assignAddressFallback(store,dt,false,status,res.back()) == AssignAction::fail)
|
||||
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
||||
if ((res.back().flags & ParameterPieces::hiddenretparm) != 0) {
|
||||
// Need to pull from registers marked as hiddenret
|
||||
if (assignAddressFallback(TYPECLASS_HIDDENRET,dt,false,status,res.back()) == AssignAction::fail) {
|
||||
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Assign as a regular first input pointer parameter
|
||||
if (assignAddress(dt,proto,0,typefactory,status,res.back()) == AssignAction::fail) {
|
||||
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
||||
}
|
||||
}
|
||||
|
||||
res.back().flags |= ParameterPieces::hiddenretparm;
|
||||
}
|
||||
for(int4 i=0;i<proto.intypes.size();++i) {
|
||||
|
@ -1573,8 +1578,10 @@ void ParamListStandardOut::assignMap(const PrototypePieces &proto,TypeFactory &t
|
|||
res.back().type = typefactory.getTypeVoid();
|
||||
}
|
||||
else {
|
||||
if (assignAddressFallback(TYPECLASS_PTR,pointertp,false,status,res.back()) == AssignAction::fail)
|
||||
throw ParamUnassignedError("Cannot assign return value as a pointer");
|
||||
res.back().type = pointertp;
|
||||
if (assignAddress(pointertp,proto,-1,typefactory,status,res.back()) == AssignAction::fail) {
|
||||
throw ParamUnassignedError("Cannot assign return value as a pointer");
|
||||
}
|
||||
}
|
||||
res.back().flags = ParameterPieces::indirectstorage;
|
||||
|
||||
|
|
|
@ -1254,8 +1254,7 @@ AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
|||
AttributeId ATTRIB_STORAGE = AttributeId("storage",149);
|
||||
AttributeId ATTRIB_STACKSPILL = AttributeId("stackspill",150);
|
||||
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",154); // Number serves as next open index
|
||||
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",156); // Number serves as next open index
|
||||
|
||||
ElementId ELEM_DATA = ElementId("data",1);
|
||||
ElementId ELEM_INPUT = ElementId("input",2);
|
||||
|
@ -1268,6 +1267,6 @@ ElementId ELEM_VAL = ElementId("val",8);
|
|||
ElementId ELEM_VALUE = ElementId("value",9);
|
||||
ElementId ELEM_VOID = ElementId("void",10);
|
||||
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",288); // Number serves as next open index
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",289); // Number serves as next open index
|
||||
|
||||
} // End namespace ghidra
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace ghidra {
|
|||
|
||||
AttributeId ATTRIB_SIZES = AttributeId("sizes",151);
|
||||
AttributeId ATTRIB_MAX_PRIMITIVES = AttributeId("maxprimitives", 153);
|
||||
AttributeId ATTRIB_REVERSESIGNIF = AttributeId("reversesignif", 154);
|
||||
AttributeId ATTRIB_MATCHSIZE = AttributeId("matchsize", 155);
|
||||
|
||||
ElementId ELEM_DATATYPE = ElementId("datatype",273);
|
||||
ElementId ELEM_CONSUME = ElementId("consume",274);
|
||||
|
@ -34,6 +36,7 @@ ElementId ELEM_HIDDEN_RETURN = ElementId("hidden_return",282);
|
|||
ElementId ELEM_JOIN_PER_PRIMITIVE = ElementId("join_per_primitive",283);
|
||||
ElementId ELEM_JOIN_DUAL_CLASS = ElementId("join_dual_class",285);
|
||||
ElementId ELEM_EXTRA_STACK = ElementId("extra_stack",287);
|
||||
ElementId ELEM_CONSUME_REMAINING = ElementId("consume_remaining",288);
|
||||
|
||||
/// \brief Check that a big Primitive properly overlaps smaller Primitives
|
||||
///
|
||||
|
@ -619,6 +622,29 @@ AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandar
|
|||
return action;
|
||||
}
|
||||
|
||||
/// \brief Read the next model rule precondition element from the stream
|
||||
///
|
||||
/// Allocate the precondition object corresponding to the element and configure it.
|
||||
/// If the next element is not a precondition, return null.
|
||||
/// \param decoder is the stream decoder
|
||||
/// \param res is the resource set for the new precondition
|
||||
/// \return the new precondition, or null if no more preconditions are in the stream
|
||||
AssignAction *AssignAction::decodePrecondition(Decoder &decoder,const ParamListStandard *res)
|
||||
{
|
||||
AssignAction *action;
|
||||
uint4 elemId = decoder.peekElement();
|
||||
|
||||
if (elemId == ELEM_CONSUME_EXTRA) {
|
||||
action = new ConsumeExtra(res);
|
||||
}
|
||||
else {
|
||||
return (AssignAction *)0;
|
||||
}
|
||||
|
||||
action->decode(decoder);
|
||||
return action;
|
||||
}
|
||||
|
||||
/// \brief Read the next model rule sideeffect element from the stream
|
||||
///
|
||||
/// Allocate the sideeffect object corresponding to the element and configure it.
|
||||
|
@ -638,6 +664,9 @@ AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListSta
|
|||
else if (elemId == ELEM_EXTRA_STACK) {
|
||||
action = new ExtraStack(res,0);
|
||||
}
|
||||
else if (elemId == ELEM_CONSUME_REMAINING) {
|
||||
action = new ConsumeRemaining(res);
|
||||
}
|
||||
else
|
||||
throw DecoderError("Expecting model rule sideeffect");
|
||||
action->decode(decoder);
|
||||
|
@ -911,8 +940,12 @@ void MultiSlotAssign::decode(Decoder &decoder)
|
|||
if (attribId == 0) break;
|
||||
if (attribId == ATTRIB_REVERSEJUSTIFY) {
|
||||
if (decoder.readBool())
|
||||
justifyRight = !justifyRight;
|
||||
justifyRight = !justifyRight;
|
||||
}
|
||||
else if (attribId == ATTRIB_REVERSESIGNIF) {
|
||||
if (decoder.readBool())
|
||||
consumeMostSig = !consumeMostSig;
|
||||
}
|
||||
else if (attribId == ATTRIB_STORAGE) {
|
||||
resourceType = string2typeclass(decoder.readString());
|
||||
}
|
||||
|
@ -1216,8 +1249,12 @@ void MultiSlotDualAssign::decode(Decoder &decoder)
|
|||
if (attribId == 0) break;
|
||||
if (attribId == ATTRIB_REVERSEJUSTIFY) {
|
||||
if (decoder.readBool())
|
||||
justifyRight = !justifyRight;
|
||||
justifyRight = !justifyRight;
|
||||
}
|
||||
else if (attribId == ATTRIB_REVERSESIGNIF) {
|
||||
if (decoder.readBool())
|
||||
consumeMostSig = !consumeMostSig;
|
||||
}
|
||||
else if (attribId == ATTRIB_STORAGE || attribId == ATTRIB_A) {
|
||||
baseType = string2typeclass(decoder.readString());
|
||||
}
|
||||
|
@ -1353,6 +1390,61 @@ void ConsumeExtra::decode(Decoder &decoder)
|
|||
|
||||
{
|
||||
uint4 elemId = decoder.openElement(ELEM_CONSUME_EXTRA);
|
||||
for(;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
else if (attribId == ATTRIB_STORAGE) {
|
||||
resourceType = string2typeclass(decoder.readString());
|
||||
}
|
||||
else if (attribId == ATTRIB_MATCHSIZE) {
|
||||
matchSize = decoder.readBool();
|
||||
}
|
||||
}
|
||||
decoder.closeElement(elemId);
|
||||
initializeEntries();
|
||||
}
|
||||
|
||||
|
||||
/// Find the first ParamEntry matching the \b resourceType.
|
||||
void ConsumeRemaining::initializeEntries(void)
|
||||
|
||||
{
|
||||
resource->extractTiles(tiles,resourceType);
|
||||
if (tiles.size() == 0)
|
||||
throw LowlevelError("Could not find matching resources for action: consume_remaining");
|
||||
}
|
||||
|
||||
ConsumeRemaining::ConsumeRemaining(const ParamListStandard *res)
|
||||
: AssignAction(res)
|
||||
{
|
||||
resourceType = TYPECLASS_GENERAL;
|
||||
}
|
||||
|
||||
ConsumeRemaining::ConsumeRemaining(type_class store,const ParamListStandard *res)
|
||||
: AssignAction(res)
|
||||
{
|
||||
resourceType = store;
|
||||
initializeEntries();
|
||||
}
|
||||
|
||||
uint4 ConsumeRemaining::assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
|
||||
vector<int4> &status,ParameterPieces &res) const
|
||||
{
|
||||
int4 iter = 0;
|
||||
while(iter != tiles.size()) {
|
||||
const ParamEntry *entry = tiles[iter];
|
||||
++iter;
|
||||
if (status[entry->getGroup()] != 0)
|
||||
continue; // Already consumed
|
||||
status[entry->getGroup()] = -1; // Consume the slot/register
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void ConsumeRemaining::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
uint4 elemId = decoder.openElement(ELEM_CONSUME_REMAINING);
|
||||
resourceType = string2typeclass(decoder.readString(ATTRIB_STORAGE));
|
||||
decoder.closeElement(elemId);
|
||||
initializeEntries();
|
||||
|
@ -1416,6 +1508,8 @@ ModelRule::ModelRule(const ModelRule &op2,const ParamListStandard *res)
|
|||
assign = op2.assign->clone(res);
|
||||
else
|
||||
assign = (AssignAction *)0;
|
||||
for (int4 i=0;i<op2.preconditions.size();++i)
|
||||
preconditions.push_back(op2.preconditions[i]->clone(res));
|
||||
for(int4 i=0;i<op2.sideeffects.size();++i)
|
||||
sideeffects.push_back(op2.sideeffects[i]->clone(res));
|
||||
}
|
||||
|
@ -1441,6 +1535,8 @@ ModelRule::~ModelRule(void)
|
|||
delete qualifier;
|
||||
if (assign != (AssignAction *)0)
|
||||
delete assign;
|
||||
for(int4 i=0;i<preconditions.size();++i)
|
||||
delete preconditions[i];
|
||||
for(int4 i=0;i<sideeffects.size();++i)
|
||||
delete sideeffects[i];
|
||||
}
|
||||
|
@ -1467,8 +1563,13 @@ uint4 ModelRule::assignAddress(Datatype *dt,const PrototypePieces &proto,int4 po
|
|||
if (qualifier != (QualifierFilter *)0 && !qualifier->filter(proto,pos)) {
|
||||
return AssignAction::fail;
|
||||
}
|
||||
uint4 response = assign->assignAddress(dt,proto,pos,tlist,status,res);
|
||||
vector<int4> tmpStatus = status;
|
||||
for(int4 i =0;i<preconditions.size();++i) {
|
||||
preconditions[i]->assignAddress(dt,proto,pos,tlist,tmpStatus,res);
|
||||
}
|
||||
uint4 response = assign->assignAddress(dt,proto,pos,tlist,tmpStatus,res);
|
||||
if (response != AssignAction::fail) {
|
||||
status = tmpStatus;
|
||||
for(int4 i=0;i<sideeffects.size();++i) {
|
||||
sideeffects[i]->assignAddress(dt,proto,pos,tlist,status,res);
|
||||
}
|
||||
|
@ -1499,6 +1600,12 @@ void ModelRule::decode(Decoder &decoder,const ParamListStandard *res)
|
|||
else {
|
||||
qualifier = new AndFilter(qualifiers);
|
||||
}
|
||||
for (;;) {
|
||||
AssignAction *precond = AssignAction::decodePrecondition(decoder, res);
|
||||
if (precond == (AssignAction *)0)
|
||||
break;
|
||||
preconditions.push_back(precond);
|
||||
}
|
||||
assign = AssignAction::decodeAction(decoder, res);
|
||||
while(decoder.peekElement() != 0) {
|
||||
sideeffects.push_back(AssignAction::decodeSideeffect(decoder,res));
|
||||
|
|
|
@ -30,6 +30,8 @@ class ParamActive;
|
|||
|
||||
extern AttributeId ATTRIB_SIZES; ///< Marshaling attribute "sizes"
|
||||
extern AttributeId ATTRIB_MAX_PRIMITIVES; ///< Marshaling attribute "maxprimitives"
|
||||
extern AttributeId ATTRIB_REVERSESIGNIF; ///< Marshaling attribute "reversesignif"
|
||||
extern AttributeId ATTRIB_MATCHSIZE; ///< Marshaling attribute "matchsize"
|
||||
|
||||
extern ElementId ELEM_DATATYPE; ///< Marshaling element \<datatype>
|
||||
extern ElementId ELEM_CONSUME; ///< Marshaling element \<consume>
|
||||
|
@ -44,6 +46,7 @@ extern ElementId ELEM_HIDDEN_RETURN; ///< Marshaling element \<hidden_return>
|
|||
extern ElementId ELEM_JOIN_PER_PRIMITIVE; ///< Marshaling element \<join_per_primitive>
|
||||
extern ElementId ELEM_JOIN_DUAL_CLASS; ///< Marshaling element \<join_dual_class>
|
||||
extern ElementId ELEM_EXTRA_STACK; ///< Marshaling element \<extra_stack>
|
||||
extern ElementId ELEM_CONSUME_REMAINING; ///< Marshaling element \<consume_remaining>
|
||||
|
||||
/// \brief Class for extracting primitive elements of a data-type
|
||||
///
|
||||
|
@ -311,6 +314,7 @@ public:
|
|||
/// \param decoder is the given stream decoder
|
||||
virtual void decode(Decoder &decoder)=0;
|
||||
static AssignAction *decodeAction(Decoder &decoder,const ParamListStandard *res);
|
||||
static AssignAction *decodePrecondition(Decoder &decoder, const ParamListStandard *res);
|
||||
static AssignAction *decodeSideeffect(Decoder &decoder,const ParamListStandard *res);
|
||||
};
|
||||
|
||||
|
@ -492,6 +496,26 @@ public:
|
|||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
/// \brief Consume all the remaining registers from a given resource list
|
||||
///
|
||||
/// This action is a side-effect and doesn't assign an address for the current parameter.
|
||||
/// The resource list, resourceType, is specified. If the side-effect is triggered, all register
|
||||
/// resources from this list are consumed, until no registers remain. If all registers are already
|
||||
/// consumed, no action is taken.
|
||||
class ConsumeRemaining : public AssignAction {
|
||||
type_class resourceType; ///< The other resource list to consume from
|
||||
vector<const ParamEntry *> tiles; ///< List of registers that can be consumed
|
||||
void initializeEntries(void); ///< Cache specific ParamEntry needed by the action
|
||||
public:
|
||||
ConsumeRemaining(const ParamListStandard *res); ///< Constructor for use with decode
|
||||
ConsumeRemaining(type_class store, const ParamListStandard *res); ///< Constructor
|
||||
virtual AssignAction *clone(const ParamListStandard *newResource) const {
|
||||
return new ConsumeRemaining(resourceType,newResource); }
|
||||
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
|
||||
vector<int4> &status,ParameterPieces &res) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
/// \brief A rule controlling how parameters are assigned addresses
|
||||
///
|
||||
/// Rules are applied to a parameter in the context of a full function prototype.
|
||||
|
@ -502,6 +526,7 @@ class ModelRule {
|
|||
DatatypeFilter *filter; ///< Which data-types \b this rule applies to
|
||||
QualifierFilter *qualifier; ///< Additional qualifiers for when the rule should apply (if non-null)
|
||||
AssignAction *assign; ///< How the Address should be assigned
|
||||
vector<AssignAction *> preconditions; ///< Extra actions that happen before assignment, discarded on failure
|
||||
vector<AssignAction *> sideeffects; ///< Extra actions that happen on success
|
||||
public:
|
||||
ModelRule(void) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue