mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
GP-3873 Data-type alignment support in decompiler
This commit is contained in:
parent
6508088623
commit
64a58bdeab
@ -31,6 +31,7 @@ src/decompile/datatests/forloop_withskip.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/impliedfield.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/indproto.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/injectoverride.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/longdouble.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/loopcomment.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/lzcount.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/mixfloatint.xml||GHIDRA||||END|
|
||||
|
@ -1380,6 +1380,7 @@ void Architecture::init(DocumentStorage &store)
|
||||
buildDatabase(store);
|
||||
|
||||
restoreFromSpec(store);
|
||||
buildCoreTypes(store);
|
||||
print->initializeFromArchitecture();
|
||||
symboltab->adjustCaches(); // In case the specs created additional address spaces
|
||||
buildSymbols(store);
|
||||
|
@ -285,11 +285,16 @@ protected:
|
||||
/// \brief Build the data-type factory/container
|
||||
///
|
||||
/// Build the TypeFactory object specific to \b this Architecture and
|
||||
/// prepopulate it with the \e core types. Core types may be pulled
|
||||
/// from the configuration information, or default core types are used.
|
||||
/// prepopulate it with the \e core types.
|
||||
/// \param store contains possible configuration information
|
||||
virtual void buildTypegrp(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Add core primitive data-types
|
||||
///
|
||||
/// Core types may be pulled from the configuration information, or default core types are used.
|
||||
/// \param store contains possible configuration information
|
||||
virtual void buildCoreTypes(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the comment database
|
||||
///
|
||||
/// Build the container that holds comments in \b this Architecture.
|
||||
|
@ -163,37 +163,109 @@ public:
|
||||
FlowBlock *getCopyMap(void) const { return copymap; } ///< Get the mapped FlowBlock
|
||||
const FlowBlock *getParent(void) const { return (const FlowBlock *) parent; } ///< Get the parent FlowBlock of \b this
|
||||
uint4 getFlags(void) const { return flags; } ///< Get the block_flags properties
|
||||
virtual Address getStart(void) const { return Address(); } ///< Get the starting address of code in \b this FlowBlock
|
||||
virtual Address getStop(void) const { return Address(); } ///< Get the ending address of code in \b this FlowBlock
|
||||
virtual block_type getType(void) const { return t_plain; } ///< Get the FlowBlock type of \b this
|
||||
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; } ///< Get the i-th component block
|
||||
virtual void markUnstructured(void) {} ///< Mark target blocks of any unstructured edges
|
||||
|
||||
/// \brief Get the starting address of code in \b this FlowBlock
|
||||
///
|
||||
/// If \b this is a basic block, the first address of (the original) instructions in the block
|
||||
/// is returned. Otherwise, an \e invalid address is returned.
|
||||
/// \return the starting address or an \e invalid address
|
||||
virtual Address getStart(void) const { return Address(); }
|
||||
|
||||
/// \brief Get the ending address of code in \b this FlowBlock
|
||||
///
|
||||
/// If \b this is a basic block, the last address of (the original) instructions in the block
|
||||
/// is returned. Otherwise, an \e invalid address is returned.
|
||||
/// \return the starting address or an \e invalid address
|
||||
virtual Address getStop(void) const { return Address(); }
|
||||
|
||||
/// \brief Get the FlowBlock type of \b this
|
||||
///
|
||||
/// \return one of the enumerated block types
|
||||
virtual block_type getType(void) const { return t_plain; }
|
||||
|
||||
/// \brief Get the i-th component block
|
||||
///
|
||||
/// \param i is the index of the component block
|
||||
/// \return the specified component block
|
||||
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; }
|
||||
|
||||
/// \brief Mark target blocks of any unstructured edges
|
||||
virtual void markUnstructured(void) {}
|
||||
|
||||
virtual void markLabelBumpUp(bool bump); ///< Let hierarchical blocks steal labels of their (first) components
|
||||
virtual void scopeBreak(int4 curexit,int4 curloopexit) {} ///< Mark unstructured edges that should be \e breaks
|
||||
|
||||
/// \brief Mark unstructured edges that should be \e breaks
|
||||
///
|
||||
/// \param curexit is the index of the (fall-thru) exit block for \b this block, or -1 for no fall-thru
|
||||
/// \param curloopexit is the index of the exit block of the containing loop, or -1 for no containing loop
|
||||
virtual void scopeBreak(int4 curexit,int4 curloopexit) {}
|
||||
|
||||
virtual void printHeader(ostream &s) const; ///< Print a simple description of \b this to stream
|
||||
virtual void printTree(ostream &s,int4 level) const; ///< Print tree structure of any blocks owned by \b this
|
||||
virtual void printRaw(ostream &s) const {} ///< Print raw instructions contained in \b this FlowBlock
|
||||
|
||||
/// \brief Print raw instructions contained in \b this FlowBlock
|
||||
///
|
||||
/// A text representation of the control-flow and instructions contained in \b this block is
|
||||
/// emitted to the given stream.
|
||||
/// \param s is the given stream to write to
|
||||
virtual void printRaw(ostream &s) const {}
|
||||
|
||||
virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code
|
||||
virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; } ///< Get the FlowBlock to which \b this block exits
|
||||
virtual PcodeOp *firstOp(void) const { return (PcodeOp *)0; } ///< Get the first PcodeOp executed by \b this FlowBlock
|
||||
virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; } ///< Get the last PcodeOp executed by \b this FlowBlock
|
||||
|
||||
/// \brief Get the leaf block from which \b this block exits
|
||||
///
|
||||
/// This will be the only basic block with (structured) edges out of \b this block.
|
||||
/// \return the specific exiting block or null if there isn't a unique block
|
||||
virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; }
|
||||
|
||||
/// \brief Get the first PcodeOp executed by \b this FlowBlock
|
||||
///
|
||||
/// If there are no PcodeOps in the block, null is returned.
|
||||
/// \return the first PcodeOp or null
|
||||
virtual PcodeOp *firstOp(void) const { return (PcodeOp *)0; }
|
||||
|
||||
/// \brief Get the last PcodeOp executed by \b this FlowBlock
|
||||
///
|
||||
/// If \b this has a unique last PcodeOp, it is returned.
|
||||
/// \return the last PcodeOp or null
|
||||
virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; }
|
||||
|
||||
virtual bool negateCondition(bool toporbottom); ///< Flip the condition computed by \b this
|
||||
virtual bool preferComplement(Funcdata &data); ///< Rearrange \b this hierarchy to simplify boolean expressions
|
||||
virtual FlowBlock *getSplitPoint(void); ///< Get the leaf splitting block
|
||||
virtual int4 flipInPlaceTest(vector<PcodeOp *> &fliplist) const;
|
||||
virtual void flipInPlaceExecute(void);
|
||||
virtual bool isComplex(void) const { return true; } ///< Is \b this too complex to be a condition (BlockCondition)
|
||||
|
||||
/// \brief Is \b this too complex to be a condition (BlockCondition)
|
||||
///
|
||||
/// \return \b false if the whole block can be emitted as a conditional clause
|
||||
virtual bool isComplex(void) const { return true; }
|
||||
|
||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||
virtual void finalTransform(Funcdata &data) {} ///< Do any structure driven final transforms
|
||||
virtual void finalizePrinting(Funcdata &data) const {} ///< Make any final configurations necessary to print the block
|
||||
|
||||
/// \brief Do any structure driven final transforms
|
||||
///
|
||||
/// \param data is the function to transform
|
||||
virtual void finalTransform(Funcdata &data) {}
|
||||
|
||||
/// \brief Make any final configurations necessary to emit the block
|
||||
///
|
||||
/// \param data is the function to finalize
|
||||
virtual void finalizePrinting(Funcdata &data) const {}
|
||||
|
||||
virtual void encodeHeader(Encoder &encoder) const; ///< Encode basic information as attributes
|
||||
virtual void decodeHeader(Decoder &decoder); ///< Decode basic information from element attributes
|
||||
virtual void encodeBody(Encoder &encoder) const {} ///< Encode detail about components to a stream
|
||||
|
||||
/// \brief Encode detail about \b this block and its components to a stream
|
||||
///
|
||||
/// \param encoder is the stream encoder
|
||||
virtual void encodeBody(Encoder &encoder) const {}
|
||||
|
||||
/// \brief Restore details about \b this FlowBlock from an element stream
|
||||
///
|
||||
/// \param decoder is the stream decoder
|
||||
virtual void decodeBody(Decoder &decoder) {}
|
||||
|
||||
void encodeEdges(Encoder &encoder) const; ///< Encode edge information to a stream
|
||||
void decodeEdges(Decoder &decoder,BlockMap &resolver);
|
||||
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||
|
@ -2681,7 +2681,7 @@ int4 ActionSetCasts::apply(Funcdata &data)
|
||||
if (opc == CPUI_PTRADD) { // Check for PTRADD that no longer fits its pointer
|
||||
int4 sz = (int4)op->getIn(2)->getOffset();
|
||||
TypePointer *ct = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op);
|
||||
if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize())))
|
||||
if ((ct->getMetatype() != TYPE_PTR)||(ct->getPtrTo()->getAlignSize() != AddrSpace::addressToByteInt(sz, ct->getWordSize())))
|
||||
data.opUndoPtradd(op,true);
|
||||
}
|
||||
else if (opc == CPUI_PTRSUB) { // Check for PTRSUB that no longer fits pointer
|
||||
|
@ -3324,9 +3324,23 @@ int4 RuleDoubleLoad::applyOp(PcodeOp *op,Funcdata &data)
|
||||
Varnode *piece1 = op->getIn(1);
|
||||
if (!piece0->isWritten()) return 0;
|
||||
if (!piece1->isWritten()) return 0;
|
||||
if (piece0->getDef()->code() != CPUI_LOAD) return false;
|
||||
if (piece1->getDef()->code() != CPUI_LOAD) return false;
|
||||
if (!SplitVarnode::testContiguousPointers(piece0->getDef(),piece1->getDef(),loadlo,loadhi,spc))
|
||||
PcodeOp *load1 = piece1->getDef();
|
||||
if (load1->code() != CPUI_LOAD) return false;
|
||||
PcodeOp *load0 = piece0->getDef();
|
||||
OpCode opc = load0->code();
|
||||
int4 offset = 0;
|
||||
if (opc == CPUI_SUBPIECE) {
|
||||
// Check for 2 LOADs but most significant part of most significant LOAD is discarded
|
||||
if (load0->getIn(1)->getOffset() != 0) return false;
|
||||
Varnode *vn0 = load0->getIn(0);
|
||||
if (!vn0->isWritten()) return false;
|
||||
offset = vn0->getSize() - piece0->getSize();
|
||||
load0 = vn0->getDef();
|
||||
opc = load0->code();
|
||||
}
|
||||
if (opc != CPUI_LOAD)
|
||||
return false;
|
||||
if (!SplitVarnode::testContiguousPointers(load0,load1,loadlo,loadhi,spc))
|
||||
return 0;
|
||||
|
||||
size = piece0->getSize() + piece1->getSize();
|
||||
@ -3340,8 +3354,17 @@ int4 RuleDoubleLoad::applyOp(PcodeOp *op,Funcdata &data)
|
||||
data.opSetOpcode(newload,CPUI_LOAD);
|
||||
data.opSetInput(newload,spcvn,0);
|
||||
Varnode *addrvn = loadlo->getIn(1);
|
||||
if (addrvn->isConstant())
|
||||
addrvn = data.newConstant(addrvn->getSize(),addrvn->getOffset());
|
||||
if (spc->isBigEndian() && offset != 0) {
|
||||
// If the most significant part of LOAD is discarded, we need to add discard amount to pointer
|
||||
PcodeOp *newadd = data.newOp(2,latest->getAddr());
|
||||
Varnode *addout = data.newUniqueOut(addrvn->getSize(),newadd);
|
||||
data.opSetOpcode(newadd,CPUI_INT_ADD);
|
||||
data.opSetInput(newadd,addrvn,0);
|
||||
data.opSetInput(newadd,data.newConstant(addrvn->getSize(), offset),1);
|
||||
data.opInsertAfter(newadd,latest);
|
||||
addrvn = addout;
|
||||
latest = newadd;
|
||||
}
|
||||
data.opSetInput(newload,addrvn,1);
|
||||
// We need to guarantee that -newload- reads -addrvn- after
|
||||
// it has been defined. So insert it after the latest.
|
||||
|
@ -410,8 +410,9 @@ int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
|
||||
/// Return an invalid address if the size is too small or if there are not enough slots left.
|
||||
/// \param slotnum is a reference to used slots (which will be updated)
|
||||
/// \param sz is the size of the parameter to allocated
|
||||
/// \param typeAlign is the required byte alignment for the parameter
|
||||
/// \return the address of the new parameter (or an invalid address)
|
||||
Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz) const
|
||||
Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign) const
|
||||
|
||||
{
|
||||
Address res; // Start with an invalid result
|
||||
@ -429,6 +430,11 @@ Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz) const
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeAlign > alignment) {
|
||||
int4 tmp = (slotnum * alignment) % typeAlign;
|
||||
if (tmp != 0)
|
||||
slotnum += (typeAlign - tmp) / alignment; // Waste slots to achieve typeAlign
|
||||
}
|
||||
int4 slotsused = sz / alignment; // How many slots does a -sz- byte object need
|
||||
if ( (sz % alignment) != 0)
|
||||
slotsused += 1;
|
||||
@ -657,7 +663,7 @@ Address ParamListStandard::assignAddress(const Datatype *tp,vector<int4> &status
|
||||
if ((curEntry.getType() != TYPE_UNKNOWN) && tp->getMetatype() != curEntry.getType())
|
||||
continue; // Wrong type
|
||||
|
||||
Address res = curEntry.getAddrBySlot(status[grp],tp->getSize());
|
||||
Address res = curEntry.getAddrBySlot(status[grp],tp->getAlignSize(),tp->getAlignment());
|
||||
if (res.isInvalid()) continue; // If -tp- doesn't fit an invalid address is returned
|
||||
if (curEntry.isExclusion()) {
|
||||
const vector<int4> &groupSet(curEntry.getAllGroups());
|
||||
@ -782,7 +788,7 @@ void ParamListStandard::buildTrialMap(ParamActive *active) const
|
||||
continue;
|
||||
int4 sz = curentry->isExclusion() ? curentry->getSize() : curentry->getAlign();
|
||||
int4 nextslot = 0;
|
||||
Address addr = curentry->getAddrBySlot(nextslot,sz);
|
||||
Address addr = curentry->getAddrBySlot(nextslot,sz,1);
|
||||
int4 trialpos = active->getNumTrials();
|
||||
active->registerTrial(addr,sz);
|
||||
ParamTrial ¶mtrial(active->getTrial(trialpos));
|
||||
@ -813,7 +819,7 @@ void ParamListStandard::buildTrialMap(ParamActive *active) const
|
||||
for(int4 j=0;j<slotlist.size();++j) {
|
||||
if (slotlist[j] == 0) {
|
||||
int4 nextslot = j; // Make copy of j, so that getAddrBySlot can change it
|
||||
Address addr = curentry->getAddrBySlot(nextslot,curentry->getAlign());
|
||||
Address addr = curentry->getAddrBySlot(nextslot,curentry->getAlign(),1);
|
||||
int4 trialpos = active->getNumTrials();
|
||||
active->registerTrial(addr,curentry->getAlign());
|
||||
ParamTrial ¶mtrial(active->getTrial(trialpos));
|
||||
|
@ -141,7 +141,7 @@ public:
|
||||
int4 getSlot(const Address &addr,int4 skip) const;
|
||||
AddrSpace *getSpace(void) const { return spaceid; } ///< Get the address space containing \b this entry
|
||||
uintb getBase(void) const { return addressbase; } ///< Get the starting offset of \b this entry
|
||||
Address getAddrBySlot(int4 &slot,int4 sz) const;
|
||||
Address getAddrBySlot(int4 &slot,int4 sz,int4 typeAlign) const;
|
||||
void decode(Decoder &decoder,bool normalstack,bool grouped,list<ParamEntry> &curList);
|
||||
bool isParamCheckHigh(void) const { return ((flags & extracheck_high)!=0); } ///< Return \b true if there is a high overlap
|
||||
bool isParamCheckLow(void) const { return ((flags & extracheck_low)!=0); } ///< Return \b true if there is a low overlap
|
||||
|
@ -318,8 +318,13 @@ Scope *ArchitectureGhidra::buildDatabase(DocumentStorage &store)
|
||||
void ArchitectureGhidra::buildTypegrp(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
types = new TypeFactoryGhidra(this);
|
||||
}
|
||||
|
||||
void ArchitectureGhidra::buildCoreTypes(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
if (el != (const Element *)0) {
|
||||
XmlDecode decoder(this,el);
|
||||
types->decodeCoreTypes(decoder);
|
||||
@ -339,6 +344,7 @@ void ArchitectureGhidra::buildTypegrp(DocumentStorage &store)
|
||||
types->setCoreType("sqword",8,TYPE_INT,false);
|
||||
types->setCoreType("float",4,TYPE_FLOAT,false);
|
||||
types->setCoreType("float8",8,TYPE_FLOAT,false);
|
||||
types->setCoreType("float10",10,TYPE_FLOAT,false);
|
||||
types->setCoreType("float16",16,TYPE_FLOAT,false);
|
||||
types->setCoreType("undefined",1,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("undefined2",2,TYPE_UNKNOWN,false);
|
||||
|
@ -95,6 +95,7 @@ class ArchitectureGhidra : public Architecture {
|
||||
virtual void buildLoader(DocumentStorage &store);
|
||||
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void);
|
||||
virtual void buildTypegrp(DocumentStorage &store);
|
||||
virtual void buildCoreTypes(DocumentStorage &store);
|
||||
virtual void buildCommentDB(DocumentStorage &store);
|
||||
virtual void buildStringManager(DocumentStorage &store);
|
||||
virtual void buildConstantPool(DocumentStorage &store);
|
||||
|
@ -2835,7 +2835,7 @@ Datatype *CParse::newStruct(const string &ident,vector<TypeDeclarator *> *declis
|
||||
sublist.emplace_back(0,-1,decl->getIdentifier(),decl->buildType(glb));
|
||||
}
|
||||
|
||||
TypeStruct::assignFieldOffsets(sublist,glb->types->getStructAlign());
|
||||
TypeStruct::assignFieldOffsets(sublist);
|
||||
if (!glb->types->setFields(sublist,res,-1,0)) {
|
||||
setError("Bad structure definition");
|
||||
glb->types->destroyType(res);
|
||||
|
@ -1042,7 +1042,7 @@ Datatype *CParse::newStruct(const string &ident,vector<TypeDeclarator *> *declis
|
||||
sublist.emplace_back(0,-1,decl->getIdentifier(),decl->buildType(glb));
|
||||
}
|
||||
|
||||
TypeStruct::assignFieldOffsets(sublist,glb->types->getStructAlign());
|
||||
TypeStruct::assignFieldOffsets(sublist);
|
||||
if (!glb->types->setFields(sublist,res,-1,0)) {
|
||||
setError("Bad structure definition");
|
||||
glb->types->destroyType(res);
|
||||
|
@ -104,7 +104,6 @@ OptionDatabase::OptionDatabase(Architecture *g)
|
||||
registerOption(new OptionForLoops());
|
||||
registerOption(new OptionInline());
|
||||
registerOption(new OptionNoReturn());
|
||||
registerOption(new OptionStructAlign());
|
||||
registerOption(new OptionProtoEval());
|
||||
registerOption(new OptionWarning());
|
||||
registerOption(new OptionNullPrinting());
|
||||
@ -364,23 +363,6 @@ string OptionNoReturn::apply(Architecture *glb,const string &p1,const string &p2
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \class OptionStructAlign
|
||||
/// \brief Alter the "structure alignment" data organization setting
|
||||
///
|
||||
/// The first parameter must an integer value indicating the desired alignment
|
||||
string OptionStructAlign::apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const
|
||||
|
||||
{
|
||||
int4 val = -1;
|
||||
istringstream s(p1);
|
||||
s >> dec >> val;
|
||||
if (val == -1)
|
||||
throw ParseError("Missing alignment value");
|
||||
|
||||
glb->types->setStructAlign(val);
|
||||
return "Structure alignment set";
|
||||
}
|
||||
|
||||
/// \class OptionWarning
|
||||
/// \brief Toggle whether a warning should be issued if a specific action/rule is applied.
|
||||
///
|
||||
|
@ -157,12 +157,6 @@ public:
|
||||
virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const;
|
||||
};
|
||||
|
||||
class OptionStructAlign : public ArchOption {
|
||||
public:
|
||||
OptionStructAlign(void) { name = "structalign"; } ///< Constructor
|
||||
virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const;
|
||||
};
|
||||
|
||||
class OptionWarning : public ArchOption {
|
||||
public:
|
||||
OptionWarning(void) { name = "warning"; } ///< Constructor
|
||||
|
@ -5669,9 +5669,9 @@ bool AddTreeState::initAlternateForm(void)
|
||||
if (baseType->isVariableLength())
|
||||
size = 0; // Open-ended size being pointed to, there will be no "multiples" component
|
||||
else
|
||||
size = AddrSpace::byteToAddressInt(baseType->getSize(),ct->getWordSize());
|
||||
size = AddrSpace::byteToAddressInt(baseType->getAlignSize(),ct->getWordSize());
|
||||
int4 unitsize = AddrSpace::addressToByteInt(1,ct->getWordSize());
|
||||
isDegenerate = (baseType->getSize() <= unitsize && baseType->getSize() > 0);
|
||||
isDegenerate = (baseType->getAlignSize() <= unitsize && baseType->getAlignSize() > 0);
|
||||
preventDistribution = false;
|
||||
clear();
|
||||
return true;
|
||||
@ -5699,7 +5699,7 @@ AddTreeState::AddTreeState(Funcdata &d,PcodeOp *op,int4 slot)
|
||||
if (baseType->isVariableLength())
|
||||
size = 0; // Open-ended size being pointed to, there will be no "multiples" component
|
||||
else
|
||||
size = AddrSpace::byteToAddressInt(baseType->getSize(),ct->getWordSize());
|
||||
size = AddrSpace::byteToAddressInt(baseType->getAlignSize(),ct->getWordSize());
|
||||
correct = 0;
|
||||
offset = 0;
|
||||
valid = true; // Valid until proven otherwise
|
||||
@ -5708,7 +5708,7 @@ AddTreeState::AddTreeState(Funcdata &d,PcodeOp *op,int4 slot)
|
||||
isSubtype = false;
|
||||
distributeOp = (PcodeOp *)0;
|
||||
int4 unitsize = AddrSpace::addressToByteInt(1,ct->getWordSize());
|
||||
isDegenerate = (baseType->getSize() <= unitsize && baseType->getSize() > 0);
|
||||
isDegenerate = (baseType->getAlignSize() <= unitsize && baseType->getAlignSize() > 0);
|
||||
}
|
||||
|
||||
/// Even if the current base data-type is not an array, the pointer expression may incorporate
|
||||
@ -6089,7 +6089,7 @@ Varnode *AddTreeState::buildExtra(void)
|
||||
bool AddTreeState::buildDegenerate(void)
|
||||
|
||||
{
|
||||
if (baseType->getSize() < ct->getWordSize())
|
||||
if (baseType->getAlignSize() < ct->getWordSize())
|
||||
// If the size is really less than scale, there is
|
||||
// probably some sort of padding going on
|
||||
return false; // Don't transform at all
|
||||
@ -6563,7 +6563,7 @@ int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data)
|
||||
basevn = op->getIn(0);
|
||||
tp = (TypePointer *)basevn->getTypeReadFacing(op);
|
||||
if (tp->getMetatype() == TYPE_PTR) // Make sure we are still a pointer
|
||||
if (tp->getPtrTo()->getSize()==AddrSpace::addressToByteInt(size,tp->getWordSize())) { // of the correct size
|
||||
if (tp->getPtrTo()->getAlignSize()==AddrSpace::addressToByteInt(size,tp->getWordSize())) { // of the correct size
|
||||
Varnode *indVn = op->getIn(1);
|
||||
if ((!indVn->isConstant()) || (indVn->getOffset() != 0)) // and that index isn't zero
|
||||
return 0;
|
||||
|
@ -199,8 +199,14 @@ PcodeInjectLibrary *SleighArchitecture::buildPcodeInjectLibrary(void)
|
||||
void SleighArchitecture::buildTypegrp(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
types = new TypeFactory(this); // Initialize the object
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildCoreTypes(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
|
||||
if (el != (const Element *)0) {
|
||||
XmlDecode decoder(this,el);
|
||||
types->decodeCoreTypes(decoder);
|
||||
|
@ -120,6 +120,7 @@ protected:
|
||||
virtual Translate *buildTranslator(DocumentStorage &store);
|
||||
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void);
|
||||
virtual void buildTypegrp(DocumentStorage &store);
|
||||
virtual void buildCoreTypes(DocumentStorage &store);
|
||||
virtual void buildCommentDB(DocumentStorage &store);
|
||||
virtual void buildStringManager(DocumentStorage &store);
|
||||
virtual void buildConstantPool(DocumentStorage &store);
|
||||
|
@ -427,6 +427,18 @@ void Datatype::encodeTypedef(Encoder &encoder) const
|
||||
encoder.closeElement(ELEM_DEF);
|
||||
}
|
||||
|
||||
/// Calculate \b size rounded up to be a multiple of \b alignment.
|
||||
/// This value is returned by getAlignSize().
|
||||
void Datatype::calcAlignSize(void)
|
||||
|
||||
{
|
||||
int4 mod = size % alignment;
|
||||
if (mod != 0)
|
||||
alignSize = size + (alignment - mod);
|
||||
else
|
||||
alignSize = size;
|
||||
}
|
||||
|
||||
/// A CPUI_PTRSUB must act on a pointer data-type where the given offset addresses a component.
|
||||
/// Perform this check.
|
||||
/// \param off is the given offset
|
||||
@ -546,6 +558,7 @@ void Datatype::decodeBasic(Decoder &decoder)
|
||||
}
|
||||
if (size < 0)
|
||||
throw LowlevelError("Bad size for type "+name);
|
||||
alignSize = size;
|
||||
submeta = base2sub[metatype];
|
||||
if ((id==0)&&(name.size()>0)) // If there is a type name
|
||||
id = hashName(name); // There must be some kind of id
|
||||
@ -938,7 +951,7 @@ void TypePointer::calcTruncate(TypeFactory &typegrp)
|
||||
TypePointer *TypePointer::downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,TypeFactory &typegrp)
|
||||
|
||||
{
|
||||
int4 ptrtoSize = ptrto->getSize();
|
||||
int4 ptrtoSize = ptrto->getAlignSize();
|
||||
if (off < 0 || off >= ptrtoSize) { // Check if we are wrapping
|
||||
if (ptrtoSize != 0 && !ptrto->isVariableLength()) { // Check if pointed-to is wrappable
|
||||
if (!allowArrayWrap)
|
||||
@ -1052,14 +1065,14 @@ int4 TypeArray::compareDependency(const Datatype &op) const
|
||||
Datatype *TypeArray::getSubType(int8 off,int8 *newoff) const
|
||||
|
||||
{ // Go down exactly one level, to type of element
|
||||
*newoff = off % arrayof->getSize();
|
||||
*newoff = off % arrayof->getAlignSize();
|
||||
return arrayof;
|
||||
}
|
||||
|
||||
int4 TypeArray::getHoleSize(int4 off) const
|
||||
|
||||
{
|
||||
int4 newOff = off % arrayof->getSize();
|
||||
int4 newOff = off % arrayof->getAlignSize();
|
||||
return arrayof->getHoleSize(newOff);
|
||||
}
|
||||
|
||||
@ -1073,9 +1086,9 @@ int4 TypeArray::getHoleSize(int4 off) const
|
||||
Datatype *TypeArray::getSubEntry(int4 off,int4 sz,int4 *newoff,int4 *el) const
|
||||
|
||||
{
|
||||
int4 noff = off % arrayof->getSize();
|
||||
int4 nel = off / arrayof->getSize();
|
||||
if (noff+sz > arrayof->getSize()) // Requesting parts of more then one element
|
||||
int4 noff = off % arrayof->getAlignSize();
|
||||
int4 nel = off / arrayof->getAlignSize();
|
||||
if (noff+sz > arrayof->getAlignSize()) // Requesting parts of more then one element
|
||||
return (Datatype *)0;
|
||||
*newoff = noff;
|
||||
*el = nel;
|
||||
@ -1151,8 +1164,9 @@ void TypeArray::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||
}
|
||||
}
|
||||
arrayof = typegrp.decodeType(decoder);
|
||||
if ((arraysize<=0)||(arraysize*arrayof->getSize()!=size))
|
||||
if ((arraysize<=0)||(arraysize*arrayof->getAlignSize()!=size))
|
||||
throw LowlevelError("Bad size for array of type "+arrayof->getName());
|
||||
alignment = arrayof->getAlignment();
|
||||
if (arraysize == 1)
|
||||
flags |= needs_resolution; // Array of size 1 needs special treatment
|
||||
// decoder.closeElement(elemId);
|
||||
@ -1364,6 +1378,7 @@ TypeStruct::TypeStruct(const TypeStruct &op)
|
||||
{
|
||||
setFields(op.field);
|
||||
size = op.size; // setFields might have changed the size
|
||||
alignSize = op.alignSize;
|
||||
}
|
||||
|
||||
/// Copy a list of fields into this structure, establishing its size.
|
||||
@ -1374,18 +1389,24 @@ void TypeStruct::setFields(const vector<TypeField> &fd)
|
||||
{
|
||||
vector<TypeField>::const_iterator iter;
|
||||
int4 end;
|
||||
// Need to calculate size
|
||||
// Need to calculate size and alignment
|
||||
size = 0;
|
||||
alignment = 1;
|
||||
for(iter=fd.begin();iter!=fd.end();++iter) {
|
||||
field.push_back(*iter);
|
||||
end = (*iter).offset + (*iter).type->getSize();
|
||||
Datatype *fieldType = (*iter).type;
|
||||
end = (*iter).offset + fieldType->getSize();
|
||||
if (end > size)
|
||||
size = end;
|
||||
int4 curAlign = fieldType->getAlignment();
|
||||
if (curAlign > alignment)
|
||||
alignment = curAlign;
|
||||
}
|
||||
if (field.size() == 1) { // A single field
|
||||
if (field[0].type->getSize() == size) // that fills the whole structure
|
||||
flags |= needs_resolution; // needs special attention
|
||||
}
|
||||
calcAlignSize();
|
||||
}
|
||||
|
||||
/// Find the proper subfield given an offset. Return the index of that field
|
||||
@ -1492,7 +1513,7 @@ Datatype *TypeStruct::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
*newoff = diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getSize();
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getAlignSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
@ -1520,7 +1541,7 @@ Datatype *TypeStruct::nearestArrayedComponentForward(int8 off,int8 *newoff,int8
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
*newoff = -diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getSize();
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getAlignSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
@ -1625,6 +1646,7 @@ void TypeStruct::encode(Encoder &encoder) const
|
||||
void TypeStruct::decodeFields(Decoder &decoder,TypeFactory &typegrp)
|
||||
|
||||
{
|
||||
alignment = 1;
|
||||
int4 maxoffset = 0;
|
||||
while(decoder.peekElement() != 0) {
|
||||
field.emplace_back(decoder,typegrp);
|
||||
@ -1636,6 +1658,9 @@ void TypeStruct::decodeFields(Decoder &decoder,TypeFactory &typegrp)
|
||||
s << "Field " << field.back().name << " does not fit in structure " + name;
|
||||
throw LowlevelError(s.str());
|
||||
}
|
||||
int4 curAlign = field.back().type->getAlignment();
|
||||
if (curAlign > alignment)
|
||||
alignment = curAlign;
|
||||
}
|
||||
if (size == 0) // We can decode an incomplete structure, indicated by 0 size
|
||||
flags |= type_incomplete;
|
||||
@ -1645,6 +1670,7 @@ void TypeStruct::decodeFields(Decoder &decoder,TypeFactory &typegrp)
|
||||
if (field[0].type->getSize() == size) // that fills the whole structure
|
||||
flags |= needs_resolution; // needs special resolution
|
||||
}
|
||||
calcAlignSize();
|
||||
}
|
||||
|
||||
/// If this method is called, the given data-type has a single component that fills it entirely
|
||||
@ -1731,24 +1757,17 @@ int4 TypeStruct::findCompatibleResolve(Datatype *ct) const
|
||||
|
||||
/// Assign an offset to fields in order so that each field starts at an aligned offset within the structure
|
||||
/// \param list is the list of fields
|
||||
/// \param align is the given alignment
|
||||
void TypeStruct::assignFieldOffsets(vector<TypeField> &list,int4 align)
|
||||
void TypeStruct::assignFieldOffsets(vector<TypeField> &list)
|
||||
|
||||
{
|
||||
int4 offset = 0;
|
||||
vector<TypeField>::iterator iter;
|
||||
for(iter=list.begin();iter!=list.end();++iter) {
|
||||
if ((*iter).offset != -1) continue;
|
||||
int4 cursize = (*iter).type->getSize();
|
||||
int4 curalign = 0;
|
||||
if (align > 1) {
|
||||
curalign = align;
|
||||
while((curalign>>1) >= cursize)
|
||||
curalign >>= 1;
|
||||
curalign -= 1;
|
||||
}
|
||||
if ((offset & curalign)!=0)
|
||||
offset = (offset-(offset & curalign) + (curalign+1));
|
||||
int4 cursize = (*iter).type->getAlignSize();
|
||||
int4 align = (*iter).type->getAlignment() - 1;
|
||||
if (align > 0 && (offset & align)!=0)
|
||||
offset = (offset-(offset & align) + (align+1));
|
||||
(*iter).offset = offset;
|
||||
(*iter).ident = offset;
|
||||
offset += cursize;
|
||||
@ -1762,14 +1781,20 @@ void TypeUnion::setFields(const vector<TypeField> &fd)
|
||||
|
||||
{
|
||||
vector<TypeField>::const_iterator iter;
|
||||
// Need to calculate size
|
||||
// Need to calculate size and alignment
|
||||
size = 0;
|
||||
alignment = 1;
|
||||
for(iter=fd.begin();iter!=fd.end();++iter) {
|
||||
field.push_back(*iter);
|
||||
int4 end = field.back().type->getSize();
|
||||
Datatype *fieldType = field.back().type;
|
||||
int4 end = fieldType->getSize();
|
||||
if (end > size)
|
||||
size = end;
|
||||
int4 curAlign = fieldType->getAlignment();
|
||||
if (curAlign > alignment)
|
||||
alignment = curAlign;
|
||||
}
|
||||
calcAlignSize();
|
||||
}
|
||||
|
||||
/// Parse children of the \<type> element describing each field.
|
||||
@ -1778,6 +1803,7 @@ void TypeUnion::setFields(const vector<TypeField> &fd)
|
||||
void TypeUnion::decodeFields(Decoder &decoder,TypeFactory &typegrp)
|
||||
|
||||
{
|
||||
alignment = 1;
|
||||
while(decoder.peekElement() != 0) {
|
||||
field.emplace_back(decoder,typegrp);
|
||||
if (field.back().offset + field.back().type->getSize() > size) {
|
||||
@ -1785,11 +1811,15 @@ void TypeUnion::decodeFields(Decoder &decoder,TypeFactory &typegrp)
|
||||
s << "Field " << field.back().name << " does not fit in union " << name;
|
||||
throw LowlevelError(s.str());
|
||||
}
|
||||
int4 curAlign = field.back().type->getAlignment();
|
||||
if (curAlign > alignment)
|
||||
alignment = curAlign;
|
||||
}
|
||||
if (size == 0) // We can decode an incomplete structure, indicated by 0 size
|
||||
flags |= type_incomplete;
|
||||
else
|
||||
markComplete(); // Otherwise the union is complete
|
||||
calcAlignSize();
|
||||
}
|
||||
|
||||
TypeUnion::TypeUnion(const TypeUnion &op)
|
||||
@ -1797,6 +1827,7 @@ TypeUnion::TypeUnion(const TypeUnion &op)
|
||||
{
|
||||
setFields(op.field);
|
||||
size = op.size; // setFields might have changed the size
|
||||
alignSize = op.alignSize;
|
||||
}
|
||||
|
||||
int4 TypeUnion::compare(const Datatype &op,int4 level) const
|
||||
@ -1986,7 +2017,7 @@ TypePartialStruct::TypePartialStruct(const TypePartialStruct &op)
|
||||
}
|
||||
|
||||
TypePartialStruct::TypePartialStruct(Datatype *contain,int4 off,int4 sz,Datatype *strip)
|
||||
: Datatype(sz,TYPE_PARTIALSTRUCT)
|
||||
: Datatype(sz,1,TYPE_PARTIALSTRUCT)
|
||||
{
|
||||
#ifdef CPUI_DEBUG
|
||||
if (contain->getMetatype() != TYPE_STRUCT && contain->getMetatype() != TYPE_ARRAY)
|
||||
@ -2067,7 +2098,7 @@ TypePartialUnion::TypePartialUnion(const TypePartialUnion &op)
|
||||
}
|
||||
|
||||
TypePartialUnion::TypePartialUnion(TypeUnion *contain,int4 off,int4 sz,Datatype *strip)
|
||||
: Datatype(sz,TYPE_PARTIALUNION)
|
||||
: Datatype(sz,1,TYPE_PARTIALUNION)
|
||||
{
|
||||
flags |= (needs_resolution | has_stripped);
|
||||
stripped = strip;
|
||||
@ -2410,7 +2441,7 @@ TypeCode::TypeCode(const TypeCode &op) : Datatype(op)
|
||||
}
|
||||
}
|
||||
|
||||
TypeCode::TypeCode(void) : Datatype(1,TYPE_CODE)
|
||||
TypeCode::TypeCode(void) : Datatype(1,1,TYPE_CODE)
|
||||
|
||||
{
|
||||
proto = (FuncProto *)0;
|
||||
@ -2661,7 +2692,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 *newoff,in
|
||||
symbolType = smallest->getSymbol()->getType();
|
||||
*newoff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
if (symbolType->getMetatype() == TYPE_ARRAY) {
|
||||
*elSize = ((TypeArray *)symbolType)->getBase()->getSize();
|
||||
*elSize = ((TypeArray *)symbolType)->getBase()->getAlignSize();
|
||||
return symbolType;
|
||||
}
|
||||
if (symbolType->getMetatype() == TYPE_STRUCT) {
|
||||
@ -2680,7 +2711,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentBackward(int8 off,int8 *newoff,i
|
||||
if (subType == (Datatype *)0)
|
||||
return (Datatype *)0;
|
||||
if (subType->getMetatype() == TYPE_ARRAY) {
|
||||
*elSize = ((TypeArray *)subType)->getBase()->getSize();
|
||||
*elSize = ((TypeArray *)subType)->getBase()->getAlignSize();
|
||||
return subType;
|
||||
}
|
||||
if (subType->getMetatype() == TYPE_STRUCT) {
|
||||
@ -2763,7 +2794,6 @@ TypeFactory::TypeFactory(Architecture *g)
|
||||
sizeOfLong = 0;
|
||||
sizeOfPointer = 0;
|
||||
sizeOfAltPointer = 0;
|
||||
align = 0;
|
||||
enumsize = 0;
|
||||
|
||||
clearCache();
|
||||
@ -2806,10 +2836,10 @@ void TypeFactory::setupSizes(void)
|
||||
sizeOfPointer = segOp->getInnerSize();
|
||||
sizeOfAltPointer = sizeOfPointer + segOp->getBaseSize();
|
||||
}
|
||||
if (align == 0)
|
||||
align = glb->getDefaultSize();
|
||||
if (alignMap.empty())
|
||||
setDefaultAlignmentMap();
|
||||
if (enumsize == 0) {
|
||||
enumsize = align;
|
||||
enumsize = glb->getDefaultSize();
|
||||
enumtype = TYPE_UINT;
|
||||
}
|
||||
}
|
||||
@ -2927,6 +2957,35 @@ TypeFactory::~TypeFactory(void)
|
||||
clear();
|
||||
}
|
||||
|
||||
/// Return the alignment associated with a primitive data-type of the given size
|
||||
/// \param size is the aligned size in bytes of the primitive
|
||||
/// \return the expected alignment in bytes
|
||||
int4 TypeFactory::getAlignment(uint4 size) const
|
||||
|
||||
{
|
||||
if (size >= alignMap.size()) {
|
||||
if (alignMap.empty())
|
||||
throw LowlevelError("TypeFactory alignment map not initialized");
|
||||
return alignMap[alignMap.size()-1];
|
||||
}
|
||||
return alignMap[size];
|
||||
}
|
||||
|
||||
/// Return the amount of room a data-type takes up in memory, which may be larger than the
|
||||
/// raw number of bytes in the data-type. This is the size consistent with the \b sizeof operator
|
||||
/// in C.
|
||||
/// \param size is the raw number of bytes in the data-type
|
||||
/// \return the aligned size
|
||||
int4 TypeFactory::getPrimitiveAlignSize(uint4 size) const
|
||||
|
||||
{
|
||||
int4 align = getAlignment(size);
|
||||
uint4 mod = size % align;
|
||||
if (mod != 0)
|
||||
size += (align-mod);
|
||||
return size;
|
||||
}
|
||||
|
||||
/// Looking just within this container, find a Datatype by \b name and/or \b id.
|
||||
/// \param n is the name of the data-type
|
||||
/// \param id is the type id of the data-type
|
||||
@ -3038,6 +3097,10 @@ Datatype *TypeFactory::findAdd(Datatype &ct)
|
||||
}
|
||||
|
||||
newtype = ct.clone(); // Add the new type to trees
|
||||
if (newtype->alignment < 0) {
|
||||
newtype->alignSize = getPrimitiveAlignSize(newtype->size);
|
||||
newtype->alignment = getAlignment(newtype->alignSize);
|
||||
}
|
||||
insert(newtype);
|
||||
return newtype;
|
||||
}
|
||||
@ -3112,8 +3175,10 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,
|
||||
ot->flags &= ~(uint4)Datatype::type_incomplete;
|
||||
ot->flags |= (flags & (Datatype::opaque_string | Datatype::variable_length | Datatype::type_incomplete));
|
||||
if (fixedsize > 0) { // If the caller is trying to force a size
|
||||
if (fixedsize > ot->size) // If the forced size is bigger than the size required for fields
|
||||
if (fixedsize > ot->size) { // If the forced size is bigger than the size required for fields
|
||||
ot->size = fixedsize; // Force the bigger size
|
||||
ot->calcAlignSize();
|
||||
}
|
||||
else if (fixedsize < ot->size) // If the forced size is smaller, this is an error
|
||||
throw LowlevelError("Trying to force too small a size on "+ot->getName());
|
||||
}
|
||||
@ -3150,8 +3215,10 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeUnion *ot,int4 fixedsize,u
|
||||
ot->flags &= ~(uint4)Datatype::type_incomplete;
|
||||
ot->flags |= (flags & (Datatype::variable_length | Datatype::type_incomplete));
|
||||
if (fixedsize > 0) { // If the caller is trying to force a size
|
||||
if (fixedsize > ot->size) // If the forced size is bigger than the size required for fields
|
||||
if (fixedsize > ot->size) { // If the forced size is bigger than the size required for fields
|
||||
ot->size = fixedsize; // Force the bigger size
|
||||
ot->calcAlignSize();
|
||||
}
|
||||
else if (fixedsize < ot->size) // If the forced size is smaller, this is an error
|
||||
throw LowlevelError("Trying to force too small a size on "+ot->getName());
|
||||
}
|
||||
@ -3830,7 +3897,6 @@ void TypeFactory::encode(Encoder &encoder) const
|
||||
encoder.openElement(ELEM_TYPEGRP);
|
||||
encoder.writeSignedInteger(ATTRIB_INTSIZE, sizeOfInt);
|
||||
encoder.writeSignedInteger(ATTRIB_LONGSIZE, sizeOfLong);
|
||||
encoder.writeSignedInteger(ATTRIB_STRUCTALIGN, align);
|
||||
encoder.writeSignedInteger(ATTRIB_ENUMSIZE, enumsize);
|
||||
encoder.writeBool(ATTRIB_ENUMSIGNED, (enumtype==TYPE_INT));
|
||||
for(iter=deporder.begin();iter!=deporder.end();++iter) {
|
||||
@ -4157,7 +4223,6 @@ void TypeFactory::decode(Decoder &decoder)
|
||||
|
||||
sizeOfInt = decoder.readSignedInteger(ATTRIB_INTSIZE);
|
||||
sizeOfLong = decoder.readSignedInteger(ATTRIB_LONGSIZE);
|
||||
align = decoder.readSignedInteger(ATTRIB_STRUCTALIGN);
|
||||
enumsize = decoder.readSignedInteger(ATTRIB_ENUMSIZE);
|
||||
if (decoder.readBool(ATTRIB_ENUMSIGNED))
|
||||
enumtype = TYPE_INT;
|
||||
@ -4191,8 +4256,6 @@ void TypeFactory::decodeCoreTypes(Decoder &decoder)
|
||||
void TypeFactory::decodeDataOrganization(Decoder &decoder)
|
||||
|
||||
{
|
||||
uint4 defaultSize = glb->getDefaultSize();
|
||||
align = 0;
|
||||
uint4 elemId = decoder.openElement(ELEM_DATA_ORGANIZATION);
|
||||
for(;;) {
|
||||
uint4 subId = decoder.openElement();
|
||||
@ -4207,15 +4270,7 @@ void TypeFactory::decodeDataOrganization(Decoder &decoder)
|
||||
sizeOfPointer = decoder.readSignedInteger(ATTRIB_VALUE);
|
||||
}
|
||||
else if (subId == ELEM_SIZE_ALIGNMENT_MAP) {
|
||||
for(;;) {
|
||||
uint4 mapId = decoder.openElement();
|
||||
if (mapId != ELEM_ENTRY) break;
|
||||
int4 sz = decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
int4 val = decoder.readSignedInteger(ATTRIB_ALIGNMENT);
|
||||
if (sz <= defaultSize)
|
||||
align = val;
|
||||
decoder.closeElement(mapId);
|
||||
}
|
||||
decodeAlignmentMap(decoder);
|
||||
}
|
||||
else {
|
||||
decoder.closeElementSkipping(subId);
|
||||
@ -4226,6 +4281,43 @@ void TypeFactory::decodeDataOrganization(Decoder &decoder)
|
||||
decoder.closeElement(elemId);
|
||||
}
|
||||
|
||||
/// Recover the map from data-type size to preferred alignment.
|
||||
/// \param decoder is the stream decoder
|
||||
void TypeFactory::decodeAlignmentMap(Decoder &decoder)
|
||||
|
||||
{
|
||||
alignMap.clear();
|
||||
for(;;) {
|
||||
uint4 mapId = decoder.openElement();
|
||||
if (mapId != ELEM_ENTRY) break;
|
||||
int4 sz = decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
int4 val = decoder.readSignedInteger(ATTRIB_ALIGNMENT);
|
||||
while(alignMap.size() <= sz)
|
||||
alignMap.push_back(-1);
|
||||
alignMap[sz] = val;
|
||||
decoder.closeElement(mapId);
|
||||
}
|
||||
int4 curAlign = 1;
|
||||
for(int4 sz=1;sz < alignMap.size();++sz) {
|
||||
int4 tmpAlign = alignMap[sz];
|
||||
if (tmpAlign == -1)
|
||||
alignMap[sz] = curAlign; // Copy alignment from nearest explicitly set value
|
||||
else
|
||||
curAlign = tmpAlign;
|
||||
}
|
||||
}
|
||||
|
||||
/// The default is used if the compiler spec does not contain a \<size_alignment_map> element.
|
||||
void TypeFactory::setDefaultAlignmentMap(void)
|
||||
|
||||
{
|
||||
alignMap.resize(5,0);
|
||||
alignMap[1] = 1;
|
||||
alignMap[2] = 2;
|
||||
alignMap[3] = 2;
|
||||
alignMap[4] = 4;
|
||||
}
|
||||
|
||||
/// Recover default enumeration properties (size and meta-type) from
|
||||
/// an \<enum> XML tag. Should probably consider this deprecated. These
|
||||
/// values are only used by the internal C parser.
|
||||
|
@ -169,20 +169,24 @@ protected:
|
||||
type_metatype metatype; ///< Meta-type - type disregarding size
|
||||
sub_metatype submeta; ///< Sub-type of of the meta-type, for comparisons
|
||||
Datatype *typedefImm; ///< The immediate data-type being typedefed by \e this
|
||||
int4 alignment; ///< Byte alignment expected for \b this data-type in addressable memory
|
||||
int4 alignSize; ///< Size of data-type rounded up to a multiple of \b alignment
|
||||
void decodeBasic(Decoder &decoder); ///< Recover basic data-type properties
|
||||
void encodeBasic(type_metatype meta,Encoder &encoder) const; ///< Encode basic data-type properties
|
||||
void encodeTypedef(Encoder &encoder) const; ///< Encode \b this as a \e typedef element to a stream
|
||||
void markComplete(void) { flags &= ~(uint4)type_incomplete; } ///< Mark \b this data-type as completely defined
|
||||
void setDisplayFormat(uint4 format); ///< Set a specific display format
|
||||
void calcAlignSize(void); ///< Calculate aligned size, assuming alignment is known
|
||||
virtual Datatype *clone(void) const=0; ///< Clone the data-type
|
||||
static uint8 hashName(const string &nm); ///< Produce a data-type id by hashing the type name
|
||||
static uint8 hashSize(uint8 id,int4 size); ///< Reversibly hash size into id
|
||||
public:
|
||||
/// Construct the base data-type copying low-level properties of another
|
||||
Datatype(const Datatype &op) { size = op.size; name=op.name; displayName=op.displayName; metatype=op.metatype;
|
||||
submeta=op.submeta; flags=op.flags; id=op.id; typedefImm=op.typedefImm; }
|
||||
submeta=op.submeta; flags=op.flags; id=op.id; typedefImm=op.typedefImm; alignment=op.alignment; alignSize=op.alignSize; }
|
||||
/// Construct the base data-type providing size and meta-type
|
||||
Datatype(int4 s,type_metatype m) { size=s; metatype=m; submeta=base2sub[m]; flags=0; id=0; typedefImm=(Datatype *)0; }
|
||||
Datatype(int4 s,int4 align,type_metatype m) {
|
||||
size=s; metatype=m; submeta=base2sub[m]; flags=0; id=0; typedefImm=(Datatype *)0; alignment=align; alignSize=s; }
|
||||
virtual ~Datatype(void) {} ///< Destructor
|
||||
bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type
|
||||
bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32|opaque_string))!=0); } ///< Does this print as a 'char'
|
||||
@ -207,6 +211,8 @@ public:
|
||||
uint8 getId(void) const { return id; } ///< Get the type id
|
||||
uint8 getUnsizedId(void) const; ///< Get the type id, without variable length size adjustment
|
||||
int4 getSize(void) const { return size; } ///< Get the type size
|
||||
int4 getAlignSize(void) const { return alignSize; } ///< Get size rounded up to multiple of alignment
|
||||
int4 getAlignment(void) const { return alignment; } ///< Get the expected byte alignment
|
||||
const string &getName(void) const { return name; } ///< Get the type name
|
||||
const string &getDisplayName(void) const { return displayName; } ///< Get string to use in display
|
||||
Datatype *getTypedef(void) const { return typedefImm; } ///< Get the data-type immediately typedefed by \e this (or null)
|
||||
@ -303,9 +309,9 @@ public:
|
||||
/// Construct TypeBase copying properties from another data-type
|
||||
TypeBase(const TypeBase &op) : Datatype(op) {}
|
||||
/// Construct TypeBase from a size and meta-type
|
||||
TypeBase(int4 s,type_metatype m) : Datatype(s,m) {}
|
||||
TypeBase(int4 s,type_metatype m) : Datatype(s,-1,m) {}
|
||||
/// Construct TypeBase from a size, meta-type, and name
|
||||
TypeBase(int4 s,type_metatype m,const string &n) : Datatype(s,m) { name = n; displayName = n; }
|
||||
TypeBase(int4 s,type_metatype m,const string &n) : Datatype(s,-1,m) { name = n; displayName = n; }
|
||||
virtual Datatype *clone(void) const { return new TypeBase(*this); }
|
||||
};
|
||||
|
||||
@ -353,7 +359,7 @@ public:
|
||||
/// Construct from another TypeVoid
|
||||
TypeVoid(const TypeVoid &op) : Datatype(op) { flags |= Datatype::coretype; }
|
||||
/// Constructor
|
||||
TypeVoid(void) : Datatype(0,TYPE_VOID) { name = "void"; displayName = name; flags |= Datatype::coretype; }
|
||||
TypeVoid(void) : Datatype(0,1,TYPE_VOID) { name = "void"; displayName = name; flags |= Datatype::coretype; }
|
||||
virtual Datatype *clone(void) const { return new TypeVoid(*this); }
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
};
|
||||
@ -370,15 +376,15 @@ protected:
|
||||
void calcSubmeta(void); ///< Calculate specific submeta for \b this pointer
|
||||
void calcTruncate(TypeFactory &typegrp); // Assign a truncated pointer subcomponent if necessary
|
||||
/// Internal constructor for use with decode
|
||||
TypePointer(void) : Datatype(0,TYPE_PTR) { ptrto = (Datatype *)0; wordsize=1; spaceid=(AddrSpace *)0; truncate=(TypePointer *)0; }
|
||||
TypePointer(void) : Datatype(0,-1,TYPE_PTR) { ptrto = (Datatype *)0; wordsize=1; spaceid=(AddrSpace *)0; truncate=(TypePointer *)0; }
|
||||
public:
|
||||
/// Construct from another TypePointer
|
||||
TypePointer(const TypePointer &op) : Datatype(op) { ptrto = op.ptrto; wordsize=op.wordsize; spaceid=op.spaceid; truncate=op.truncate; }
|
||||
/// Construct from a size, pointed-to type, and wordsize
|
||||
TypePointer(int4 s,Datatype *pt,uint4 ws) : Datatype(s,TYPE_PTR) {
|
||||
TypePointer(int4 s,Datatype *pt,uint4 ws) : Datatype(s,-1,TYPE_PTR) {
|
||||
ptrto = pt; flags = ptrto->getInheritable(); wordsize=ws; spaceid=(AddrSpace *)0; truncate=(TypePointer *)0; calcSubmeta(); }
|
||||
/// Construct from a pointed-to type and an address space attribute
|
||||
TypePointer(Datatype *pt,AddrSpace *spc) : Datatype(spc->getAddrSize(), TYPE_PTR) {
|
||||
TypePointer(Datatype *pt,AddrSpace *spc) : Datatype(spc->getAddrSize(), -1, TYPE_PTR) {
|
||||
ptrto = pt; flags = ptrto->getInheritable(); spaceid=spc; wordsize=spc->getWordSize(); truncate=(TypePointer *)0; calcSubmeta(); }
|
||||
Datatype *getPtrTo(void) const { return ptrto; } ///< Get the pointed-to Datatype
|
||||
uint4 getWordSize(void) const { return wordsize; } ///< Get the size of the addressable unit being pointed to
|
||||
@ -406,7 +412,7 @@ protected:
|
||||
int4 arraysize; ///< Number of elements in the array
|
||||
void decode(Decoder &decoder,TypeFactory &typegrp); ///< Restore \b this array from a stream
|
||||
/// Internal constructor for decode
|
||||
TypeArray(void) : Datatype(0,TYPE_ARRAY) { arraysize = 0; arrayof = (Datatype *)0; }
|
||||
TypeArray(void) : Datatype(0,-1,TYPE_ARRAY) { arraysize = 0; arrayof = (Datatype *)0; }
|
||||
public:
|
||||
/// Construct from another TypeArray
|
||||
TypeArray(const TypeArray &op) : Datatype(op) { arrayof = op.arrayof; arraysize = op.arraysize; }
|
||||
@ -470,7 +476,7 @@ protected:
|
||||
void decodeFields(Decoder &decoder,TypeFactory &typegrp); ///< Restore fields from a stream
|
||||
public:
|
||||
TypeStruct(const TypeStruct &op); ///< Construct from another TypeStruct
|
||||
TypeStruct(void) : Datatype(0,TYPE_STRUCT) { flags |= type_incomplete; } ///< Construct incomplete/empty TypeStruct
|
||||
TypeStruct(void) : Datatype(0,-1,TYPE_STRUCT) { flags |= type_incomplete; } ///< Construct incomplete/empty TypeStruct
|
||||
vector<TypeField>::const_iterator beginField(void) const { return field.begin(); } ///< Beginning of fields
|
||||
vector<TypeField>::const_iterator endField(void) const { return field.end(); } ///< End of fields
|
||||
virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
@ -487,7 +493,7 @@ public:
|
||||
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot);
|
||||
virtual Datatype* findResolve(const PcodeOp *op,int4 slot);
|
||||
virtual int4 findCompatibleResolve(Datatype *ct) const;
|
||||
static void assignFieldOffsets(vector<TypeField> &list,int4 align); ///< Assign field offsets given a byte alignment
|
||||
static void assignFieldOffsets(vector<TypeField> &list); ///< Assign field offsets
|
||||
static int4 scoreSingleComponent(Datatype *parent,PcodeOp *op,int4 slot); ///< Determine best type fit for given PcodeOp use
|
||||
};
|
||||
|
||||
@ -503,7 +509,7 @@ protected:
|
||||
void decodeFields(Decoder &decoder,TypeFactory &typegrp); ///< Restore fields from a stream
|
||||
public:
|
||||
TypeUnion(const TypeUnion &op); ///< Construct from another TypeUnion
|
||||
TypeUnion(void) : Datatype(0,TYPE_UNION) { flags |= (type_incomplete | needs_resolution); } ///< Construct incomplete TypeUnion
|
||||
TypeUnion(void) : Datatype(0,-1,TYPE_UNION) { flags |= (type_incomplete | needs_resolution); } ///< Construct incomplete TypeUnion
|
||||
const TypeField *getField(int4 i) const { return &field[i]; } ///< Get the i-th field of the union
|
||||
virtual const TypeField *findTruncation(int8 offset,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
// virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
@ -658,7 +664,7 @@ public:
|
||||
}
|
||||
/// Construct given an address space, scope, and architecture
|
||||
TypeSpacebase(AddrSpace *id,const Address &frame,Architecture *g)
|
||||
: Datatype(0,TYPE_SPACEBASE), localframe(frame) { spaceid = id; glb = g; }
|
||||
: Datatype(0,1,TYPE_SPACEBASE), localframe(frame) { spaceid = id; glb = g; }
|
||||
Scope *getMap(void) const; ///< Get the symbol table indexed by \b this
|
||||
Address getAddress(uintb off,int4 sz,const Address &point) const; ///< Construct an Address given an offset
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
@ -676,9 +682,9 @@ class TypeFactory {
|
||||
int4 sizeOfLong; ///< Size of the core "long" datatype
|
||||
int4 sizeOfPointer; ///< Size of pointers (into default data address space)
|
||||
int4 sizeOfAltPointer; ///< Size of alternate pointers used by architecture (if not 0)
|
||||
int4 align; ///< Alignment of structures
|
||||
int4 enumsize; ///< Size of an enumerated type
|
||||
type_metatype enumtype; ///< Default enumeration meta-type (when parsing C)
|
||||
vector<int4> alignMap; ///< Alignment of primitive data-types based on their size
|
||||
DatatypeSet tree; ///< Datatypes within this factory (sorted by function)
|
||||
DatatypeNameSet nametree; ///< Cross-reference by name
|
||||
Datatype *typecache[9][8]; ///< Matrix of the most common atomic data-types
|
||||
@ -689,6 +695,8 @@ class TypeFactory {
|
||||
void insert(Datatype *newtype); ///< Insert pointer into the cross-reference sets
|
||||
Datatype *findAdd(Datatype &ct); ///< Find data-type in this container or add it
|
||||
void orderRecurse(vector<Datatype *> &deporder,DatatypeSet &mark,Datatype *ct) const; ///< Write out dependency list
|
||||
void decodeAlignmentMap(Decoder &decoder); ///< Parse a \<size_alignment_map> element
|
||||
void setDefaultAlignmentMap(void); ///< Provide default alignments for data-types
|
||||
Datatype *decodeTypedef(Decoder &decoder); ///< Restore a \<def> element describing a typedef
|
||||
Datatype *decodeStruct(Decoder &decoder,bool forcecore); ///< Restore a \<type> element describing a structure
|
||||
Datatype *decodeUnion(Decoder &decoder,bool forcecore); ///< Restore a \<type> element describing a union
|
||||
@ -709,8 +717,8 @@ public:
|
||||
void clear(void); ///< Clear out all types
|
||||
void clearNoncore(void); ///< Clear out non-core types
|
||||
virtual ~TypeFactory(void); ///< Destructor
|
||||
void setStructAlign(int4 al) { align = al; } ///< Set the default structure alignment
|
||||
int4 getStructAlign(void) const { return align; } ///< Get the default structure alignment
|
||||
int4 getAlignment(uint4 size) const; ///< Get data-type alignment based on size
|
||||
int4 getPrimitiveAlignSize(uint4 size) const; ///< Get the aligned size of a primitive data-type
|
||||
int4 getSizeOfInt(void) const { return sizeOfInt; } ///< Get the size of the default "int"
|
||||
int4 getSizeOfLong(void) const { return sizeOfLong; } ///< Get the size of the default "long"
|
||||
int4 getSizeOfPointer(void) const { return sizeOfPointer; } ///< Get the size of pointers
|
||||
@ -832,7 +840,7 @@ inline bool Datatype::isPieceStructured(void) const
|
||||
return (metatype <= TYPE_ARRAY);
|
||||
}
|
||||
|
||||
inline TypeArray::TypeArray(int4 n,Datatype *ao) : Datatype(n*ao->getSize(),TYPE_ARRAY)
|
||||
inline TypeArray::TypeArray(int4 n,Datatype *ao) : Datatype(n*ao->getAlignSize(),ao->getAlignment(),TYPE_ARRAY)
|
||||
|
||||
{
|
||||
arraysize = n;
|
||||
|
@ -1151,7 +1151,7 @@ Datatype *TypeOpIntAdd::propagateAddIn2Out(Datatype *alttype,TypeFactory *typegr
|
||||
{
|
||||
TypePointer *pointer = (TypePointer *)alttype;
|
||||
uintb offset;
|
||||
int4 command = propagateAddPointer(offset,op,inslot,pointer->getPtrTo()->getSize());
|
||||
int4 command = propagateAddPointer(offset,op,inslot,pointer->getPtrTo()->getAlignSize());
|
||||
if (command == 2) return op->getOut()->getTempType(); // Doesn't look like a good pointer add
|
||||
TypePointer *parent = (TypePointer *)0;
|
||||
int8 parentOff;
|
||||
|
@ -449,7 +449,7 @@ void ScoreUnionFields::scoreTrialDown(const Trial &trial,bool lastLevel)
|
||||
}
|
||||
}
|
||||
TypePointer *baseType = (TypePointer *)trial.fitType;
|
||||
if (baseType->getPtrTo()->getSize() == elSize) {
|
||||
if (baseType->getPtrTo()->getAlignSize() == elSize) {
|
||||
score = 5;
|
||||
resType = trial.fitType;
|
||||
}
|
||||
@ -601,7 +601,7 @@ void ScoreUnionFields::scoreTrialDown(const Trial &trial,bool lastLevel)
|
||||
if (meta == TYPE_PTR) {
|
||||
if (trial.inslot == 0) {
|
||||
Datatype *ptrto = ((TypePointer *)trial.fitType)->getPtrTo();
|
||||
if (ptrto->getSize() == trial.op->getIn(2)->getOffset()) {
|
||||
if (ptrto->getAlignSize() == trial.op->getIn(2)->getOffset()) {
|
||||
score = 10;
|
||||
resType = trial.fitType;
|
||||
}
|
||||
@ -812,7 +812,7 @@ void ScoreUnionFields::scoreTrialUp(const Trial &trial,bool lastLevel)
|
||||
case CPUI_PTRADD:
|
||||
if (meta == TYPE_PTR) {
|
||||
Datatype *ptrto = ((TypePointer *)trial.fitType)->getPtrTo();
|
||||
if (ptrto->getSize() == def->getIn(2)->getOffset())
|
||||
if (ptrto->getAlignSize() == def->getIn(2)->getOffset())
|
||||
score = 10;
|
||||
else
|
||||
score = 2;
|
||||
|
@ -34,22 +34,22 @@ bool RangeHint::reconcile(const RangeHint *b) const
|
||||
|
||||
{
|
||||
const RangeHint *a = this;
|
||||
if (a->type->getSize() < b->type->getSize()) {
|
||||
if (a->type->getAlignSize() < b->type->getAlignSize()) {
|
||||
const RangeHint *tmp = b;
|
||||
b = a; // Make sure b is smallest
|
||||
a = tmp;
|
||||
}
|
||||
int8 mod = (b->sstart - a->sstart) % a->type->getSize();
|
||||
int8 mod = (b->sstart - a->sstart) % a->type->getAlignSize();
|
||||
if (mod < 0)
|
||||
mod += a->type->getSize();
|
||||
mod += a->type->getAlignSize();
|
||||
|
||||
Datatype *sub = a->type;
|
||||
while((sub!=(Datatype *)0)&&(sub->getSize() > b->type->getSize()))
|
||||
while((sub!=(Datatype *)0)&&(sub->getAlignSize() > b->type->getAlignSize()))
|
||||
sub = sub->getSubType(mod,&mod);
|
||||
|
||||
if (sub == (Datatype *)0) return false;
|
||||
if (mod != 0) return false;
|
||||
if (sub->getSize() == b->type->getSize()) return true;
|
||||
if (sub->getAlignSize() == b->type->getAlignSize()) return true;
|
||||
if ((b->flags & Varnode::typelock)!=0) return false;
|
||||
// If we reach here, component sizes do not match
|
||||
// Check for data-types we want to protect more
|
||||
@ -130,7 +130,7 @@ bool RangeHint::attemptJoin(RangeHint *b)
|
||||
if (highind < 0) return false;
|
||||
if (b->rangeType == endpoint) return false; // Don't merge with bounding range
|
||||
Datatype *settype = type; // Assume we will keep this data-type
|
||||
if (settype->getSize() != b->type->getSize()) return false;
|
||||
if (settype->getAlignSize() != b->type->getAlignSize()) return false;
|
||||
if (settype != b->type) {
|
||||
Datatype *aTestType = type;
|
||||
Datatype *bTestType = b->type;
|
||||
@ -155,8 +155,8 @@ bool RangeHint::attemptJoin(RangeHint *b)
|
||||
if ((b->flags & Varnode::typelock)!=0) return false;
|
||||
if (flags != b->flags) return false;
|
||||
intb diffsz = b->sstart - sstart;
|
||||
if ((diffsz % settype->getSize()) != 0) return false;
|
||||
diffsz /= settype->getSize();
|
||||
if ((diffsz % settype->getAlignSize()) != 0) return false;
|
||||
diffsz /= settype->getAlignSize();
|
||||
if (diffsz > highind) return false;
|
||||
type = settype;
|
||||
absorb(b);
|
||||
@ -170,11 +170,11 @@ bool RangeHint::attemptJoin(RangeHint *b)
|
||||
void RangeHint::absorb(RangeHint *b)
|
||||
|
||||
{
|
||||
if (b->rangeType == open && type->getSize() == b->type->getSize()) {
|
||||
if (b->rangeType == open && type->getAlignSize() == b->type->getAlignSize()) {
|
||||
rangeType = open;
|
||||
if (0 <= b->highind) { // If b has array indexing
|
||||
intb diffsz = b->sstart - sstart;
|
||||
diffsz /= type->getSize();
|
||||
diffsz /= type->getAlignSize();
|
||||
int4 trialhi = b->highind + diffsz;
|
||||
if (highind < trialhi)
|
||||
highind = trialhi;
|
||||
@ -554,7 +554,7 @@ void ScopeLocal::createEntry(const RangeHint &a)
|
||||
Address addr(space,a.start);
|
||||
Address usepoint;
|
||||
Datatype *ct = glb->types->concretize(a.type);
|
||||
int4 num = a.size/ct->getSize();
|
||||
int4 num = a.size/ct->getAlignSize();
|
||||
if (num>1)
|
||||
ct = glb->types->getTypeArray(num,ct);
|
||||
|
||||
@ -919,7 +919,7 @@ void MapState::addGuard(const LoadGuard &guard,OpCode opc,TypeFactory *typeFacto
|
||||
// we pretend we have an array of LOAD's size
|
||||
step = outSize;
|
||||
}
|
||||
if (ct->getSize() != step) { // Make sure data-type matches our step size
|
||||
if (ct->getAlignSize() != step) { // Make sure data-type matches our step size
|
||||
if (step > 8)
|
||||
return; // Don't manufacture primitives bigger than 8-bytes
|
||||
ct = typeFactory->getBase(step, TYPE_UNKNOWN);
|
||||
|
@ -19,7 +19,6 @@ f8c30fafc7c3
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option readonly on</com>
|
||||
<com>option structalign 1</com>
|
||||
<com>parse line union myalt { int4 myint; float4 myfloat; };</com>
|
||||
<com>parse line struct packstruct { int4 a; myalt u; };</com>
|
||||
<com>parse line extern int4 getvalue(packstruct val,int4 sel);</com>
|
||||
|
@ -0,0 +1,103 @@
|
||||
<decompilertest>
|
||||
<!--
|
||||
Functions manipulating longdouble data-types.
|
||||
-->
|
||||
<binaryimage arch="x86:LE:64:default:gcc">
|
||||
<bytechunk space="ram" offset="0x100000" readonly="true">
|
||||
f30f1efadb6c2408dc05aa010000488d
|
||||
3deb0f0000db7c2408e9e2100000f30f
|
||||
1efa4154488d3dd50f000055538b5c24
|
||||
20448b6424408b6c2448ff742438ff74
|
||||
2438450fbfe40fbfede8b21000000fbf
|
||||
c35a594401e05b01e85d415cc3f30f1e
|
||||
fa534889fbff7718ff7710488d3d8e0f
|
||||
0000e889100000ff7328488d3d7f0f00
|
||||
00ff7320e8771000000fbf53020fbf03
|
||||
4883c42001d00fbf533001d00fbf5332
|
||||
5b01d0c3
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x10014b" readonly="true">
|
||||
f30f1efa41
|
||||
548b542410488d355600000031c0bf01
|
||||
000000448b642440e89b0f0000ff7424
|
||||
28488d3d880e0000ff742428e87f0f00
|
||||
008b542440bf0100000031c0488d351f
|
||||
000000e8700f000058bf010000005a48
|
||||
8d350c0000004489e231c0415ce9560f
|
||||
000025640a00
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x1001b8" readonly="true">
|
||||
6f1283c0caa13b40
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x1001d2" readonly="true">
|
||||
f30f1efab8070000008d57074c8d
|
||||
051b0e00004863cf29f84863d248c1e1
|
||||
04489848c1e20441db2c1048c1e00441
|
||||
db2c008d047f81e7feff0000489848c1
|
||||
e70448c1e004dec141db3c08db6c3010
|
||||
db3c3ec3
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x101100" readonly="true">
|
||||
f30f1efadb6c2408d9c0db3fdc059e01
|
||||
0000db7f10c3
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x1012b0" readonly="true">
|
||||
666666666666e63f
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x100000" name="pass"/>
|
||||
<symbol space="ram" offset="0x10001e" name="passmany"/>
|
||||
<symbol space="ram" offset="0x10005d" name="printstruct"/>
|
||||
<symbol space="ram" offset="0x1001d2" name="arrayindex"/>
|
||||
<symbol space="ram" offset="0x101100" name="writeLongDouble"/>
|
||||
<symbol space="ram" offset="0x101108" name="printf_chk"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option readonly on</com>
|
||||
<com>map addr r0x101000 float10 ldarr[16]</com>
|
||||
<com>map fun r0x10014b printldfirst</com>
|
||||
<com>override flow r0x1001ad callreturn</com>
|
||||
<com>parse line struct ldstruct { int2 c; int2 d; float10 a; float10 b; int2 e; int2 f; };</com>
|
||||
<com>parse line struct ldfirst { float10 a; int4 b; };</com>
|
||||
<com>parse line extern void writeLongDouble(float10 *ptrwrite,float10 valwrite);</com>
|
||||
<com>parse line extern void printf_chk(int4 pipe,char *str,int4 val);</com>
|
||||
<com>parse line extern void pass(float10 valpass);</com>
|
||||
<com>parse line extern int4 passmany(int8 a,int8 b,int8 c,int8 d,int8 e,int8 f,int2 y,float10 x,int2 z,int2 w);</com>
|
||||
<com>parse line extern int4 printstruct(ldstruct *ptrldstr);</com>
|
||||
<com>parse line extern void printldfirst(int8 a,int8 b,int8 c,int8 d,int8 e,int8 f,int4 v1,ldfirst firstval,int4 v2);</com>
|
||||
<com>parse line extern void arrayindex(int4 val,float10 *ptr);</com>
|
||||
<com>lo fu pass</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu passmany</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu printstruct</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu printldfirst</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu arrayindex</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu writeLongDouble</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Long double #1" min="1" max="1">ldarr\[0\] = valpass \+ \(float10\)27\.632</stringmatch>
|
||||
<stringmatch name="Long double #2" min="1" max="1">ldarr\[1\] = valpass \+ \(float10\)27\.632</stringmatch>
|
||||
<stringmatch name="Long double #3" min="1" max="1">writeLongDouble\(ldarr,x\);</stringmatch>
|
||||
<stringmatch name="Long double #4" min="1" max="1">return \(int4\)y \+ \(int4\)z \+ \(int4\)w;</stringmatch>
|
||||
<stringmatch name="Long double #5" min="1" max="1">writeLongDouble\(ldarr,ptrldstr->a\);</stringmatch>
|
||||
<stringmatch name="Long double #6" min="1" max="1">writeLongDouble\(ldarr,ptrldstr->b\);</stringmatch>
|
||||
<stringmatch name="Long double #7" min="1" max="1">return \(int4\)ptrldstr->c \+ \(int4\)ptrldstr->d \+ \(int4\)ptrldstr->e \+ \(int4\)ptrldstr->f;</stringmatch>
|
||||
<stringmatch name="Long double #8" min="1" max="1">printf_chk\(1,\"%d\\n\",v1\);</stringmatch>
|
||||
<stringmatch name="Long double #9" min="1" max="1">printf_chk\(1,\"%d\\n\",firstval\.b\);</stringmatch>
|
||||
<stringmatch name="Long double #10" min="1" max="1">printf_chk\(1,\"%d\\n\",v2\);</stringmatch>
|
||||
<stringmatch name="Long double #11" min="1" max="1">writeLongDouble\(ldarr,firstval\.a\);</stringmatch>
|
||||
<stringmatch name="Long double #12" min="1" max="1">\*ptrwrite = valwrite;</stringmatch>
|
||||
<stringmatch name="Long double #13" min="1" max="1">ptrwrite\[1\] = valwrite \+ \(float10\)0.7;</stringmatch>
|
||||
<stringmatch name="Long double #14" min="1" max="1">ldarr\[val\] = ldarr\[7 \- val\] \+ ldarr\[val \+ 7\];</stringmatch>
|
||||
<stringmatch name="Long double #15" min="1" max="1">ptr\[val & 0xfffe\] = ptr\[.*\(val \* 3\) \+ 1\];</stringmatch>
|
||||
</decompilertest>
|
@ -12,7 +12,7 @@
|
||||
<symbol space="ram" offset="0x400517" name="readstruct"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>parse line struct twostruct { int4 field1; int4 array[5]; };</com>
|
||||
<com>parse line struct twostruct { int4 field1; int4 field2; int4 array[5]; };</com>
|
||||
<com>parse line extern int4 readstruct(twostruct *ptr,int8 a,int8 b);</com>
|
||||
<com>lo fu readstruct</com>
|
||||
<com>decompile</com>
|
||||
|
@ -22,6 +22,6 @@
|
||||
<com>print C</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Offset array #1" min="1" max="1">return mStack.*array\[param_1 \+ -2\]</stringmatch>
|
||||
<stringmatch name="Offset array #1" min="1" max="1">return mStack.*array\[param_1 \+ -1\]</stringmatch>
|
||||
<stringmatch name="Offset array #2" min="0" max="0">firstfield</stringmatch>
|
||||
</decompilertest>
|
||||
|
@ -12,7 +12,6 @@
|
||||
<symbol space="ram" offset="0x1006da" name="getstruct"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option structalign 1</com>
|
||||
<com>parse line struct tinystruct { int4 a; int2 b; int2 c; };</com>
|
||||
<com>parse line extern tinystruct getstruct(int4 i);</com>
|
||||
<com>parse line extern int4 access(int4 i);</com>
|
||||
|
@ -342,10 +342,11 @@ public class ParamEntry {
|
||||
* there are not enough slots left
|
||||
* @param slotnum number of slots already assigned
|
||||
* @param sz number of bytes to being assigned
|
||||
* @param typeAlign required byte alignment for the parameter
|
||||
* @param res the final storage address
|
||||
* @return slotnum plus the number of slots used
|
||||
*/
|
||||
public int getAddrBySlot(int slotnum, int sz, VarnodeData res) {
|
||||
public int getAddrBySlot(int slotnum, int sz, int typeAlign, VarnodeData res) {
|
||||
res.space = null; // Start with an invalid result
|
||||
int spaceused;
|
||||
if (sz < minsize) {
|
||||
@ -366,6 +367,12 @@ public class ParamEntry {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeAlign > alignment) {
|
||||
int tmp = (slotnum * alignment) % typeAlign;
|
||||
if (tmp != 0) {
|
||||
slotnum += (typeAlign - tmp) / alignment; // Waste slots to achieve typeAlign
|
||||
}
|
||||
}
|
||||
int slotsused = sz / alignment; // How many slots does a -sz- byte object need
|
||||
if ((sz % alignment) != 0) {
|
||||
slotsused += 1;
|
||||
|
@ -98,7 +98,8 @@ public class ParamListStandard implements ParamList {
|
||||
}
|
||||
|
||||
VarnodeData res = new VarnodeData();
|
||||
status[grp] = element.getAddrBySlot(status[grp], tp.getLength(), res);
|
||||
status[grp] =
|
||||
element.getAddrBySlot(status[grp], tp.getAlignedLength(), tp.getAlignment(), res);
|
||||
if (res.space == null) {
|
||||
continue; // -tp- does not fit in this entry
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user