mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-5851 Fix tiling truncations for odd data-type sizes in
MultiSlotAssign. Fix for big endian multi-slot return value.
This commit is contained in:
parent
eb7dbaa04f
commit
f6495e4146
13 changed files with 280 additions and 89 deletions
|
@ -302,6 +302,8 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype,
|
||||||
|
|
||||||
{ // Generic casting rules that apply for most ops
|
{ // Generic casting rules that apply for most ops
|
||||||
if (curtype == reqtype) return (Datatype *)0; // Types are equal, no cast required
|
if (curtype == reqtype) return (Datatype *)0; // Types are equal, no cast required
|
||||||
|
if (curtype->getMetatype()==TYPE_VOID)
|
||||||
|
return reqtype; // If coming from "void" (as a dereferenced pointer) we need a cast
|
||||||
Datatype *reqbase = reqtype;
|
Datatype *reqbase = reqtype;
|
||||||
Datatype *curbase = curtype;
|
Datatype *curbase = curtype;
|
||||||
bool isptr = false;
|
bool isptr = false;
|
||||||
|
@ -325,8 +327,9 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype,
|
||||||
while(curbase->getTypedef() != (Datatype *)0)
|
while(curbase->getTypedef() != (Datatype *)0)
|
||||||
curbase = curbase->getTypedef();
|
curbase = curbase->getTypedef();
|
||||||
if (curbase == reqbase) return (Datatype *)0; // Different typedefs could point to the same type
|
if (curbase == reqbase) return (Datatype *)0; // Different typedefs could point to the same type
|
||||||
if ((reqbase->getMetatype()==TYPE_VOID)||(curtype->getMetatype()==TYPE_VOID))
|
if (reqbase->getMetatype()==TYPE_VOID || curbase->getMetatype()==TYPE_VOID) {
|
||||||
return (Datatype *)0; // Don't cast from or to VOID
|
return (Datatype *)0; // Don't cast to or from a void pointer
|
||||||
|
}
|
||||||
if (reqbase->getSize() != curbase->getSize()) {
|
if (reqbase->getSize() != curbase->getSize()) {
|
||||||
if (reqbase->isVariableLength() && isptr && reqbase->hasSameVariableBase(curbase)) {
|
if (reqbase->isVariableLength() && isptr && reqbase->hasSameVariableBase(curbase)) {
|
||||||
return (Datatype *)0; // Don't need a cast
|
return (Datatype *)0; // Don't need a cast
|
||||||
|
|
|
@ -1943,6 +1943,7 @@ ParamActive::ParamActive(bool recoversub)
|
||||||
isfullychecked = false;
|
isfullychecked = false;
|
||||||
needsfinalcheck = false;
|
needsfinalcheck = false;
|
||||||
recoversubcall = recoversub;
|
recoversubcall = recoversub;
|
||||||
|
joinReverse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamActive::clear(void)
|
void ParamActive::clear(void)
|
||||||
|
@ -1953,6 +1954,7 @@ void ParamActive::clear(void)
|
||||||
stackplaceholder = -1;
|
stackplaceholder = -1;
|
||||||
numpasses = 0;
|
numpasses = 0;
|
||||||
isfullychecked = false;
|
isfullychecked = false;
|
||||||
|
joinReverse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A ParamTrial object is created and a slot is assigned.
|
/// A ParamTrial object is created and a slot is assigned.
|
||||||
|
@ -5693,7 +5695,7 @@ void FuncCallSpecs::buildInputFromTrials(Funcdata &data)
|
||||||
newparam.push_back(op->getIn(0)); // Preserve the fspec parameter
|
newparam.push_back(op->getIn(0)); // Preserve the fspec parameter
|
||||||
|
|
||||||
if (isDotdotdot() && isInputLocked()){
|
if (isDotdotdot() && isInputLocked()){
|
||||||
//if varargs, move the fixed args to the beginning of the list in order
|
// if varargs, move the fixed args to the beginning of the list in order to
|
||||||
// preserve relative order of variable args
|
// preserve relative order of variable args
|
||||||
activeinput.sortFixedPosition();
|
activeinput.sortFixedPosition();
|
||||||
}
|
}
|
||||||
|
@ -5802,8 +5804,15 @@ void FuncCallSpecs::buildOutputFromTrials(Funcdata &data,vector<Varnode *> &tria
|
||||||
data.opSetOutput(op,finaloutvn); // Move varnode to its new position as output of call
|
data.opSetOutput(op,finaloutvn); // Move varnode to its new position as output of call
|
||||||
}
|
}
|
||||||
else if (activeoutput.getNumTrials()==2) {
|
else if (activeoutput.getNumTrials()==2) {
|
||||||
Varnode *hivn = finalvn[1]; // orderOutputPieces puts hi last
|
Varnode *hivn,*lovn;
|
||||||
Varnode *lovn = finalvn[0];
|
if (activeoutput.isJoinReverse()) {
|
||||||
|
hivn = finalvn[0];
|
||||||
|
lovn = finalvn[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hivn = finalvn[1];
|
||||||
|
lovn = finalvn[0];
|
||||||
|
}
|
||||||
if (data.isDoublePrecisOn()) {
|
if (data.isDoublePrecisOn()) {
|
||||||
lovn->setPrecisLo(); // Mark that these varnodes are part of a larger precision whole
|
lovn->setPrecisLo(); // Mark that these varnodes are part of a larger precision whole
|
||||||
hivn->setPrecisHi();
|
hivn->setPrecisHi();
|
||||||
|
|
|
@ -291,6 +291,7 @@ class ParamActive {
|
||||||
bool isfullychecked; ///< True if all trials are fully examined (and no new trials are expected)
|
bool isfullychecked; ///< True if all trials are fully examined (and no new trials are expected)
|
||||||
bool needsfinalcheck; ///< Should a final pass be made on trials (to take into account control-flow changes)
|
bool needsfinalcheck; ///< Should a final pass be made on trials (to take into account control-flow changes)
|
||||||
bool recoversubcall; ///< True if \b this is being used to recover prototypes of a sub-function call
|
bool recoversubcall; ///< True if \b this is being used to recover prototypes of a sub-function call
|
||||||
|
bool joinReverse; ///< True if varnodes should be joined in reverse order
|
||||||
public:
|
public:
|
||||||
ParamActive(bool recoversub); ///< Construct an empty container
|
ParamActive(bool recoversub); ///< Construct an empty container
|
||||||
void clear(void); ///< Reset to an empty container
|
void clear(void); ///< Reset to an empty container
|
||||||
|
@ -301,6 +302,8 @@ public:
|
||||||
int4 whichTrial(const Address &addr,int4 sz) const; ///< Get the trial overlapping with the given memory range
|
int4 whichTrial(const Address &addr,int4 sz) const; ///< Get the trial overlapping with the given memory range
|
||||||
bool needsFinalCheck(void) const { return needsfinalcheck; } ///< Is a final check required
|
bool needsFinalCheck(void) const { return needsfinalcheck; } ///< Is a final check required
|
||||||
void markNeedsFinalCheck(void) { needsfinalcheck = true; } ///< Mark that a final check is required
|
void markNeedsFinalCheck(void) { needsfinalcheck = true; } ///< Mark that a final check is required
|
||||||
|
bool isJoinReverse(void) const { return joinReverse; } ///< Do Varnodes need to be joined in reverse order
|
||||||
|
void setJoinReverse(void) { joinReverse = true; } ///< Mark that varnodes need to be joined in reverse order
|
||||||
bool isRecoverSubcall(void) const { return recoversubcall; } ///< Are these trials for a call to a sub-function
|
bool isRecoverSubcall(void) const { return recoversubcall; } ///< Are these trials for a call to a sub-function
|
||||||
bool isFullyChecked(void) const { return isfullychecked; } ///< Are all trials checked with no new trials expected
|
bool isFullyChecked(void) const { return isfullychecked; } ///< Are all trials checked with no new trials expected
|
||||||
void markFullyChecked(void) { isfullychecked = true; } ///< Mark that all trials are checked
|
void markFullyChecked(void) { isfullychecked = true; } ///< Mark that all trials are checked
|
||||||
|
@ -311,6 +314,7 @@ public:
|
||||||
void setMaxPass(int4 val) { maxpass = val; } ///< Set the maximum number of passes
|
void setMaxPass(int4 val) { maxpass = val; } ///< Set the maximum number of passes
|
||||||
void finishPass(void) { numpasses += 1; } ///< Mark that an analysis pass has completed
|
void finishPass(void) { numpasses += 1; } ///< Mark that an analysis pass has completed
|
||||||
void sortTrials(void) { sort(trial.begin(),trial.end()); } ///< Sort the trials in formal parameter order
|
void sortTrials(void) { sort(trial.begin(),trial.end()); } ///< Sort the trials in formal parameter order
|
||||||
|
void sortFixedPosition(void) {sort(trial.begin(),trial.end(),ParamTrial::fixedPositionCompare);} ///< sort the trials by fixed position then <
|
||||||
void deleteUnusedTrials(void); ///< Remove trials that were found not to be parameters
|
void deleteUnusedTrials(void); ///< Remove trials that were found not to be parameters
|
||||||
void splitTrial(int4 i,int4 sz); ///< Split the given trial in two
|
void splitTrial(int4 i,int4 sz); ///< Split the given trial in two
|
||||||
void joinTrial(int4 slot,const Address &addr,int4 sz); ///< Join adjacent parameter trials
|
void joinTrial(int4 slot,const Address &addr,int4 sz); ///< Join adjacent parameter trials
|
||||||
|
@ -330,8 +334,6 @@ public:
|
||||||
/// \param addr is the new range's starting address
|
/// \param addr is the new range's starting address
|
||||||
/// \param sz is the new range's size in bytes
|
/// \param sz is the new range's size in bytes
|
||||||
void shrink(int4 i,const Address &addr,int4 sz) { trial[i].setAddress(addr,sz); }
|
void shrink(int4 i,const Address &addr,int4 sz) { trial[i].setAddress(addr,sz); }
|
||||||
|
|
||||||
void sortFixedPosition(void) {sort(trial.begin(),trial.end(),ParamTrial::fixedPositionCompare);} ///< sort the trials by fixed position then <
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A special space for encoding FuncCallSpecs
|
/// \brief A special space for encoding FuncCallSpecs
|
||||||
|
@ -616,6 +618,7 @@ public:
|
||||||
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
||||||
virtual ~ParamListStandard(void);
|
virtual ~ParamListStandard(void);
|
||||||
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
||||||
|
bool isBigEndian(void) const { return entry.front().getSpace()->isBigEndian(); } ///< Return \b true if resources are big endian
|
||||||
void extractTiles(vector<const ParamEntry *> &tiles,type_class type) const; ///< Get registers of given storage class
|
void extractTiles(vector<const ParamEntry *> &tiles,type_class type) const; ///< Get registers of given storage class
|
||||||
const ParamEntry *getStackEntry(void) const; ///< Get the stack entry
|
const ParamEntry *getStackEntry(void) const; ///< Get the stack entry
|
||||||
uint4 assignAddressFallback(type_class resource,Datatype *tp,bool matchExact,vector<int4> &status,
|
uint4 assignAddressFallback(type_class resource,Datatype *tp,bool matchExact,vector<int4> &status,
|
||||||
|
|
|
@ -609,12 +609,7 @@ AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandar
|
||||||
action = new HiddenReturnAssign(res,hiddenret_specialreg);
|
action = new HiddenReturnAssign(res,hiddenret_specialreg);
|
||||||
}
|
}
|
||||||
else if (elemId == ELEM_JOIN_PER_PRIMITIVE) {
|
else if (elemId == ELEM_JOIN_PER_PRIMITIVE) {
|
||||||
bool consumeMostSig = false;
|
action = new MultiMemberAssign(TYPECLASS_GENERAL,false,res->isBigEndian(),res);
|
||||||
AddrSpace *spc = res->getSpacebase();
|
|
||||||
if (spc != (AddrSpace *)0 && spc->isBigEndian()) {
|
|
||||||
consumeMostSig = true;
|
|
||||||
}
|
|
||||||
action = new MultiMemberAssign(TYPECLASS_GENERAL,false,consumeMostSig,res);
|
|
||||||
}
|
}
|
||||||
else if (elemId == ELEM_JOIN_DUAL_CLASS) {
|
else if (elemId == ELEM_JOIN_DUAL_CLASS) {
|
||||||
action = new MultiSlotDualAssign(res);
|
action = new MultiSlotDualAssign(res);
|
||||||
|
@ -676,6 +671,28 @@ AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListSta
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Truncate a tiling by a given number of bytes
|
||||||
|
///
|
||||||
|
/// The extra bytes are considered padding and removed from one end of the tiling.
|
||||||
|
/// The bytes removed depend on the endianness and how the data is justified within the tiling.
|
||||||
|
/// \param pieces is the tiling of 2 or more Varnodes
|
||||||
|
/// \param offset is the given number of bytes to truncate
|
||||||
|
/// \param isBigEndian is true for big endian architectures
|
||||||
|
/// \param consumeMostSig is true if the first tile in the list covers the most significant bytes
|
||||||
|
/// \param justifyRight is true if the data is right justified within the tiling
|
||||||
|
void AssignAction::justifyPieces(vector<VarnodeData> &pieces,int4 offset,bool isBigEndian,
|
||||||
|
bool consumeMostSig,bool justifyRight)
|
||||||
|
{
|
||||||
|
bool addOffset = isBigEndian ^ consumeMostSig ^ justifyRight;
|
||||||
|
int pos = justifyRight ? 0 : pieces.size() - 1;
|
||||||
|
|
||||||
|
VarnodeData &vndata(pieces[pos]);
|
||||||
|
if (addOffset) {
|
||||||
|
vndata.offset += offset;
|
||||||
|
}
|
||||||
|
vndata.size -= offset;
|
||||||
|
}
|
||||||
|
|
||||||
void GotoStack::initializeEntry(void)
|
void GotoStack::initializeEntry(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -784,6 +801,7 @@ MultiSlotAssign::MultiSlotAssign(const ParamListStandard *res)
|
||||||
: AssignAction(res)
|
: AssignAction(res)
|
||||||
{
|
{
|
||||||
resourceType = TYPECLASS_GENERAL; // Join general purpose registers
|
resourceType = TYPECLASS_GENERAL; // Join general purpose registers
|
||||||
|
isBigEndian = res->isBigEndian();
|
||||||
fillinOutputActive = true;
|
fillinOutputActive = true;
|
||||||
uint4 listType = res->getType();
|
uint4 listType = res->getType();
|
||||||
// Consume from stack on input parameters by default
|
// Consume from stack on input parameters by default
|
||||||
|
@ -791,8 +809,7 @@ MultiSlotAssign::MultiSlotAssign(const ParamListStandard *res)
|
||||||
consumeMostSig = false;
|
consumeMostSig = false;
|
||||||
enforceAlignment = false;
|
enforceAlignment = false;
|
||||||
justifyRight = false;
|
justifyRight = false;
|
||||||
AddrSpace *spc = res->getSpacebase();
|
if (isBigEndian) {
|
||||||
if (spc != (AddrSpace *)0 && spc->isBigEndian()) {
|
|
||||||
consumeMostSig = true;
|
consumeMostSig = true;
|
||||||
justifyRight = true;
|
justifyRight = true;
|
||||||
}
|
}
|
||||||
|
@ -803,6 +820,7 @@ MultiSlotAssign::MultiSlotAssign(type_class store,bool stack,bool mostSig,bool a
|
||||||
: AssignAction(res)
|
: AssignAction(res)
|
||||||
{
|
{
|
||||||
resourceType = store;
|
resourceType = store;
|
||||||
|
isBigEndian = res->isBigEndian();
|
||||||
fillinOutputActive = true;
|
fillinOutputActive = true;
|
||||||
consumeFromStack = stack;
|
consumeFromStack = stack;
|
||||||
consumeMostSig = mostSig;
|
consumeMostSig = mostSig;
|
||||||
|
@ -870,12 +888,8 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i
|
||||||
tmp.offset = addr.getOffset();
|
tmp.offset = addr.getOffset();
|
||||||
tmp.size = dt->getSize();
|
tmp.size = dt->getSize();
|
||||||
}
|
}
|
||||||
else if (justifyRight) {
|
|
||||||
pieces.front().offset += -sizeLeft; // Initial bytes of first entry are padding
|
|
||||||
pieces.front().size += sizeLeft;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
pieces.back().size += sizeLeft;
|
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = tmpStatus; // Commit resource usage for all the pieces
|
status = tmpStatus; // Commit resource usage for all the pieces
|
||||||
|
@ -931,7 +945,10 @@ bool MultiSlotAssign::fillinOutputMap(ParamActive *active) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (count > 0);
|
if (count==0) return false;
|
||||||
|
if (consumeMostSig)
|
||||||
|
active->setJoinReverse();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiSlotAssign::decode(Decoder &decoder)
|
void MultiSlotAssign::decode(Decoder &decoder)
|
||||||
|
@ -1023,7 +1040,10 @@ bool MultiMemberAssign::fillinOutputMap(ParamActive *active) const
|
||||||
return false; // Entry must be justified
|
return false; // Entry must be justified
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
return (count > 0);
|
if (count==0) return false;
|
||||||
|
if (consumeMostSig)
|
||||||
|
active->setJoinReverse();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiMemberAssign::decode(Decoder &decoder)
|
void MultiMemberAssign::decode(Decoder &decoder)
|
||||||
|
@ -1119,14 +1139,14 @@ int4 MultiSlotDualAssign::getTileClass(const PrimitiveExtractor &primitives,int4
|
||||||
MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res)
|
MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res)
|
||||||
: AssignAction(res)
|
: AssignAction(res)
|
||||||
{
|
{
|
||||||
|
isBigEndian = res->isBigEndian();
|
||||||
fillinOutputActive = true;
|
fillinOutputActive = true;
|
||||||
baseType = TYPECLASS_GENERAL; // Tile from general purpose registers
|
baseType = TYPECLASS_GENERAL; // Tile from general purpose registers
|
||||||
altType = TYPECLASS_FLOAT; // Use specialized registers for floating-point components
|
altType = TYPECLASS_FLOAT; // Use specialized registers for floating-point components
|
||||||
consumeFromStack = false;
|
consumeFromStack = false;
|
||||||
consumeMostSig = false;
|
consumeMostSig = false;
|
||||||
justifyRight = false;
|
justifyRight = false;
|
||||||
AddrSpace *spc = res->getSpacebase();
|
if (isBigEndian) {
|
||||||
if (spc != (AddrSpace *)0 && spc->isBigEndian()) {
|
|
||||||
consumeMostSig = true;
|
consumeMostSig = true;
|
||||||
justifyRight = true;
|
justifyRight = true;
|
||||||
}
|
}
|
||||||
|
@ -1139,6 +1159,7 @@ MultiSlotDualAssign::MultiSlotDualAssign(type_class baseStore,type_class altStor
|
||||||
bool mostSig,bool justRight,bool fillAlt,const ParamListStandard *res)
|
bool mostSig,bool justRight,bool fillAlt,const ParamListStandard *res)
|
||||||
: AssignAction(res)
|
: AssignAction(res)
|
||||||
{
|
{
|
||||||
|
isBigEndian = res->isBigEndian();
|
||||||
fillinOutputActive = true;
|
fillinOutputActive = true;
|
||||||
baseType = baseStore;
|
baseType = baseStore;
|
||||||
altType = altStore;
|
altType = altStore;
|
||||||
|
@ -1209,13 +1230,7 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro
|
||||||
pieces.back().size = sizeLeft;
|
pieces.back().size = sizeLeft;
|
||||||
}
|
}
|
||||||
if (sizeLeft < 0) { // Have odd data-type size
|
if (sizeLeft < 0) { // Have odd data-type size
|
||||||
if (justifyRight) {
|
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||||
pieces.front().offset += -sizeLeft; // Initial bytes of first entry are padding
|
|
||||||
pieces.front().size += sizeLeft;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pieces.back().size += sizeLeft;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
status = tmpStatus; // Commit resource usage for all the pieces
|
status = tmpStatus; // Commit resource usage for all the pieces
|
||||||
res.flags = 0;
|
res.flags = 0;
|
||||||
|
@ -1276,8 +1291,10 @@ bool MultiSlotDualAssign::fillinOutputMap(ParamActive *active) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (count > 0);
|
if (count==0) return false;
|
||||||
|
if (consumeMostSig)
|
||||||
|
active->setJoinReverse();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiSlotDualAssign::decode(Decoder &decoder)
|
void MultiSlotDualAssign::decode(Decoder &decoder)
|
||||||
|
|
|
@ -319,6 +319,7 @@ public:
|
||||||
static AssignAction *decodeAction(Decoder &decoder,const ParamListStandard *res);
|
static AssignAction *decodeAction(Decoder &decoder,const ParamListStandard *res);
|
||||||
static AssignAction *decodePrecondition(Decoder &decoder, const ParamListStandard *res);
|
static AssignAction *decodePrecondition(Decoder &decoder, const ParamListStandard *res);
|
||||||
static AssignAction *decodeSideeffect(Decoder &decoder,const ParamListStandard *res);
|
static AssignAction *decodeSideeffect(Decoder &decoder,const ParamListStandard *res);
|
||||||
|
static void justifyPieces(vector<VarnodeData> &pieces,int4 offset,bool isBigEndian,bool consumeMostSig,bool justifyRight);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Action assigning a parameter Address from the next available stack location
|
/// \brief Action assigning a parameter Address from the next available stack location
|
||||||
|
@ -355,6 +356,7 @@ public:
|
||||||
/// Consumption can spill over onto the stack if desired.
|
/// Consumption can spill over onto the stack if desired.
|
||||||
class MultiSlotAssign : public AssignAction {
|
class MultiSlotAssign : public AssignAction {
|
||||||
type_class resourceType; ///< Resource list from which to consume
|
type_class resourceType; ///< Resource list from which to consume
|
||||||
|
bool isBigEndian; ///< True for big endian architectures
|
||||||
bool consumeFromStack; ///< True if resources should be consumed from the stack
|
bool consumeFromStack; ///< True if resources should be consumed from the stack
|
||||||
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
|
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
|
||||||
bool enforceAlignment; ///< True if register resources are discarded to match alignment
|
bool enforceAlignment; ///< True if register resources are discarded to match alignment
|
||||||
|
@ -399,6 +401,7 @@ public:
|
||||||
class MultiSlotDualAssign : public AssignAction {
|
class MultiSlotDualAssign : public AssignAction {
|
||||||
type_class baseType; ///< Resource list from which to consume general tiles
|
type_class baseType; ///< Resource list from which to consume general tiles
|
||||||
type_class altType; ///< Resource list from which to consume alternate tiles
|
type_class altType; ///< Resource list from which to consume alternate tiles
|
||||||
|
bool isBigEndian; ///< True for big endian architectures
|
||||||
bool consumeFromStack; ///< True if resources should be consumed from the stack
|
bool consumeFromStack; ///< True if resources should be consumed from the stack
|
||||||
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
|
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
|
||||||
bool justifyRight; ///< True if initial bytes are padding for odd data-type sizes
|
bool justifyRight; ///< True if initial bytes are padding for odd data-type sizes
|
||||||
|
|
|
@ -258,6 +258,52 @@ TEST(paramstore_x64) {
|
||||||
ASSERT(theEnviron.test(model, "doubleintintint func(void);", "RAX,RDI"));
|
ASSERT(theEnviron.test(model, "doubleintintint func(void);", "RAX,RDI"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(paramstore_ppc64be_stdcall) {
|
||||||
|
ProtoModel *model = theEnviron.getModel("PowerPC:BE:64:default:default","__stdcall");
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,float4 b,float8 c);","void,r3:4,join f1,f2"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,int8 b,float8 c);","void,f1,r4,f2"));
|
||||||
|
theEnviron.parseType(model,"struct sparm { int4 a; float8 dd; };");
|
||||||
|
|
||||||
|
string proto= "void func(int4 c,float8 ff,int4 d,float16 ld,sparm s,float8 gg,sparm t,int4 e,float8 hh);";
|
||||||
|
string res="void,r3:4,f1,r5:4,join f2 f3,join r8 r9,f4,stack70:16,stack84:4,f5";
|
||||||
|
ASSERT(theEnviron.test(model,proto,res));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(paramstore_mips32be_stdcall) {
|
||||||
|
ProtoModel *model = theEnviron.getModel("MIPS:BE:32:default:default","__stdcall");
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int2 a,int4 b,char c);","void,a0:2,a1,a2:1"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,float8 b);","void,f12_13,f14_15"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,float4 b);","void,f12,f14"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,float8 b);","void,f12,f14_15"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,float4 b);","void,f12_13,f14"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,int4 b,int4 c,int4 d);","void,a0,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,int4 b,float8 c);","void,f12_13,a2,stack10:8"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,int4 b,int4 c);","void,f12_13,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,int4 b,int4 c);","void,f12,a1,a2"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,int4 b,int4 c,float8 d);","void,a0,a1,a2,stack10:8"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,int4 b,int4 c,float4 d);","void,a0,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,int4 b,float8 c);","void,a0,a1,join a2 a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,float8 b);","void,a0,join a2 a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,float4 b,float4 c,float4 d);","void,f12,f14,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,int4 b,float4 c,int4 d);","void,f12,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float8 a,float4 b,float4 c);","void,f12_13,f14,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(float4 a,float4 b,float8 c);","void,f12,f14,join a2 a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,float4 b,int4 c,float4 d);","void,a0,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,float4 b,int4 c,int4 d);","void,a0,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"void func(int4 a,int4 b,float4 c,int4 d);","void,a0,a1,a2,a3"));
|
||||||
|
ASSERT(theEnviron.test(model,"int4 func(void);","v0"));
|
||||||
|
ASSERT(theEnviron.test(model, "float4 func(void);", "f0"));
|
||||||
|
ASSERT(theEnviron.test(model, "float8 func(void);", "f0_1"));
|
||||||
|
theEnviron.parseType(model,"struct onefieldstruct { int4 a; };");
|
||||||
|
theEnviron.parseType(model,"struct twofieldstruct { int4 a; int4 b; };");
|
||||||
|
ASSERT(theEnviron.test(model, "onefieldstruct func(int4 a);", "v0,a0,a1"));
|
||||||
|
ASSERT(theEnviron.test(model, "twofieldstruct func(int4 a);", "v0,a0,a1"));
|
||||||
|
ASSERT(theEnviron.test(model, "void func(twofieldstruct a);", "void,join a0 a1"));
|
||||||
|
|
||||||
|
theEnviron.parseType(model,"struct intdouble { int4 a; float8 b; };");
|
||||||
|
ASSERT(theEnviron.test(model, "void func(intdouble a);", "void,join a0 a1 a2 a3"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(paramstore_aarch64_cdecl) {
|
TEST(paramstore_aarch64_cdecl) {
|
||||||
ProtoModel *model = theEnviron.getModel("AARCH64:LE:64:v8A:default","__cdecl");
|
ProtoModel *model = theEnviron.getModel("AARCH64:LE:64:v8A:default","__cdecl");
|
||||||
ASSERT(theEnviron.test(model, "void func(int2 a,int4 b,int1 c);", "void,w0:2,w1,w2:1"));
|
ASSERT(theEnviron.test(model, "void func(int2 a,int4 b,int1 c);", "void,w0:2,w1,w2:1"));
|
||||||
|
|
|
@ -138,7 +138,7 @@ TEST(cast_pointer) {
|
||||||
TypeTestEnvironment::build();
|
TypeTestEnvironment::build();
|
||||||
ASSERT(castPrinted(CPUI_COPY,parse("uint4 *"),parse("int4 *")));
|
ASSERT(castPrinted(CPUI_COPY,parse("uint4 *"),parse("int4 *")));
|
||||||
ASSERT(!castPrinted(CPUI_COPY,parse("void *"),parse("float4 *")));
|
ASSERT(!castPrinted(CPUI_COPY,parse("void *"),parse("float4 *")));
|
||||||
ASSERT(castPrinted(CPUI_COPY,parse("int2 *"),parse("void *")));
|
ASSERT(!castPrinted(CPUI_COPY,parse("int2 *"),parse("void *")));
|
||||||
Datatype *typedefInt = types->getBase(4,TYPE_INT,"myint4");
|
Datatype *typedefInt = types->getBase(4,TYPE_INT,"myint4");
|
||||||
Datatype *typedefPtr = types->getTypePointer(8,typedefInt,1);
|
Datatype *typedefPtr = types->getTypePointer(8,typedefInt,1);
|
||||||
ASSERT(!castPrinted(CPUI_COPY,typedefPtr,parse("int4 *")));
|
ASSERT(!castPrinted(CPUI_COPY,typedefPtr,parse("int4 *")));
|
||||||
|
|
|
@ -167,6 +167,13 @@ public class ParamListStandard implements ParamList {
|
||||||
return entry[index];
|
return entry[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if resources are from a big endian address space
|
||||||
|
*/
|
||||||
|
public boolean isBigEndian() {
|
||||||
|
return entry[0].isBigEndian();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignMap(PrototypePieces proto, DataTypeManager dtManager,
|
public void assignMap(PrototypePieces proto, DataTypeManager dtManager,
|
||||||
ArrayList<ParameterPieces> res, boolean addAutoParams) {
|
ArrayList<ParameterPieces> res, boolean addAutoParams) {
|
||||||
|
|
|
@ -18,11 +18,14 @@ package ghidra.program.model.lang.protorules;
|
||||||
import static ghidra.program.model.pcode.ElementId.*;
|
import static ghidra.program.model.pcode.ElementId.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.pcode.Encoder;
|
import ghidra.program.model.pcode.Encoder;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.xml.*;
|
import ghidra.xml.*;
|
||||||
|
|
||||||
|
@ -124,8 +127,7 @@ public abstract class AssignAction {
|
||||||
action = new HiddenReturnAssign(res, HIDDENRET_SPECIALREG);
|
action = new HiddenReturnAssign(res, HIDDENRET_SPECIALREG);
|
||||||
}
|
}
|
||||||
else if (nm.equals(ELEM_JOIN_PER_PRIMITIVE.name())) {
|
else if (nm.equals(ELEM_JOIN_PER_PRIMITIVE.name())) {
|
||||||
boolean consumeMostSig = res.getEntry(0).isBigEndian();
|
action = new MultiMemberAssign(StorageClass.GENERAL, false, res.isBigEndian(), res);
|
||||||
action = new MultiMemberAssign(StorageClass.GENERAL, false, consumeMostSig, res);
|
|
||||||
}
|
}
|
||||||
else if (nm.equals(ELEM_JOIN_DUAL_CLASS.name())) {
|
else if (nm.equals(ELEM_JOIN_DUAL_CLASS.name())) {
|
||||||
action = new MultiSlotDualAssign(res);
|
action = new MultiSlotDualAssign(res);
|
||||||
|
@ -191,4 +193,20 @@ public abstract class AssignAction {
|
||||||
action.restoreXml(parser);
|
action.restoreXml(parser);
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void justifyPieces(ArrayList<Varnode> pieces, int offset, boolean isBigEndian,
|
||||||
|
boolean consumeMostSig,
|
||||||
|
boolean justifyRight) {
|
||||||
|
boolean addOffset = isBigEndian ^ consumeMostSig ^ justifyRight;
|
||||||
|
int pos = justifyRight ? 0 : pieces.size() - 1;
|
||||||
|
|
||||||
|
Varnode vn = pieces.get(pos);
|
||||||
|
Address addr = vn.getAddress();
|
||||||
|
if (addOffset) {
|
||||||
|
addr = addr.add(offset);
|
||||||
|
}
|
||||||
|
int sz = vn.getSize() - offset;
|
||||||
|
vn = new Varnode(addr, sz);
|
||||||
|
pieces.set(pos, vn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
|
@ -41,6 +40,7 @@ import ghidra.xml.*;
|
||||||
*/
|
*/
|
||||||
public class MultiSlotAssign extends AssignAction {
|
public class MultiSlotAssign extends AssignAction {
|
||||||
private StorageClass resourceType; // Resource list from which to consume
|
private StorageClass resourceType; // Resource list from which to consume
|
||||||
|
private boolean isBigEndian; // True for big endian architectures
|
||||||
private boolean consumeFromStack; // True if resources should be consumed from the stack
|
private boolean consumeFromStack; // True if resources should be consumed from the stack
|
||||||
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
|
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
|
||||||
private boolean enforceAlignment; // True if register resources are discarded to match alignment
|
private boolean enforceAlignment; // True if register resources are discarded to match alignment
|
||||||
|
@ -74,6 +74,7 @@ public class MultiSlotAssign extends AssignAction {
|
||||||
*/
|
*/
|
||||||
protected MultiSlotAssign(ParamListStandard res) {
|
protected MultiSlotAssign(ParamListStandard res) {
|
||||||
super(res);
|
super(res);
|
||||||
|
isBigEndian = res.isBigEndian();
|
||||||
resourceType = StorageClass.GENERAL; // Join general purpose registers
|
resourceType = StorageClass.GENERAL; // Join general purpose registers
|
||||||
consumeFromStack = !(res instanceof ParamListStandardOut); // Spill into stack by default
|
consumeFromStack = !(res instanceof ParamListStandardOut); // Spill into stack by default
|
||||||
consumeMostSig = false;
|
consumeMostSig = false;
|
||||||
|
@ -81,7 +82,7 @@ public class MultiSlotAssign extends AssignAction {
|
||||||
justifyRight = false;
|
justifyRight = false;
|
||||||
adjacentEntries = true;
|
adjacentEntries = true;
|
||||||
allowBackfill = false;
|
allowBackfill = false;
|
||||||
if (res.getEntry(0).isBigEndian()) {
|
if (isBigEndian) {
|
||||||
consumeMostSig = true;
|
consumeMostSig = true;
|
||||||
justifyRight = true;
|
justifyRight = true;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +93,7 @@ public class MultiSlotAssign extends AssignAction {
|
||||||
boolean justRight, boolean backfill, ParamListStandard res)
|
boolean justRight, boolean backfill, ParamListStandard res)
|
||||||
throws InvalidInputException {
|
throws InvalidInputException {
|
||||||
super(res);
|
super(res);
|
||||||
|
isBigEndian = res.isBigEndian();
|
||||||
resourceType = store;
|
resourceType = store;
|
||||||
consumeFromStack = stack;
|
consumeFromStack = stack;
|
||||||
consumeMostSig = mostSig;
|
consumeMostSig = mostSig;
|
||||||
|
@ -240,20 +242,8 @@ public class MultiSlotAssign extends AssignAction {
|
||||||
// Floating-point register holding extended lower precision value
|
// Floating-point register holding extended lower precision value
|
||||||
onePieceJoin = true; // Treat as "join" of full size register
|
onePieceJoin = true; // Treat as "join" of full size register
|
||||||
}
|
}
|
||||||
else if (justifyRight) {
|
|
||||||
// Initial bytes are padding
|
|
||||||
Varnode vn = pieces.get(0);
|
|
||||||
Address addr = vn.getAddress().add(-sizeLeft);
|
|
||||||
int sz = vn.getSize() + sizeLeft;
|
|
||||||
vn = new Varnode(addr, sz);
|
|
||||||
pieces.set(0, vn);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
int end = pieces.size() - 1;
|
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||||
Varnode vn = pieces.get(end);
|
|
||||||
int sz = vn.getSize() + sizeLeft;
|
|
||||||
vn = new Varnode(vn.getAddress(), sz);
|
|
||||||
pieces.set(end, vn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
||||||
|
@ -265,10 +255,10 @@ public class MultiSlotAssign extends AssignAction {
|
||||||
@Override
|
@Override
|
||||||
public void encode(Encoder encoder) throws IOException {
|
public void encode(Encoder encoder) throws IOException {
|
||||||
encoder.openElement(ELEM_JOIN);
|
encoder.openElement(ELEM_JOIN);
|
||||||
if (resource.getEntry(0).isBigEndian() != justifyRight) {
|
if (resource.isBigEndian() != justifyRight) {
|
||||||
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
||||||
}
|
}
|
||||||
if (resource.getEntry(0).isBigEndian() != consumeMostSig) {
|
if (resource.isBigEndian() != consumeMostSig) {
|
||||||
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
||||||
}
|
}
|
||||||
if (resourceType != StorageClass.GENERAL) {
|
if (resourceType != StorageClass.GENERAL) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
|
@ -42,6 +41,7 @@ import ghidra.xml.*;
|
||||||
public class MultiSlotDualAssign extends AssignAction {
|
public class MultiSlotDualAssign extends AssignAction {
|
||||||
private StorageClass baseType; // Resource list from which to consume general tiles
|
private StorageClass baseType; // Resource list from which to consume general tiles
|
||||||
private StorageClass altType; // Resource list from which to consume alternate tiles
|
private StorageClass altType; // Resource list from which to consume alternate tiles
|
||||||
|
private boolean isBigEndian; // True for big endian architectures
|
||||||
private boolean consumeFromStack; // True if resources can be consumed from the stack
|
private boolean consumeFromStack; // True if resources can be consumed from the stack
|
||||||
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
|
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
|
||||||
private boolean justifyRight; // True if initial bytes are padding for odd data-type sizes
|
private boolean justifyRight; // True if initial bytes are padding for odd data-type sizes
|
||||||
|
@ -151,12 +151,13 @@ public class MultiSlotDualAssign extends AssignAction {
|
||||||
*/
|
*/
|
||||||
protected MultiSlotDualAssign(ParamListStandard res) {
|
protected MultiSlotDualAssign(ParamListStandard res) {
|
||||||
super(res);
|
super(res);
|
||||||
|
isBigEndian = res.isBigEndian();
|
||||||
baseType = StorageClass.GENERAL; // Tile from general purpose registers
|
baseType = StorageClass.GENERAL; // Tile from general purpose registers
|
||||||
altType = StorageClass.FLOAT; // Use specialized registers for floating-point components
|
altType = StorageClass.FLOAT; // Use specialized registers for floating-point components
|
||||||
consumeFromStack = false;
|
consumeFromStack = false;
|
||||||
consumeMostSig = false;
|
consumeMostSig = false;
|
||||||
justifyRight = false;
|
justifyRight = false;
|
||||||
if (res.getEntry(0).isBigEndian()) {
|
if (isBigEndian) {
|
||||||
consumeMostSig = true;
|
consumeMostSig = true;
|
||||||
justifyRight = true;
|
justifyRight = true;
|
||||||
}
|
}
|
||||||
|
@ -180,6 +181,7 @@ public class MultiSlotDualAssign extends AssignAction {
|
||||||
boolean mostSig, boolean justRight, boolean fillAlt, ParamListStandard res)
|
boolean mostSig, boolean justRight, boolean fillAlt, ParamListStandard res)
|
||||||
throws InvalidInputException {
|
throws InvalidInputException {
|
||||||
super(res);
|
super(res);
|
||||||
|
isBigEndian = res.isBigEndian();
|
||||||
baseType = baseStore;
|
baseType = baseStore;
|
||||||
altType = altStore;
|
altType = altStore;
|
||||||
consumeFromStack = stack;
|
consumeFromStack = stack;
|
||||||
|
@ -294,21 +296,7 @@ public class MultiSlotDualAssign extends AssignAction {
|
||||||
pieces.add(vn);
|
pieces.add(vn);
|
||||||
}
|
}
|
||||||
if (sizeLeft < 0) { // Have odd data-type size
|
if (sizeLeft < 0) { // Have odd data-type size
|
||||||
if (justifyRight) {
|
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||||
// Initial bytes of first entry are padding
|
|
||||||
Varnode vn = pieces.get(0);
|
|
||||||
Address addr = vn.getAddress().add(-sizeLeft);
|
|
||||||
int sz = vn.getSize() + sizeLeft;
|
|
||||||
vn = new Varnode(addr, sz);
|
|
||||||
pieces.set(0, vn);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int end = pieces.size() - 1;
|
|
||||||
Varnode vn = pieces.get(end);
|
|
||||||
int sz = vn.getSize() + sizeLeft;
|
|
||||||
vn = new Varnode(vn.getAddress(), sz);
|
|
||||||
pieces.set(end, vn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
||||||
res.type = dt;
|
res.type = dt;
|
||||||
|
@ -319,10 +307,10 @@ public class MultiSlotDualAssign extends AssignAction {
|
||||||
@Override
|
@Override
|
||||||
public void encode(Encoder encoder) throws IOException {
|
public void encode(Encoder encoder) throws IOException {
|
||||||
encoder.openElement(ELEM_JOIN_DUAL_CLASS);
|
encoder.openElement(ELEM_JOIN_DUAL_CLASS);
|
||||||
if (resource.getEntry(0).isBigEndian() != justifyRight) {
|
if (resource.isBigEndian() != justifyRight) {
|
||||||
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
||||||
}
|
}
|
||||||
if (resource.getEntry(0).isBigEndian() != consumeMostSig) {
|
if (resource.isBigEndian() != consumeMostSig) {
|
||||||
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
||||||
}
|
}
|
||||||
if (baseType != StorageClass.GENERAL) {
|
if (baseType != StorageClass.GENERAL) {
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* ###
|
||||||
|
* 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 org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MipsPrototypeModelTest extends AbstractProtoModelTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
buildArchitecture("MIPS:BE:32:default:default");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tesStdCall() throws Exception {
|
||||||
|
PrototypeModel model = cspec.getCallingConvention("__stdcall");
|
||||||
|
|
||||||
|
test(model, "void func(short a,int b,char c)", "void,a0:2,a1,a2:1");
|
||||||
|
test(model, "void func(double a,double b)", "void,f12_13,f14_15");
|
||||||
|
test(model, "void func(float a,float b)", "void,f12,f14");
|
||||||
|
test(model, "void func(float a,double b)", "void,f12,f14_15");
|
||||||
|
test(model, "void func(double a,float b)", "void,f12_13,f14");
|
||||||
|
test(model, "void func(int a,int b,int c,int d)", "void,a0,a1,a2,a3");
|
||||||
|
test(model, "void func(double a,int b,double c)", "void,f12_13,a2,stack10:8");
|
||||||
|
test(model, "void func(double a,int b,int c)", "void,f12_13,a2,a3");
|
||||||
|
test(model, "void func(float a,int b,int c)", "void,f12,a1,a2");
|
||||||
|
test(model, "void func(int a,int b,int c,double d)", "void,a0,a1,a2,stack10:8");
|
||||||
|
test(model, "void func(int a,int b,int c,float d)", "void,a0,a1,a2,a3");
|
||||||
|
test(model, "void func(int a,int b,double c)", "void,a0,a1,join a2 a3");
|
||||||
|
test(model, "void func(int a,double b)", "void,a0,join a2 a3");
|
||||||
|
test(model, "void func(float a,float b,float c,float d)", "void,f12,f14,a2,a3");
|
||||||
|
test(model, "void func(float a,int b,float c,int d)", "void,f12,a1,a2,a3");
|
||||||
|
test(model, "void func(double a,float b,float c)", "void,f12_13,f14,a3");
|
||||||
|
test(model, "void func(float a,float b,double c)", "void,f12,f14,join a2 a3");
|
||||||
|
test(model, "void func(int a,float b,int c,float d)", "void,a0,a1,a2,a3");
|
||||||
|
test(model, "void func(int a,float b,int c,int d)", "void,a0,a1,a2,a3");
|
||||||
|
test(model, "void func(int a,int b,float c,int d)", "void,a0,a1,a2,a3");
|
||||||
|
|
||||||
|
test(model, "int func(void)", "v0");
|
||||||
|
test(model, "float func(void)", "f0");
|
||||||
|
test(model, "double func(void)", "f0_1");
|
||||||
|
parseStructure("onefieldstruct", "int");
|
||||||
|
parseStructure("twofieldstruct", "int,int");
|
||||||
|
test(model, "onefieldstruct func(int a)", "v0,a0,a1");
|
||||||
|
test(model, "twofieldstruct func(int a)", "v0,a0,a1");
|
||||||
|
test(model, "void func(twofieldstruct a)", "void,join a0 a1");
|
||||||
|
|
||||||
|
parseStructure("intdouble", "int,double");
|
||||||
|
test(model, "void func(intdouble a)", "void,join a0 a1 a2 a3");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* ###
|
||||||
|
* 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 org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PowerPCPrototypeModelTest extends AbstractProtoModelTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
buildArchitecture("PowerPC:BE:64:default:default");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tesStdCall() throws Exception {
|
||||||
|
PrototypeModel model = cspec.getCallingConvention("__stdcall");
|
||||||
|
test(model, "void func(int a,float b,double c)", "void,r3:4,join f1,f2");
|
||||||
|
test(model, "void func(double a,long b,double c)", "void,f1,r4,f2");
|
||||||
|
|
||||||
|
parseStructure("sparm", "int,double");
|
||||||
|
|
||||||
|
String proto =
|
||||||
|
"void func(int c,double ff,int d,float16 ld,sparm s,double gg,sparm t,int e,double hh)";
|
||||||
|
String res = "void,r3:4,f1,r5:4,join f2 f3,join r8 r9,f4,stack70:16,stack84:4,f5";
|
||||||
|
test(model, proto, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue