GP-2237 AddrSpace as marshaling primitive and prettyprint update

This commit is contained in:
caheckman 2022-06-23 20:16:51 -04:00
parent 4807ec354a
commit 6be9943b8a
58 changed files with 1333 additions and 1098 deletions

View file

@ -64,12 +64,12 @@ void SeqNum::encode(Encoder &encoder) const
encoder.closeElement(ELEM_SEQNUM);
}
SeqNum SeqNum::decode(Decoder &decoder,const AddrSpaceManager *manage)
SeqNum SeqNum::decode(Decoder &decoder)
{
uintm uniq = ~((uintm)0);
uint4 elemId = decoder.openElement(ELEM_SEQNUM);
Address pc = Address::decode(decoder,manage); // Recover address
Address pc = Address::decode(decoder); // Recover address
for(;;) {
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
@ -199,14 +199,13 @@ void Address::renormalize(int4 size) {
/// or a \e name attribute can be used to recover an address
/// based on a register name.
/// \param decoder is the stream decoder
/// \param manage is the address space manager for the program
/// \return the resulting Address
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage)
Address Address::decode(Decoder &decoder)
{
VarnodeData var;
var.decode(decoder,manage);
var.decode(decoder);
return Address(var.space,var.offset);
}
@ -220,15 +219,14 @@ Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage)
/// and size based on a register name. If a size is recovered
/// it is stored in \e size reference.
/// \param decoder is the stream decoder
/// \param manage is the address space manager for the program
/// \param size is the reference to any recovered size
/// \return the resulting Address
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage,int4 &size)
Address Address::decode(Decoder &decoder,int4 &size)
{
VarnodeData var;
var.decode(decoder,manage);
var.decode(decoder);
size = var.size;
return Address(var.space,var.offset);
}
@ -293,7 +291,7 @@ void Range::encode(Encoder &encoder) const
{
encoder.openElement(ELEM_RANGE);
encoder.writeString(ATTRIB_SPACE, spc->getName());
encoder.writeSpace(ATTRIB_SPACE, spc);
encoder.writeUnsignedInteger(ATTRIB_FIRST, first);
encoder.writeUnsignedInteger(ATTRIB_LAST, last);
encoder.closeElement(ELEM_RANGE);
@ -301,21 +299,19 @@ void Range::encode(Encoder &encoder) const
/// Reconstruct this object from a \<range> or \<register> element
/// \param decoder is the stream decoder
/// \param manage is the space manager for recovering AddrSpace objects
void Range::decode(Decoder &decoder,const AddrSpaceManager *manage)
void Range::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement();
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
throw XmlError("Expecting <range> or <register> element");
decodeFromAttributes(decoder,manage);
decodeFromAttributes(decoder);
decoder.closeElement(elemId);
}
/// Reconstruct from attributes that may not be part of a \<range> element.
/// \param decoder is the stream decoder
/// \param manage is the space manager for recovering AddrSpace objects
void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage)
void Range::decodeFromAttributes(Decoder &decoder)
{
spc = (AddrSpace *)0;
@ -326,10 +322,7 @@ void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
if (attribId == ATTRIB_SPACE) {
string spcname = decoder.readString();
spc = manage->getSpaceByName(spcname);
if (spc == (AddrSpace *)0)
throw LowlevelError("Undefined space: "+spcname);
spc = decoder.readSpace();
}
else if (attribId == ATTRIB_FIRST) {
first = decoder.readUnsignedInteger();
@ -339,7 +332,7 @@ void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage
seenLast = true;
}
else if (attribId == ATTRIB_NAME) {
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
const Translate *trans = decoder.getAddrSpaceManager()->getDefaultCodeSpace()->getTrans();
const VarnodeData &point(trans->getRegister(decoder.readString()));
spc = point.space;
first = point.offset;
@ -620,14 +613,13 @@ void RangeList::encode(Encoder &encoder) const
/// Recover each individual disjoint Range for \b this RangeList.
/// \param decoder is the stream decoder
/// \param manage is manager for retrieving address spaces
void RangeList::decode(Decoder &decoder,const AddrSpaceManager *manage)
void RangeList::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_RANGELIST);
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,manage);
range.decode(decoder);
tree.insert(range);
}
decoder.closeElement(elemId);

View file

@ -96,10 +96,10 @@ public:
void encode(Encoder &encoder,int4 size) const; ///< Encode \b this and a size to a stream
/// Restore an address from parsed XML
static Address decode(Decoder &decoder,const AddrSpaceManager *manage);
static Address decode(Decoder &decoder);
/// Restore an address and size from parsed XML
static Address decode(Decoder &decoder,const AddrSpaceManager *manage,int4 &size);
static Address decode(Decoder &decoder,int4 &size);
};
/// \brief A class for uniquely labelling and comparing PcodeOps
@ -158,7 +158,7 @@ public:
void encode(Encoder &encoder) const;
/// Decode a SeqNum from a stream
static SeqNum decode(Decoder &decoder,const AddrSpaceManager *manage);
static SeqNum decode(Decoder &decoder);
/// Write out a SeqNum in human readable form to a stream
friend ostream &operator<<(ostream &s,const SeqNum &sq);
@ -202,8 +202,8 @@ public:
return (first < op2.first); }
void printBounds(ostream &s) const; ///< Print \b this Range to a stream
void encode(Encoder &encoder) const; ///< Encode \b this Range to a stream
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Restore \b this from a stream
void decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage); ///< Read \b from attributes on another tag
void decode(Decoder &decoder); ///< Restore \b this from a stream
void decodeFromAttributes(Decoder &decoder); ///< Read \b from attributes on another tag
};
/// \brief A partially parsed description of a Range
@ -247,7 +247,7 @@ public:
uintb longestFit(const Address &addr,uintb maxsize) const; ///< Find size of biggest Range containing given address
void printBounds(ostream &s) const; ///< Print a description of \b this RangeList to stream
void encode(Encoder &encoder) const; ///< Encode \b this RangeList to a stream
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this RangeList from a \<rangelist> element
void decode(Decoder &decoder); ///< Decode \b this RangeList from a \<rangelist> element
};
/// Precalculated masks indexed by size

View file

@ -409,13 +409,13 @@ void Architecture::setPrintLanguage(const string &nm)
PrintLanguageCapability *capa = PrintLanguageCapability::findCapability(nm);
if (capa == (PrintLanguageCapability *)0)
throw LowlevelError("Unknown print language: "+nm);
bool printxml = print->emitsXml(); // Copy settings for current print language
bool printMarkup = print->emitsMarkup(); // Copy settings for current print language
ostream *t = print->getOutputStream();
print = capa->buildLanguage(this);
print->setOutputStream(t); // Restore settings from previous language
print->initializeFromArchitecture();
if (printxml)
print->setXML(true);
if (printMarkup)
print->setMarkup(true);
printlist.push_back(print);
print->adjustTypeOperators();
return;
@ -446,8 +446,8 @@ void Architecture::decodeFlowOverride(Decoder &decoder)
uint4 subId = decoder.openElement();
if (subId != ELEM_FLOW) break;
string flowType = decoder.readString(ATTRIB_TYPE);
Address funcaddr = Address::decode(decoder,this);
Address overaddr = Address::decode(decoder,this);
Address funcaddr = Address::decode(decoder);
Address overaddr = Address::decode(decoder);
Funcdata *fd = symboltab->getGlobalScope()->queryFunction(funcaddr);
if (fd != (Funcdata *)0)
fd->getOverride().insertFlowOverride(overaddr,Override::stringToType(flowType));
@ -482,7 +482,7 @@ void Architecture::restoreXml(DocumentStorage &store)
const Element *el = store.getTag(ELEM_SAVE_STATE.getName());
if (el == (const Element *)0)
throw LowlevelError("Could not find save_state tag");
XmlDecode decoder(el);
XmlDecode decoder(this,el);
uint4 elemId = decoder.openElement(ELEM_SAVE_STATE);
loadersymbols_parsed = false;
for(;;) {
@ -500,11 +500,11 @@ void Architecture::restoreXml(DocumentStorage &store)
else if (subId == ELEM_DB)
symboltab->decode(decoder);
else if (subId == ELEM_CONTEXT_POINTS)
context->decode(decoder,this);
context->decode(decoder);
else if (subId == ELEM_COMMENTDB)
commentdb->decode(decoder,this);
commentdb->decode(decoder);
else if (subId == ELEM_STRINGMANAGE)
stringManager->decode(decoder,this);
stringManager->decode(decoder);
else if (subId == ELEM_CONSTANTPOOL)
cpool->decode(decoder,*types);
else if (subId == ELEM_OPTIONSLIST)
@ -607,7 +607,7 @@ void Architecture::buildTypegrp(DocumentStorage &store)
const Element *el = store.getTag("coretypes");
types = new TypeFactory(this); // Initialize the object
if (el != (const Element *)0) {
XmlDecode decoder(el);
XmlDecode decoder(this,el);
types->decodeCoreTypes(decoder);
}
else {
@ -929,7 +929,7 @@ void Architecture::decodeReadOnly(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_READONLY);
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,this);
range.decode(decoder);
symboltab->setPropertyRange(Varnode::readonly,range);
}
decoder.closeElement(elemId);
@ -945,7 +945,7 @@ void Architecture::decodeVolatile(Decoder &decoder)
userops.decodeVolatile(decoder,this);
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,this); // Tag itself is range
range.decode(decoder); // Tag itself is range
symboltab->setPropertyRange(Varnode::volatil,range);
}
decoder.closeElement(elemId);
@ -962,7 +962,7 @@ void Architecture::decodeReturnAddress(Decoder &decoder)
if (subId != 0) {
if (defaultReturnAddr.space != (AddrSpace *)0)
throw LowlevelError("Multiple <returnaddress> tags in .cspec");
defaultReturnAddr.decode(decoder,this);
defaultReturnAddr.decode(decoder);
}
decoder.closeElement(elemId);
}
@ -976,7 +976,7 @@ void Architecture::decodeIncidentalCopy(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_INCIDENTALCOPY);
while(decoder.peekElement() != 0) {
VarnodeData vdata;
vdata.decode(decoder,this);
vdata.decode(decoder);
Range range( vdata.space, vdata.offset, vdata.offset+vdata.size-1);
symboltab->setPropertyRange(Varnode::incidental_copy,range);
}
@ -994,7 +994,7 @@ void Architecture::decodeLaneSizes(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_REGISTER_DATA);
while(decoder.peekElement() != 0) {
if (lanedRegister.decode(decoder, this)) {
if (lanedRegister.decode(decoder)) {
int4 sizeIndex = lanedRegister.getWholeSize();
while (maskList.size() <= sizeIndex)
maskList.push_back(0);
@ -1016,10 +1016,10 @@ void Architecture::decodeStackPointer(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_STACKPOINTER);
string spaceName;
string registerName;
bool stackGrowth = true; // Default stack growth is in negative direction
bool isreversejustify = false;
AddrSpace *basespace = (AddrSpace *)0;
for(;;) {
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
@ -1028,14 +1028,13 @@ void Architecture::decodeStackPointer(Decoder &decoder)
else if (attribId == ATTRIB_GROWTH)
stackGrowth = decoder.readString() == "negative";
else if (attribId == ATTRIB_SPACE)
spaceName = decoder.readString();
basespace = decoder.readSpace();
else if (attribId == ATTRIB_REGISTER)
registerName = decoder.readString();
}
AddrSpace *basespace = getSpaceByName(spaceName);
if (basespace == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+spaceName);
throw LowlevelError(ELEM_STACKPOINTER.getName() + " element missing \"space\" attribute");
VarnodeData point = translate->getRegister(registerName);
decoder.closeElement(elemId);
@ -1056,10 +1055,7 @@ void Architecture::decodeDeadcodeDelay(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_DEADCODEDELAY);
string spaceName = decoder.readString(ATTRIB_SPACE);
AddrSpace *spc = getSpaceByName(spaceName);
if (spc == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+spaceName);
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
if (delay >= 0)
setDeadcodeDelay(spc,delay);
@ -1075,7 +1071,7 @@ void Architecture::decodeInferPtrBounds(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_INFERPTRBOUNDS);
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,this);
range.decode(decoder);
setInferPtrBounds(range);
}
decoder.closeElement(elemId);
@ -1113,12 +1109,9 @@ void Architecture::decodeSpacebase(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_SPACEBASE);
string nameString = decoder.readString(ATTRIB_NAME);
string registerName = decoder.readString(ATTRIB_REGISTER);
string spaceName = decoder.readString(ATTRIB_SPACE);
AddrSpace *basespace = decoder.readSpace(ATTRIB_SPACE);
decoder.closeElement(elemId);
const VarnodeData &point(translate->getRegister(registerName));
AddrSpace *basespace = getSpaceByName(spaceName);
if (basespace == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+spaceName);
addSpacebase(basespace,nameString,point,point.size,false,false);
}
@ -1131,7 +1124,7 @@ void Architecture::decodeNoHighPtr(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_NOHIGHPTR);
while(decoder.peekElement() != 0) { // Iterate over every range tag in the list
Range range;
range.decode(decoder,this);
range.decode(decoder);
addNoHighPtr(range);
}
decoder.closeElement(elemId);
@ -1151,7 +1144,7 @@ void Architecture::decodePreferSplit(Decoder &decoder)
while(decoder.peekElement() != 0) {
splitrecords.emplace_back();
PreferSplitRecord &record( splitrecords.back() );
record.storage.decode( decoder, this );
record.storage.decode( decoder );
record.splitoffset = record.storage.size/2;
}
decoder.closeElement(elemId);
@ -1203,7 +1196,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
const Element *el = store.getTag("processor_spec");
if (el == (const Element *)0)
throw LowlevelError("No processor configuration tag found");
XmlDecode decoder(el);
XmlDecode decoder(this,el);
uint4 elemId = decoder.openElement(ELEM_PROCESSOR_SPEC);
for(;;) {
@ -1218,7 +1211,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
else if (subId == ELEM_INCIDENTALCOPY)
decodeIncidentalCopy(decoder);
else if (subId == ELEM_CONTEXT_DATA)
context->decodeFromSpec(decoder,this);
context->decodeFromSpec(decoder);
else if (subId == ELEM_JUMPASSIST)
userops.decodeJumpAssist(decoder, this);
else if (subId == ELEM_SEGMENTOP)
@ -1228,11 +1221,8 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
}
else if (subId == ELEM_DATA_SPACE) {
uint4 elemId = decoder.openElement();
string spaceName = decoder.readString(ATTRIB_SPACE);
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
decoder.closeElement(elemId);
AddrSpace *spc = getSpaceByName(spaceName);
if (spc == (AddrSpace *)0)
throw LowlevelError("Undefined space: "+spaceName);
setDefaultDataSpace(spc->getIndex());
}
else if (subId == ELEM_INFERPTRBOUNDS) {
@ -1273,7 +1263,7 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
const Element *el = store.getTag("compiler_spec");
if (el == (const Element *)0)
throw LowlevelError("No compiler configuration tag found");
XmlDecode decoder(el);
XmlDecode decoder(this,el);
uint4 elemId = decoder.openElement(ELEM_COMPILER_SPEC);
for(;;) {
@ -1306,7 +1296,7 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
else if (subId == ELEM_READONLY)
decodeReadOnly(decoder);
else if (subId == ELEM_CONTEXT_DATA)
context->decodeFromSpec(decoder,this);
context->decodeFromSpec(decoder);
else if (subId == ELEM_RESOLVEPROTOTYPE)
decodeProto(decoder);
else if (subId == ELEM_EVAL_CALLED_PROTOTYPE)
@ -1337,7 +1327,7 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
el = store.getTag("specextensions"); // Look for any user-defined configuration document
if (el != (const Element *)0) {
XmlDecode decoderExt(el);
XmlDecode decoderExt(this,el);
elemId = decoderExt.openElement(ELEM_SPECEXTENSIONS);
for(;;) {
uint4 subId = decoderExt.peekElement();
@ -1388,7 +1378,7 @@ void Architecture::parseExtraRules(DocumentStorage &store)
{
const Element *expertag = store.getTag("experimental_rules");
if (expertag != (const Element *)0) {
XmlDecode decoder(expertag);
XmlDecode decoder(this,expertag);
uint4 elemId = decoder.openElement(ELEM_EXPERIMENTAL_RULES);
while(decoder.peekElement() != 0)
decodeDynamicRule( decoder );

View file

@ -1324,10 +1324,10 @@ void BlockGraph::encodeBody(Encoder &encoder) const
list[i]->encode(encoder);
}
void BlockGraph::decodeBody(Decoder &decoder,BlockMap &resolver)
void BlockGraph::decodeBody(Decoder &decoder)
{
BlockMap newresolver(resolver);
BlockMap newresolver;
vector<FlowBlock *> tmplist;
for(;;) {
@ -1352,11 +1352,10 @@ void BlockGraph::decodeBody(Decoder &decoder,BlockMap &resolver)
/// Parse a \<block> element. This is currently just a wrapper around the
/// FlowBlock::decode() that sets of the BlockMap resolver
/// \param decoder is the stream decoder
/// \param m is the address space manager
void BlockGraph::decode(Decoder &decoder,const AddrSpaceManager *m)
void BlockGraph::decode(Decoder &decoder)
{
BlockMap resolver(m);
BlockMap resolver;
FlowBlock::decode(decoder,resolver);
// Restore goto references here
}
@ -2417,7 +2416,7 @@ void FlowBlock::decode(Decoder &decoder,BlockMap &resolver)
{
uint4 elemId = decoder.openElement(ELEM_BLOCK);
decodeHeader(decoder);
decodeBody(decoder,resolver);
decodeBody(decoder);
decodeEdges(decoder,resolver);
decoder.closeElement(elemId);
}
@ -2562,10 +2561,10 @@ void BlockBasic::encodeBody(Encoder &encoder) const
cover.encode(encoder);
}
void BlockBasic::decodeBody(Decoder &decoder,BlockMap &resolver)
void BlockBasic::decodeBody(Decoder &decoder)
{
cover.decode(decoder, resolver.getAddressManager());
cover.decode(decoder);
}
void BlockBasic::printHeader(ostream &s) const
@ -3440,12 +3439,6 @@ FlowBlock *BlockSwitch::nextFlowAfter(const FlowBlock *bl) const
return getParent()->nextFlowAfter(this);
}
BlockMap::BlockMap(const BlockMap &op2)
{
manage = op2.manage;
}
/// \param bt is the block_type
/// \return a new instance of the specialized FlowBlock
FlowBlock *BlockMap::resolveBlock(FlowBlock::block_type bt)

View file

@ -190,8 +190,7 @@ public:
/// \brief Restore details about \b this FlowBlock from an element stream
///
/// \param decoder is the stream decoder
/// \param resolver is used to recover FlowBlock objects based on elment references
virtual void decodeBody(Decoder &decoder,BlockMap &resolver) {}
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
@ -310,8 +309,8 @@ public:
virtual void finalTransform(Funcdata &data);
virtual void finalizePrinting(Funcdata &data) const;
virtual void encodeBody(Encoder &encoder) const;
virtual void decodeBody(Decoder &decoder,BlockMap &resolver);
void decode(Decoder &decoder,const AddrSpaceManager *m); ///< Restore \b this BlockGraph from an XML stream
virtual void decodeBody(Decoder &decoder);
void decode(Decoder &decoder); ///< Decode \b this BlockGraph from a stream
void addEdge(FlowBlock *begin,FlowBlock *end); ///< Add a directed edge between component FlowBlocks
void addLoopEdge(FlowBlock *begin,int4 outindex); ///< Mark a given edge as a \e loop edge
void removeEdge(FlowBlock *begin,FlowBlock *end); ///< Remove an edge between component FlowBlocks
@ -394,7 +393,7 @@ public:
virtual block_type getType(void) const { return t_basic; }
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; }
virtual void encodeBody(Encoder &encoder) const;
virtual void decodeBody(Decoder &decoder,BlockMap &resolver);
virtual void decodeBody(Decoder &decoder);
virtual void printHeader(ostream &s) const;
virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
@ -713,14 +712,10 @@ public:
/// list of FlowBlock objects sorted by index and then looks up the FlowBlock matching a given
/// index as edges specify them.
class BlockMap {
const AddrSpaceManager *manage; ///< Address space manager used to decode FlowBlock address ranges
vector<FlowBlock *> sortlist; ///< The list of deserialized FlowBlock objects
FlowBlock *resolveBlock(FlowBlock::block_type bt); ///< Construct a FlowBlock of the given type
static FlowBlock *findBlock(const vector<FlowBlock *> &list,int4 ind); ///< Locate a FlowBlock with a given index
public:
BlockMap(const AddrSpaceManager *m) { manage = m; } ///< Construct given an address space manager
BlockMap(const BlockMap &op2); ///< Copy constructor
const AddrSpaceManager *getAddressManager(void) const { return manage; } ///< Get the address space manager
void sortList(void); ///< Sort the list of FlowBlock objects
/// \brief Find the FlowBlock matching the given index

View file

@ -33,12 +33,11 @@ void CallGraphEdge::decode(Decoder &decoder,CallGraph *graph)
{
uint4 elemId = decoder.openElement(ELEM_EDGE);
const AddrSpaceManager *manage = graph->getArch();
Address fromaddr,toaddr,siteaddr;
fromaddr = Address::decode(decoder,manage);
toaddr = Address::decode(decoder,manage);
siteaddr = Address::decode(decoder,manage);
fromaddr = Address::decode(decoder);
toaddr = Address::decode(decoder);
siteaddr = Address::decode(decoder);
decoder.closeElement(elemId);
CallGraphNode *fromnode = graph->findNode(fromaddr);
@ -83,7 +82,7 @@ void CallGraphNode::decode(Decoder &decoder,CallGraph *graph)
if (attribId == ATTRIB_NAME)
name = decoder.readString();
}
Address addr = Address::decode(decoder,graph->getArch());
Address addr = Address::decode(decoder);
decoder.closeElement(elemId);
graph->addNode(addr,name);
}

View file

@ -107,7 +107,6 @@ class CallGraph {
void iterateFunctionsAddrOrder(Scope *scope);
public:
CallGraph(Architecture *g) { glb = g; }
Architecture *getArch(void) const { return glb; }
CallGraphNode *addNode(Funcdata *f);
CallGraphNode *addNode(const Address &addr,const string &nm);
CallGraphNode *findNode(const Address &addr);

View file

@ -52,16 +52,15 @@ void Comment::encode(Encoder &encoder) const
/// Parse a \<comment> element from the given stream decoder
/// \param decoder is the given stream decoder
/// \param manage is a manager for resolving address space references
void Comment::decode(Decoder &decoder,const AddrSpaceManager *manage)
void Comment::decode(Decoder &decoder)
{
emitted = false;
type = 0;
uint4 elemId = decoder.openElement(ELEM_COMMENT);
type = Comment::encodeCommentType(decoder.readString(ATTRIB_TYPE));
funcaddr = Address::decode(decoder,manage);
addr = Address::decode(decoder,manage);
funcaddr = Address::decode(decoder);
addr = Address::decode(decoder);
uint4 subId = decoder.peekElement();
if (subId != 0) {
decoder.openElement();
@ -249,13 +248,13 @@ void CommentDatabaseInternal::encode(Encoder &encoder) const
encoder.closeElement(ELEM_COMMENTDB);
}
void CommentDatabaseInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
void CommentDatabaseInternal::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_COMMENTDB);
while(decoder.peekElement() != 0) {
Comment com;
com.decode(decoder,manage);
com.decode(decoder);
addComment(com.getType(),com.getFuncAddr(),com.getAddr(),com.getText());
}
decoder.closeElement(elemId);

View file

@ -66,7 +66,7 @@ public:
int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index
const string &getText(void) const { return text; } ///< Get the body of the comment
void encode(Encoder &encoder) const; ///< Encode the comment to a stream
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Restore the comment from XML
void decode(Decoder &decoder); ///< Restore the comment from XML
static uint4 encodeCommentType(const string &name); ///< Convert name string to comment property
static string decodeCommentType(uint4 val); ///< Convert comment property to string
};
@ -147,8 +147,7 @@ public:
/// \brief Restore all comments from a \<commentdb> element
///
/// \param decoder is the stream decoder
/// \param manage is a manager for resolving address space references
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
virtual void decode(Decoder &decoder)=0;
};
@ -171,7 +170,7 @@ public:
virtual CommentSet::const_iterator beginComment(const Address &fad) const;
virtual CommentSet::const_iterator endComment(const Address &fad) const;
virtual void encode(Encoder &encoder) const;
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
virtual void decode(Decoder &decoder);
};
/// \brief A class for sorting comments into and within basic blocks

View file

@ -40,9 +40,9 @@ void CommentDatabaseGhidra::fillCache(const Address &fad) const
iter = cache.beginComment(fad);
iterend = cache.endComment(fad);
XmlDecode decoder;
XmlDecode decoder(ghidra);
if (ghidra->getComments(fad,commentfilter,decoder)) {
cache.decode(decoder,ghidra);
cache.decode(decoder);
}
}

View file

@ -47,7 +47,7 @@ public:
virtual CommentSet::const_iterator endComment(const Address &fad) const;
virtual void encode(Encoder &encoder) const {
throw LowlevelError("commentdb::encode unimplemented"); }
virtual void decode(Decoder &decoder,const AddrSpaceManager *trans) {
virtual void decode(Decoder &decoder) {
throw LowlevelError("CommentDatabaseGhidra::decode unimplemented"); }
};

View file

@ -32,7 +32,7 @@ const CPoolRecord *ConstantPoolGhidra::getRecord(const vector<uintb> &refs) cons
{
const CPoolRecord *rec = cache.getRecord(refs);
if (rec == (const CPoolRecord *)0) {
XmlDecode decoder;
XmlDecode decoder(ghidra);
bool success;
try {
success = ghidra->getCPoolRef(refs,decoder);

View file

@ -211,9 +211,8 @@ void SymbolEntry::encode(Encoder &encoder) const
/// if the symbol is dynamic. Then parse the \b uselimit describing the valid
/// range of code addresses.
/// \param decoder is the stream decoder
/// \param manage is an address space manager for constructing Address objects
/// \return the advanced iterator
void SymbolEntry::decode(Decoder &decoder,const AddrSpaceManager *manage)
void SymbolEntry::decode(Decoder &decoder)
{
uint4 elemId = decoder.peekElement();
@ -224,10 +223,10 @@ void SymbolEntry::decode(Decoder &decoder,const AddrSpaceManager *manage)
decoder.closeElement(elemId);
}
else {
addr = Address::decode(decoder,manage);
addr = Address::decode(decoder);
hash = 0;
}
uselimit.decode(decoder,manage);
uselimit.decode(decoder);
}
/// Examine the data-type to decide if the Symbol has the special property
@ -809,7 +808,7 @@ void ExternRefSymbol::decode(Decoder &decoder)
if (attribId == ATTRIB_NAME) // Unless we see it explicitly
name = decoder.readString();
}
refaddr = Address::decode(decoder,scope->getArch());
refaddr = Address::decode(decoder);
decoder.closeElement(elemId);
buildNameType();
}
@ -1583,7 +1582,7 @@ Symbol *Scope::addMapSym(Decoder &decoder)
addSymbolInternal(sym); // This routine may throw, but it will delete sym in this case
while(decoder.peekElement() != 0) {
SymbolEntry entry(sym);
entry.decode(decoder,glb);
entry.decode(decoder);
if (entry.isInvalid()) {
glb->printMessage("WARNING: Throwing out symbol with invalid mapping: "+sym->getName());
removeSymbol(sym);
@ -2632,7 +2631,7 @@ void ScopeInternal::decodeHole(Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_HOLE);
uint4 flags = 0;
Range range;
range.decodeFromAttributes(decoder, glb);
range.decodeFromAttributes(decoder);
decoder.rewindAttributes();
for(;;) {
uint4 attribId = decoder.getNextAttributeId();
@ -2717,7 +2716,7 @@ void ScopeInternal::decode(Decoder &decoder)
}
if (subId== ELEM_RANGELIST) {
RangeList newrangetree;
newrangetree.decode(decoder,glb);
newrangetree.decode(decoder);
glb->symboltab->setRange(this,newrangetree);
}
else if (subId == ELEM_RANGEEQUALSSYMBOLS) {
@ -3262,7 +3261,7 @@ void Database::decode(Decoder &decoder)
decoder.openElement();
uint4 val = decoder.readUnsignedInteger(ATTRIB_VAL);
VarnodeData vData;
vData.decodeFromAttributes(decoder, glb);
vData.decodeFromAttributes(decoder);
Address addr = vData.getAddr();
decoder.closeElement(subId);
flagbase.split(addr) = val;

View file

@ -157,7 +157,7 @@ public:
Datatype *getSizedType(const Address &addr,int4 sz) const; ///< Get the data-type associated with (a piece of) \b this
void printEntry(ostream &s) const; ///< Dump a description of \b this to a stream
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this from a stream
void decode(Decoder &decoder); ///< Decode \b this from a stream
};
typedef rangemap<SymbolEntry> EntryMap; ///< A rangemap of SymbolEntry

View file

@ -52,7 +52,7 @@ Scope *ScopeGhidra::reresolveScope(uint8 id) const
if (cacheScope != (Scope *)0)
return cacheScope; // Scope was previously cached
XmlDecode decoder;
XmlDecode decoder(ghidra);
if (!ghidra->getNamespacePath(id,decoder))
throw LowlevelError("Could not get namespace info");
@ -85,7 +85,7 @@ void ScopeGhidra::decodeHole(Decoder &decoder) const
uint4 elemId = decoder.openElement(ELEM_HOLE);
uint4 flags = 0;
Range range;
range.decodeFromAttributes(decoder,ghidra);
range.decodeFromAttributes(decoder);
decoder.rewindAttributes();
for(;;) {
uint4 attribId = decoder.getNextAttributeId();
@ -212,7 +212,7 @@ Symbol *ScopeGhidra::removeQuery(const Address &addr) const
// Have we queried this address before
if (holes.inRange(addr,1)) return (Symbol *)0;
XmlDecode decoder;
XmlDecode decoder(ghidra);
if (ghidra->getMappedSymbolsXML(addr,decoder)) { // Query GHIDRA about this address
sym = dump2Cache(decoder); // Add it to the cache
}
@ -350,7 +350,7 @@ Funcdata *ScopeGhidra::resolveExternalRefFunction(ExternRefSymbol *sym) const
// If the function isn't in cache, we use the special
// getExternalRefXML interface to recover the external function
SymbolEntry *entry = sym->getFirstWholeMap();
XmlDecode decoder;
XmlDecode decoder(ghidra);
if (ghidra->getExternalRefXML(entry->getAddr(),decoder)) {
FunctionSymbol *funcSym;
// Make sure referenced function is cached

View file

@ -445,11 +445,10 @@ Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz) const
/// \brief Decode a \<pentry> element into \b this object
///
/// \param decoder is the stream decoder
/// \param manage is a manager to resolve address space references
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
/// \param grouped is \b true if \b this will be grouped with other entries
/// \param curList is the list of ParamEntry defined up to this point
void ParamEntry::decode(Decoder &decoder,const AddrSpaceManager *manage,bool normalstack,bool grouped,list<ParamEntry> &curList)
void ParamEntry::decode(Decoder &decoder,bool normalstack,bool grouped,list<ParamEntry> &curList)
{
flags = 0;
@ -499,7 +498,7 @@ void ParamEntry::decode(Decoder &decoder,const AddrSpaceManager *manage,bool nor
if (alignment == size)
alignment = 0;
Address addr;
addr = Address::decode(decoder,manage);
addr = Address::decode(decoder);
decoder.closeElement(elemId);
spaceid = addr.getSpace();
addressbase = addr.getOffset();
@ -1107,18 +1106,17 @@ void ParamListStandard::populateResolver(void)
/// \brief Parse a \<pentry> element and add it to \b this list
///
/// \param decoder is the stream decoder
/// \param manage is manager for parsing address spaces
/// \param effectlist holds any passed back effect records
/// \param groupid is the group to which the new ParamEntry is assigned
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
/// \param grouped is \b true if the new ParamEntry is grouped with other entries
void ParamListStandard::parsePentry(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped)
{
entry.emplace_back(groupid);
entry.back().decode(decoder,manage,normalstack,grouped,entry);
entry.back().decode(decoder,normalstack,grouped,entry);
if (splitFloat) {
if (!grouped && entry.back().getType() == TYPE_FLOAT) {
if (resourceTwoStart >= 0)
@ -1142,13 +1140,12 @@ void ParamListStandard::parsePentry(Decoder &decoder,const AddrSpaceManager *man
///
/// All ParamEntry objects will share the same \b group id.
/// \param decoder is the stream decoder
/// \param manage is manager for parsing address spaces
/// \param effectlist holds any passed back effect records
/// \param groupid is the group to which all ParamEntry elements are assigned
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
void ParamListStandard::parseGroup(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
void ParamListStandard::parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat)
{
int4 basegroup = numgroup;
@ -1156,7 +1153,7 @@ void ParamListStandard::parseGroup(Decoder &decoder,const AddrSpaceManager *mana
ParamEntry *previous2 = (ParamEntry *)0;
uint4 elemId = decoder.openElement(ELEM_GROUP);
while(decoder.peekElement() != 0) {
parsePentry(decoder, manage, effectlist, basegroup, normalstack, autokill, splitFloat, true);
parsePentry(decoder, effectlist, basegroup, normalstack, autokill, splitFloat, true);
ParamEntry &pentry( entry.back() );
if (pentry.getSpace()->getType() == IPTR_JOIN)
throw LowlevelError("<pentry> in the join space not allowed in <group> tag");
@ -1330,8 +1327,7 @@ void ParamListStandard::getRangeList(AddrSpace *spc,RangeList &res) const
}
}
void ParamListStandard::decode(Decoder &decoder,const AddrSpaceManager *manage,
vector<EffectRecord> &effectlist,bool normalstack)
void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack)
{
numgroup = 0;
@ -1362,10 +1358,10 @@ void ParamListStandard::decode(Decoder &decoder,const AddrSpaceManager *manage,
uint4 subId = decoder.peekElement();
if (subId == 0) break;
if (subId == ELEM_PENTRY) {
parsePentry(decoder, manage, effectlist, numgroup, normalstack, autokilledbycall, splitFloat, false);
parsePentry(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat, false);
}
else if (subId == ELEM_GROUP) {
parseGroup(decoder, manage, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
parseGroup(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
}
}
decoder.closeElement(elemId);
@ -1552,10 +1548,10 @@ void ParamListStandardOut::assignMap(const vector<Datatype *> &proto,TypeFactory
}
}
void ParamListStandardOut::decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)
void ParamListStandardOut::decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack)
{
ParamListRegisterOut::decode(decoder,manage,effectlist,normalstack);
ParamListRegisterOut::decode(decoder,effectlist,normalstack);
// Check for double precision entries
list<ParamEntry>::iterator iter;
ParamEntry *previous1 = (ParamEntry *)0;
@ -1901,7 +1897,7 @@ void FspecSpace::encodeAttributes(Encoder &encoder,uintb offset) const
encoder.writeString(ATTRIB_SPACE, "fspec");
else {
AddrSpace *id = fc->getEntryAddress().getSpace();
encoder.writeString(ATTRIB_SPACE, id->getName());
encoder.writeSpace(ATTRIB_SPACE, id);
encoder.writeUnsignedInteger(ATTRIB_OFFSET, fc->getEntryAddress().getOffset());
}
}
@ -1915,7 +1911,7 @@ void FspecSpace::encodeAttributes(Encoder &encoder,uintb offset,int4 size) const
encoder.writeString(ATTRIB_SPACE, "fspec");
else {
AddrSpace *id = fc->getEntryAddress().getSpace();
encoder.writeString(ATTRIB_SPACE, id->getName());
encoder.writeSpace(ATTRIB_SPACE, id);
encoder.writeUnsignedInteger(ATTRIB_OFFSET, fc->getEntryAddress().getOffset());
encoder.writeSignedInteger(ATTRIB_SIZE, size);
}
@ -1993,12 +1989,11 @@ void EffectRecord::encode(Encoder &encoder) const
/// Parse an \<addr> element to get the memory range. The effect type is inherited from the parent.
/// \param grouptype is the effect inherited from the parent
/// \param decoder is the stream decoder
/// \param manage is a manager to resolve address space references
void EffectRecord::decode(uint4 grouptype,Decoder &decoder,const AddrSpaceManager *manage)
void EffectRecord::decode(uint4 grouptype,Decoder &decoder)
{
type = grouptype;
range.decode(decoder,manage);
range.decode(decoder);
}
void ProtoModel::defaultLocalRange(void)
@ -2333,7 +2328,7 @@ void ProtoModel::decode(Decoder &decoder)
uint4 subId = decoder.peekElement();
if (subId == 0) break;
if (subId == ELEM_INPUT) {
input->decode(decoder,glb,effectlist,stackgrowsnegative);
input->decode(decoder,effectlist,stackgrowsnegative);
if (stackspc != (AddrSpace *)0) {
input->getRangeList(stackspc,paramrange);
if (!paramrange.empty())
@ -2341,13 +2336,13 @@ void ProtoModel::decode(Decoder &decoder)
}
}
else if (subId == ELEM_OUTPUT) {
output->decode(decoder,glb,effectlist,stackgrowsnegative);
output->decode(decoder,effectlist,stackgrowsnegative);
}
else if (subId == ELEM_UNAFFECTED) {
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::unaffected,decoder,glb);
effectlist.back().decode(EffectRecord::unaffected,decoder);
}
decoder.closeElement(subId);
}
@ -2355,7 +2350,7 @@ void ProtoModel::decode(Decoder &decoder)
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::killedbycall,decoder,glb);
effectlist.back().decode(EffectRecord::killedbycall,decoder);
}
decoder.closeElement(subId);
}
@ -2363,7 +2358,7 @@ void ProtoModel::decode(Decoder &decoder)
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::return_address,decoder,glb);
effectlist.back().decode(EffectRecord::return_address,decoder);
}
decoder.closeElement(subId);
sawretaddr = true;
@ -2373,7 +2368,7 @@ void ProtoModel::decode(Decoder &decoder)
decoder.openElement();
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,glb);
range.decode(decoder);
localrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
}
decoder.closeElement(subId);
@ -2383,7 +2378,7 @@ void ProtoModel::decode(Decoder &decoder)
decoder.openElement();
while(decoder.peekElement() != 0) {
Range range;
range.decode(decoder,glb);
range.decode(decoder);
paramrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
}
decoder.closeElement(subId);
@ -2392,7 +2387,7 @@ void ProtoModel::decode(Decoder &decoder)
decoder.openElement();
while(decoder.peekElement() != 0) {
likelytrash.emplace_back();
likelytrash.back().decode(decoder,glb);
likelytrash.back().decode(decoder);
}
decoder.closeElement(subId);
}
@ -3219,7 +3214,7 @@ void ProtoStoreInternal::decode(Decoder &decoder,ProtoModel *model)
namelist.push_back(name);
pieces.emplace_back();
ParameterPieces &curparam( pieces.back() );
curparam.addr = Address::decode(decoder,glb);
curparam.addr = Address::decode(decoder);
curparam.type = glb->types->decodeType(decoder);
curparam.flags = flags;
if (curparam.addr.isInvalid())
@ -4422,14 +4417,14 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
outputlock = decoder.readBool();
}
int4 tmpsize;
outpieces.addr = Address::decode(decoder,glb,tmpsize);
outpieces.addr = Address::decode(decoder,tmpsize);
outpieces.type = glb->types->decodeType(decoder);
outpieces.flags = 0;
decoder.closeElement(subId);
}
else if (subId == ELEM_ADDR) { // Old-style specification of return (supported partially for backward compat)
int4 tmpsize;
outpieces.addr = Address::decode(decoder,glb,tmpsize);
outpieces.addr = Address::decode(decoder,tmpsize);
outpieces.type = glb->types->decodeType(decoder);
outpieces.flags = 0;
}
@ -4452,7 +4447,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::unaffected,decoder,glb);
effectlist.back().decode(EffectRecord::unaffected,decoder);
}
decoder.closeElement(subId);
}
@ -4460,7 +4455,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::killedbycall,decoder,glb);
effectlist.back().decode(EffectRecord::killedbycall,decoder);
}
decoder.closeElement(subId);
}
@ -4468,7 +4463,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
decoder.openElement();
while(decoder.peekElement() != 0) {
effectlist.emplace_back();
effectlist.back().decode(EffectRecord::return_address,decoder,glb);
effectlist.back().decode(EffectRecord::return_address,decoder);
}
decoder.closeElement(subId);
}
@ -4476,7 +4471,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
decoder.openElement();
while(decoder.peekElement() != 0) {
likelytrash.emplace_back();
likelytrash.back().decode(decoder,glb);
likelytrash.back().decode(decoder);
}
decoder.closeElement(subId);
}

View file

@ -140,7 +140,7 @@ public:
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;
void decode(Decoder &decoder,const AddrSpaceManager *manage,bool normalstack,bool grouped,list<ParamEntry> &curList);
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
static void orderWithinGroup(const ParamEntry &entry1,const ParamEntry &entry2); ///< Enforce ParamEntry group ordering rules
@ -385,7 +385,7 @@ public:
bool operator==(const EffectRecord &op2) const; ///< Equality operator
bool operator!=(const EffectRecord &op2) const; ///< Inequality operator
void encode(Encoder &encoder) const; ///< Encode the record to a stream
void decode(uint4 grouptype,Decoder &decoder,const AddrSpaceManager *manage); ///< Decode the record from a stream
void decode(uint4 grouptype,Decoder &decoder); ///< Decode the record from a stream
static bool compareByAddress(const EffectRecord &op1,const EffectRecord &op2);
};
@ -531,10 +531,9 @@ public:
/// \brief Restore the model from an \<input> or \<output> element in the stream
///
/// \param decoder is the stream decoder
/// \param manage is used to resolve references to address spaces
/// \param effectlist is a container collecting EffectRecords across all parameters
/// \param normalstack is \b true if parameters are pushed on the stack in the normal order
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)=0;
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack)=0;
virtual ParamList *clone(void) const=0; ///< Clone this parameter list model
};
@ -571,9 +570,9 @@ protected:
void calcDelay(void); ///< Calculate the maximum heritage delay for any potential parameter in this list
void addResolverRange(AddrSpace *spc,uintb first,uintb last,ParamEntry *paramEntry,int4 position);
void populateResolver(void); ///< Build the ParamEntry resolver maps
void parsePentry(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
void parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped);
void parseGroup(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
void parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat);
public:
ParamListStandard(void) {} ///< Construct for use with decode()
@ -594,7 +593,7 @@ public:
virtual AddrSpace *getSpacebase(void) const { return spacebase; }
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
virtual int4 getMaxDelay(void) const { return maxdelay; }
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
@ -646,7 +645,7 @@ public:
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListRegisterOut(op2) {} ///< Copy constructor
virtual uint4 getType(void) const { return p_standard_out; }
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};

View file

@ -735,7 +735,7 @@ uint8 Funcdata::decode(Decoder &decoder)
throw LowlevelError("Missing function name");
if (size == -1)
throw LowlevelError("Missing function size");
baseaddr = Address::decode( decoder, glb );
baseaddr = Address::decode( decoder );
for(;;) {
uint4 subId = decoder.peekElement();
if (subId == 0) break;

View file

@ -343,7 +343,7 @@ void ArchitectureGhidra::buildTypegrp(DocumentStorage &store)
const Element *el = store.getTag("coretypes");
types = new TypeFactoryGhidra(this);
if (el != (const Element *)0) {
XmlDecode decoder(el);
XmlDecode decoder(this,el);
types->decodeCoreTypes(decoder);
}
else {
@ -864,7 +864,7 @@ ArchitectureGhidra::ArchitectureGhidra(const string &pspec,const string &cspec,c
: Architecture(), sin(i), sout(o), encoder(sout)
{
print->setXML(true);
print->setMarkup(true);
print->setOutputStream(&sout);
pspecxml = pspec;
cspecxml = cspec;

View file

@ -19,22 +19,22 @@ const TrackedSet &ContextGhidra::getTrackedSet(const Address &addr) const
{
cache.clear();
XmlDecode decoder;
((ArchitectureGhidra *)glb)->getTrackedRegisters(addr,decoder);
XmlDecode decoder(glb);
glb->getTrackedRegisters(addr,decoder);
uint4 elemId = decoder.openElement(ELEM_TRACKED_POINTSET);
decodeTracked(decoder,glb,cache);
decodeTracked(decoder,cache);
decoder.closeElement(elemId);
return cache;
}
void ContextGhidra::decode(Decoder &decoder,const AddrSpaceManager *manage)
void ContextGhidra::decode(Decoder &decoder)
{
decoder.skipElement(); // Ignore details handled by ghidra
}
void ContextGhidra::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)
void ContextGhidra::decodeFromSpec(Decoder &decoder)
{
decoder.skipElement(); // Ignore details handled by ghidra

View file

@ -51,8 +51,8 @@ public:
virtual const TrackedSet &getTrackedSet(const Address &addr) const;
// Ignored routines (taken care of by GHIDRA)
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
virtual void decode(Decoder &decoder);
virtual void decodeFromSpec(Decoder &decoder);
// Unimplemented routines (should never be called)
virtual int getContextSize(void) const {

View file

@ -47,15 +47,15 @@ void connect_to_console(Funcdata *fd)
decomp_data->fd = fd;
decomp_data->conf = fd->getArch();
ostream *oldPrintStream = decomp_data->conf->print->getOutputStream();
bool emitXml = decomp_data->conf->print->emitsXml();
bool emitMarkup = decomp_data->conf->print->emitsMarkup();
decomp_data->conf->setDebugStream(remote->getOutputStream());
decomp_data->conf->print->setOutputStream(remote->getOutputStream());
decomp_data->conf->print->setXML(false);
decomp_data->conf->print->setMarkup(false);
ghidra_dcp->reset();
mainloop(ghidra_dcp);
decomp_data->conf->clearAnalysis(fd);
decomp_data->conf->print->setOutputStream(oldPrintStream);
decomp_data->conf->print->setXML(emitXml);
decomp_data->conf->print->setMarkup(emitMarkup);
fd->debugDisable();
decomp_data->conf->allacts.getCurrent()->clearBreakPoints();
}
@ -274,9 +274,9 @@ void DecompileAt::loadParameters(void)
{
GhidraCommand::loadParameters();
XmlDecode decoder;
XmlDecode decoder(ghidra);
ArchitectureGhidra::readStream(sin,decoder); // Read encoded address directly from in stream
addr = Address::decode(decoder,ghidra); // Decode for functions address
addr = Address::decode(decoder); // Decode for functions address
}
void DecompileAt::rawAction(void)
@ -328,9 +328,9 @@ void StructureGraph::loadParameters(void)
{
GhidraCommand::loadParameters();
XmlDecode decoder;
XmlDecode decoder(ghidra);
ArchitectureGhidra::readStream(sin,decoder);
ingraph.decode(decoder,ghidra);
ingraph.decode(decoder);
}
void StructureGraph::rawAction(void)
@ -408,8 +408,8 @@ void SetOptions::loadParameters(void)
{
GhidraCommand::loadParameters();
decoder.clear();
ArchitectureGhidra::readStream(sin,decoder);
optionsListTag.clear();
ArchitectureGhidra::readStringStream(sin, optionsListTag);
}
void SetOptions::rawAction(void)
@ -418,8 +418,12 @@ void SetOptions::rawAction(void)
res = false;
ghidra->resetDefaults();
DocumentStorage storage;
istringstream s(optionsListTag);
Document *doc = storage.parseDocument(s);
XmlDecode decoder(ghidra,doc->getRoot());
ghidra->options->decode(decoder);
decoder.clear();
optionsListTag.clear();
res = true;
}

View file

@ -220,7 +220,7 @@ public:
/// The command returns a single character message, 't' or 'f', indicating whether the
/// configuration succeeded.
class SetOptions : public GhidraCommand {
XmlDecode decoder; ///< The XML option document
string optionsListTag; ///< The <optionslist> XML tag
virtual void loadParameters(void);
virtual void sendResult(void);
public:

View file

@ -36,7 +36,7 @@ void GhidraTranslate::initialize(DocumentStorage &store)
const Element *el = store.getTag("sleigh");
if (el == (const Element *)0)
throw LowlevelError("Could not find ghidra sleigh tag");
XmlDecode decoder(el);
XmlDecode decoder(this,el);
decode(decoder);
}
@ -46,7 +46,7 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
map<string,VarnodeData>::const_iterator iter = nm2addr.find(nm);
if (iter != nm2addr.end())
return (*iter).second;
XmlDecode decoder;
XmlDecode decoder(glb);
try {
if (!glb->getRegister(nm,decoder)) // Ask Ghidra client about the register
throw LowlevelError("No register named "+nm);
@ -59,7 +59,7 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
}
Address regaddr;
int4 regsize;
regaddr = Address::decode( decoder, this, regsize);
regaddr = Address::decode( decoder, regsize);
VarnodeData vndata;
vndata.space = regaddr.getSpace();
vndata.offset = regaddr.getOffset();

View file

@ -51,12 +51,11 @@ void TrackedContext::encode(Encoder &encoder) const
/// Parse a \<set> element to fill in the storage and value details.
/// \param decoder is the stream decoder
/// \param manage is the manager used to decode address references
void TrackedContext::decode(Decoder &decoder,const AddrSpaceManager *manage)
void TrackedContext::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_SET);
loc.decodeFromAttributes(decoder, manage);
loc.decodeFromAttributes(decoder);
val = decoder.readUnsignedInteger(ATTRIB_VAL);
decoder.closeElement(elemId);
@ -86,16 +85,14 @@ void ContextDatabase::encodeTracked(Encoder &encoder,const Address &addr,const T
/// Parse a \<tracked_pointset> element, decoding each child in turn to populate a list of
/// TrackedContext objects.
/// \param decoder is the given stream decoder
/// \param manage is used to resolve address space references
/// \param vec is the container that will hold the new TrackedContext objects
void ContextDatabase::decodeTracked(Decoder &decoder,const AddrSpaceManager *manage,
TrackedSet &vec)
void ContextDatabase::decodeTracked(Decoder &decoder,TrackedSet &vec)
{
vec.clear(); // Clear out any old stuff
while(decoder.peekElement() != 0) {
vec.emplace_back();
vec.back().decode(decoder,manage);
vec.back().decode(decoder);
}
}
@ -498,7 +495,7 @@ void ContextInternal::encode(Encoder &encoder) const
encoder.closeElement(ELEM_CONTEXT_POINTS);
}
void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
void ContextInternal::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_CONTEXT_POINTS);
@ -513,14 +510,14 @@ void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
}
else {
VarnodeData vData;
vData.decodeFromAttributes(decoder, manage);
vData.decodeFromAttributes(decoder);
decodeContext(decoder,vData.getAddr(),Address());
}
}
else if (subId == ELEM_TRACKED_POINTSET) {
VarnodeData vData;
vData.decodeFromAttributes(decoder, manage);
decodeTracked(decoder,manage,trackbase.split(vData.getAddr()) );
vData.decodeFromAttributes(decoder);
decodeTracked(decoder,trackbase.split(vData.getAddr()) );
}
else
throw LowlevelError("Bad <context_points> tag");
@ -529,7 +526,7 @@ void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
decoder.closeElement(elemId);
}
void ContextInternal::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)
void ContextInternal::decodeFromSpec(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_CONTEXT_DATA);
@ -537,14 +534,14 @@ void ContextInternal::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *ma
uint4 subId = decoder.openElement();
if (subId == 0) break;
Range range;
range.decodeFromAttributes(decoder, manage); // There MUST be a range
range.decodeFromAttributes(decoder); // There MUST be a range
Address addr1 = range.getFirstAddr();
Address addr2 = range.getLastAddrOpen(manage);
Address addr2 = range.getLastAddrOpen(decoder.getAddrSpaceManager());
if (subId == ELEM_CONTEXT_SET) {
decodeContext(decoder,addr1,addr2);
}
else if (subId == ELEM_TRACKED_SET) {
decodeTracked(decoder,manage,createSet(addr1,addr2));
decodeTracked(decoder,createSet(addr1,addr2));
}
else
throw LowlevelError("Bad <context_data> tag");

View file

@ -76,7 +76,7 @@ public:
struct TrackedContext {
VarnodeData loc; ///< Storage details of the register being tracked
uintb val; ///< The value of the register
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this from a stream
void decode(Decoder &decoder); ///< Decode \b this from a stream
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
};
typedef vector<TrackedContext> TrackedSet; ///< A set of tracked registers and their values (at one code point)
@ -116,7 +116,7 @@ typedef vector<TrackedContext> TrackedSet; ///< A set of tracked registers and
class ContextDatabase {
protected:
static void encodeTracked(Encoder &encoder,const Address &addr,const TrackedSet &vec);
static void decodeTracked(Decoder &decoder,const AddrSpaceManager *manage,TrackedSet &vec);
static void decodeTracked(Decoder &decoder,TrackedSet &vec);
/// \brief Retrieve the context variable description object by name
///
@ -234,16 +234,14 @@ public:
/// \brief Restore the state of \b this database object from the given stream decoder
///
/// \param decoder is the given stream decoder
/// \param manage is used to resolve address space references
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
virtual void decode(Decoder &decoder)=0;
/// \brief Add initial context state from elements in the compiler/processor specifications
///
/// Parse a \<context_data> element from the given stream decoder from either the compiler
/// or processor specification file for the architecture, initializing this database.
/// \param decoder is the given stream decoder
/// \param manage is used to resolve address space references
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)=0;
virtual void decodeFromSpec(Decoder &decoder)=0;
void setVariableDefault(const string &nm,uintm val); ///< Provide a default value for a context variable
uintm getDefaultValue(const string &nm) const; ///< Retrieve the default value for a context variable
@ -305,8 +303,8 @@ public:
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2);
virtual void encode(Encoder &encoder) const;
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
virtual void decode(Decoder &decoder);
virtual void decodeFromSpec(Decoder &decoder);
};
/// \brief A helper class for caching the active context blob to minimize database lookups

View file

@ -880,9 +880,9 @@ void IfcPrintCXml::execute(istream &s)
throw IfaceExecutionError("No function selected");
dcp->conf->print->setOutputStream(status->fileoptr);
dcp->conf->print->setXML(true);
dcp->conf->print->setMarkup(true);
dcp->conf->print->docFunction(dcp->fd);
dcp->conf->print->setXML(false);
dcp->conf->print->setMarkup(false);
}
/// \class IfcPrintCStruct
@ -2724,7 +2724,7 @@ void IfcCallGraphLoad::execute(istream &s)
Document *doc = store.parseDocument(is);
dcp->allocateCallGraph();
XmlDecode decoder(doc->getRoot());
XmlDecode decoder(dcp->conf,doc->getRoot());
dcp->cgraph->decoder(decoder);
*status->optr << "Successfully read in callgraph" << endl;
@ -3016,8 +3016,8 @@ void IfcStructureBlocks::execute(istream &s)
try {
BlockGraph ingraph;
XmlDecode decoder(doc->getRoot());
ingraph.decode(decoder,dcp->conf);
XmlDecode decoder(dcp->conf,doc->getRoot());
ingraph.decode(decoder);
BlockGraph resultgraph;
vector<FlowBlock *> rootlist;

View file

@ -48,7 +48,7 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
{
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
XmlDecode decoder;
XmlDecode decoder(ghidra);
try {
if (!ghidra->getPcodeInject(name,type,con,decoder))
throw LowlevelError("Could not retrieve pcode snippet: "+name);
@ -61,7 +61,7 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
}
uint4 elemId = decoder.openElement();
while(decoder.peekElement() != 0)
emit.decodeOp(decoder,ghidra->translate);
emit.decodeOp(decoder);
decoder.closeElement(elemId);
}
@ -121,7 +121,7 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
{
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
XmlDecode decoder;
XmlDecode decoder(ghidra);
try {
if (!ghidra->getPcodeInject(name,type,con,decoder))
throw LowlevelError("Could not retrieve pcode snippet: "+name);
@ -134,7 +134,7 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
}
uint4 elemId = decoder.openElement();
while(decoder.peekElement() != 0)
emit.decodeOp(decoder,ghidra->translate);
emit.decodeOp(decoder);
decoder.closeElement(elemId);
}

View file

@ -259,7 +259,7 @@ InjectPayloadDynamic::~InjectPayloadDynamic(void)
void InjectPayloadDynamic::decodeEntry(Decoder &decoder)
{
Address addr = Address::decode(decoder,glb);
Address addr = Address::decode(decoder);
uint4 subId = decoder.openElement(ELEM_PAYLOAD);
istringstream s(decoder.readString(ATTRIB_CONTENT));
try {
@ -282,10 +282,10 @@ void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
if (eiter == addrMap.end())
throw LowlevelError("Missing dynamic inject");
const Element *el = (*eiter).second->getRoot();
XmlDecode decoder(el);
XmlDecode decoder(glb->translate,el);
uint4 rootId = decoder.openElement(ELEM_INST);
while(decoder.peekElement() != 0)
emit.decodeOp(decoder,glb->translate);
emit.decodeOp(decoder);
decoder.closeElement(rootId);
}

View file

@ -40,14 +40,13 @@ void LoadTable::encode(Encoder &encoder) const
}
/// \param decoder is the stream decoder
/// \param glb is the architecture for resolving address space tags
void LoadTable::decode(Decoder &decoder,Architecture *glb)
void LoadTable::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_LOADTABLE);
size = decoder.readSignedInteger(ATTRIB_SIZE);
num = decoder.readSignedInteger(ATTRIB_NUM);
addr = Address::decode( decoder, glb);
addr = Address::decode( decoder );
decoder.closeElement(elemId);
}
@ -1934,7 +1933,7 @@ void JumpBasicOverride::encode(Encoder &encoder) const
encoder.closeElement(ELEM_BASICOVERRIDE);
}
void JumpBasicOverride::decode(Decoder &decoder,Architecture *glb)
void JumpBasicOverride::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_BASICOVERRIDE);
@ -1943,12 +1942,12 @@ void JumpBasicOverride::decode(Decoder &decoder,Architecture *glb)
if (subId == 0) break;
if (subId == ELEM_DEST) {
VarnodeData vData;
vData.decodeFromAttributes(decoder, glb);
vData.decodeFromAttributes(decoder);
adset.insert( vData.getAddr() );
}
else if (subId == ELEM_NORMADDR) {
VarnodeData vData;
vData.decodeFromAttributes(decoder, glb);
vData.decodeFromAttributes(decoder);
normaddress = vData.getAddr();
}
else if (subId == ELEM_NORMHASH) {
@ -2645,7 +2644,7 @@ void JumpTable::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_JUMPTABLE);
opaddress = Address::decode( decoder, glb);
opaddress = Address::decode( decoder );
bool missedlabel = false;
for(;;) {
uint4 subId = decoder.peekElement();
@ -2667,17 +2666,17 @@ void JumpTable::decode(Decoder &decoder)
}
if (!foundlabel) // No label attribute
missedlabel = true; // No following entries are allowed to have a label attribute
addresstable.push_back( Address::decode( decoder, glb) );
addresstable.push_back( Address::decode( decoder ) );
}
else if (subId == ELEM_LOADTABLE) {
loadpoints.emplace_back();
loadpoints.back().decode(decoder,glb);
loadpoints.back().decode(decoder);
}
else if (subId == ELEM_BASICOVERRIDE) {
if (jmodel != (JumpModel *)0)
throw LowlevelError("Duplicate jumptable override specs");
jmodel = new JumpBasicOverride(this);
jmodel->decode(decoder,glb);
jmodel->decode(decoder);
}
}
decoder.closeElement(elemId);

View file

@ -60,7 +60,7 @@ public:
LoadTable(const Address &ad,int4 sz,int4 nm) { addr = ad; size = sz; num = nm; } ///< Construct a full table
bool operator<(const LoadTable &op2) const { return (addr < op2.addr); } ///< Compare \b this with another table by address
void encode(Encoder &encoder) const; ///< Encode a description of \b this as an \<loadtable> element
void decode(Decoder &decoder,Architecture *glb); ///< Decode \b this table from a \<loadtable> element
void decode(Decoder &decoder); ///< Decode \b this table from a \<loadtable> element
static void collapseTable(vector<LoadTable> &table); ///< Collapse a sequence of table descriptions
};
@ -321,7 +321,7 @@ public:
virtual JumpModel *clone(JumpTable *jt) const=0; ///< Clone \b this model
virtual void clear(void) {} ///< Clear any non-permanent aspects of the model
virtual void encode(Encoder &encoder) const {} ///< Encode this model to a stream
virtual void decode(Decoder &decoder,Architecture *glb) {} ///< Decode \b this model from a stream
virtual void decode(Decoder &decoder) {} ///< Decode \b this model from a stream
};
/// \brief A trivial jump-table model, where the BRANCHIND input Varnode is the switch variable
@ -463,7 +463,7 @@ public:
virtual JumpModel *clone(JumpTable *jt) const;
virtual void clear(void);
virtual void encode(Encoder &encoder) const;
virtual void decode(Decoder &decoder,Architecture *glb);
virtual void decode(Decoder &decoder);
};
class JumpAssistOp;

View file

@ -81,27 +81,19 @@ void LoadImageXml::open(const AddrSpaceManager *m)
uint4 sz; // unused size
// Read parsed xml file
XmlDecode decoder(rootel);
XmlDecode decoder(m,rootel);
uint4 elemId = decoder.openElement(ELEM_BINARYIMAGE);
for(;;) {
uint4 subId = decoder.openElement();
if (subId == 0) break;
if (subId==ELEM_SYMBOL) {
AddrSpace *base = (AddrSpace *)0;
string spaceName = decoder.readString(ATTRIB_SPACE);
base = manage->getSpaceByName(spaceName);
if (base == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+spaceName);
AddrSpace *base = decoder.readSpace(ATTRIB_SPACE);
Address addr(base,base->decodeAttributes(decoder,sz));
string nm = decoder.readString(ATTRIB_NAME);
addrtosymbol[addr] = nm;
}
else if (subId == ELEM_BYTECHUNK) {
AddrSpace *base = (AddrSpace *)0;
string spaceName = decoder.readString(ATTRIB_SPACE);
base = manage->getSpaceByName(spaceName);
if (base == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+spaceName);
AddrSpace *base = decoder.readSpace(ATTRIB_SPACE);
Address addr(base,base->decodeAttributes(decoder,sz));
map<Address,vector<uint1> >::iterator chnkiter;
vector<uint1> &vec( chunk[addr] );

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "marshal.hh"
#include <sstream>
#include "translate.hh"
unordered_map<string,uint4> AttributeId::lookupAttributeId;
@ -348,6 +348,35 @@ string XmlDecode::readString(const AttributeId &attribId)
return el->getAttributeValue(index);
}
AddrSpace *XmlDecode::readSpace(void)
{
const Element *el = elStack.back();
string nm = el->getAttributeValue(attributeIndex);
AddrSpace *res = spcManager->getSpaceByName(nm);
if (res == (AddrSpace *)0)
throw XmlError("Unknown address space name: "+nm);
return res;
}
AddrSpace *XmlDecode::readSpace(const AttributeId &attribId)
{
const Element *el = elStack.back();
string nm;
if (attribId == ATTRIB_CONTENT) {
nm = el->getContent();
}
else {
int4 index = findMatchingAttribute(el, attribId.getName());
nm = el->getAttributeValue(index);
}
AddrSpace *res = spcManager->getSpaceByName(nm);
if (res == (AddrSpace *)0)
throw XmlError("Unknown address space name: "+nm);
return res;
}
void XmlEncode::openElement(const ElementId &elemId)
{
@ -429,6 +458,20 @@ void XmlEncode::writeString(const AttributeId &attribId,const string &val)
a_v(outStream,attribId.getName(),val);
}
void XmlEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
{
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
outStream << '>';
elementTagIsOpen = false;
}
xml_escape(outStream, spc->getName().c_str());
return;
}
a_v(outStream,attribId.getName(),spc->getName());
}
// Common attributes. Attributes with multiple uses
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
@ -457,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
AttributeId ATTRIB_VALUE = AttributeId("value",25);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",136); // Number serves as next open index
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",144); // Number serves as next open index
ElementId ELEM_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2);
@ -470,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
ElementId ELEM_VALUE = ElementId("value",9);
ElementId ELEM_VOID = ElementId("void",10);
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",208); // Number serves as next open index
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",218); // Number serves as next open index

View file

@ -75,6 +75,9 @@ public:
friend bool operator!=(const ElementId &op1,uint4 id) { return (op1.id != id); } ///< Test inequality of an ElementId with a raw integer id
};
class AddrSpace;
class AddrSpaceManager;
/// \brief A class for reading structured data from a stream
///
/// All data is loosely structured as with an XML document. A document contains a nested set
@ -89,7 +92,12 @@ public:
/// whose data can be extracted using a read*(AttributeId) call that is passed the special ATTRIB_CONTENT id.
/// This attribute will not be traversed by getNextAttribute().
class Decoder {
protected:
const AddrSpaceManager *spcManager; ///< Manager for decoding address space attributes
public:
Decoder(const AddrSpaceManager *spc) { spcManager = spc; } ///< Base constructor
const AddrSpaceManager *getAddrSpaceManager(void) const { return spcManager; } ///< Get the manager used for address space decoding
virtual ~Decoder(void) {} ///< Destructor
/// \brief Clear any current decoding state
@ -215,6 +223,21 @@ public:
/// \return the string associated with the attribute
virtual string readString(const AttributeId &attribId)=0;
/// \brief Parse the current attribute as an address space
///
/// The last attribute, as returned by getNextAttributeId, is returned as an address space.
/// \return the address space associated with the current attribute.
virtual AddrSpace *readSpace(void)=0;
/// \brief Find the specific attribute in the current element and return it as an address space
///
/// Search attributes from the current element for a match to the given attribute id.
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is throw.
/// Parse via getNextAttributeId is reset.
/// \param attribId is the specific attribute id to match
/// \return the address space associated with the attribute
virtual AddrSpace *readSpace(const AttributeId &attribId)=0;
/// \brief Skip parsing of the next element
///
/// The element skipped is the one that would be opened by the next call to openElement.
@ -283,6 +306,13 @@ public:
/// \param attribId is the given AttributeId annotation
/// \param val is the string to encode
virtual void writeString(const AttributeId &attribId,const string &val)=0;
/// \brief Write an address space reference into the encoding
///
/// The address space is associated with the given AttributeId annotation and the current open element.
/// \param attribId is the given AttributeId annotation
/// \param spc is the address space to encode
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc)=0;
};
/// \brief An XML based decoder
@ -298,8 +328,10 @@ class XmlDecode : public Decoder {
int4 attributeIndex; ///< Position of \e current attribute to parse (in \e current element)
int4 findMatchingAttribute(const Element *el,const string &attribName);
public:
XmlDecode(const Element *root) { document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root
XmlDecode(void) { document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
XmlDecode(const AddrSpaceManager *spc,const Element *root) : Decoder(spc) {
document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root
XmlDecode(const AddrSpaceManager *spc) : Decoder(spc) {
document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
virtual ~XmlDecode(void);
virtual void clear(void);
virtual void ingestStream(istream &s);
@ -318,6 +350,8 @@ public:
virtual uintb readUnsignedInteger(const AttributeId &attribId);
virtual string readString(void);
virtual string readString(const AttributeId &attribId);
virtual AddrSpace *readSpace(void);
virtual AddrSpace *readSpace(const AttributeId &attribId);
};
/// \brief An XML based encoder
@ -337,6 +371,7 @@ public:
virtual void writeSignedInteger(const AttributeId &attribId,intb val);
virtual void writeUnsignedInteger(const AttributeId &attribId,uintb val);
virtual void writeString(const AttributeId &attribId,const string &val);
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc);
};
extern ElementId ELEM_UNKNOWN; ///< Special element to represent an element with an unrecognized name

View file

@ -427,7 +427,7 @@ void PcodeOp::encode(Encoder &encoder) const
if ((i==0)&&((code()==CPUI_STORE)||(code()==CPUI_LOAD))) {
AddrSpace *spc = vn->getSpaceFromConst();
encoder.openElement(ELEM_SPACEID);
encoder.writeString(ATTRIB_NAME, spc->getName());
encoder.writeSpace(ATTRIB_NAME, spc);
encoder.closeElement(ELEM_SPACEID);
}
else {

View file

@ -310,7 +310,7 @@ void Override::encode(Encoder &encoder,Architecture *glb) const
if (deadcodedelay[i] < 0) continue;
AddrSpace *spc = glb->getSpace(i);
encoder.openElement(ELEM_DEADCODEDELAY);
encoder.writeString(ATTRIB_SPACE, spc->getName());
encoder.writeSpace(ATTRIB_SPACE, spc);
encoder.writeSignedInteger(ATTRIB_DELAY, deadcodedelay[i]);
encoder.closeElement(ELEM_DEADCODEDELAY);
}
@ -359,36 +359,36 @@ void Override::decode(Decoder &decoder,Architecture *glb)
uint4 subId = decoder.openElement();
if (subId == 0) break;
if (subId == ELEM_INDIRECTOVERRIDE) {
Address callpoint = Address::decode(decoder,glb);
Address directcall = Address::decode(decoder,glb);
Address callpoint = Address::decode(decoder);
Address directcall = Address::decode(decoder);
insertIndirectOverride(callpoint,directcall);
}
else if (subId == ELEM_PROTOOVERRIDE) {
Address callpoint = Address::decode(decoder,glb);
Address callpoint = Address::decode(decoder);
FuncProto *fp = new FuncProto();
fp->setInternal(glb->defaultfp,glb->types->getTypeVoid());
fp->decode(decoder,glb);
insertProtoOverride(callpoint,fp);
}
else if (subId == ELEM_FORCEGOTO) {
Address targetpc = Address::decode(decoder,glb);
Address destpc = Address::decode(decoder,glb);
Address targetpc = Address::decode(decoder);
Address destpc = Address::decode(decoder);
insertForceGoto(targetpc,destpc);
}
else if (subId == ELEM_DEADCODEDELAY) {
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
AddrSpace *spc = glb->getSpaceByName( decoder.readString(ATTRIB_SPACE));
if ((spc == (AddrSpace *)0)||(delay < 0))
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
if (delay < 0)
throw LowlevelError("Bad deadcodedelay tag");
insertDeadcodeDelay(spc,delay);
}
else if (subId == ELEM_MULTISTAGEJUMP) {
Address callpoint = Address::decode(decoder,glb);
Address callpoint = Address::decode(decoder);
insertMultistageJump(callpoint);
}
else if (subId == ELEM_FLOW) {
uint4 type = stringToType(decoder.readString(ATTRIB_TYPE));
Address addr = Address::decode(decoder,glb);
Address addr = Address::decode(decoder);
if ((type == Override::NONE)||(addr.isInvalid()))
throw LowlevelError("Bad flowoverride tag");
insertFlowOverride(addr,type);

View file

@ -18,19 +18,17 @@
/// Build this VarnodeData from an \<addr>, \<register>, or \<varnode> element.
/// \param decoder is the stream decoder
/// \param manage is the address space manager
void VarnodeData::decode(Decoder &decoder,const AddrSpaceManager *manage)
void VarnodeData::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement();
decodeFromAttributes(decoder,manage);
decodeFromAttributes(decoder);
decoder.closeElement(elemId);
}
/// Collect attributes for the VarnodeData possibly from amidst other attributes
/// \param decoder is the stream decoder
/// \param manage is the address space manager
void VarnodeData::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage)
void VarnodeData::decodeFromAttributes(Decoder &decoder)
{
space = (AddrSpace *)0;
@ -40,16 +38,13 @@ void VarnodeData::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *
if (attribId == 0)
break; // Its possible to have no attributes in an <addr/> tag
if (attribId == ATTRIB_SPACE) {
string nm = decoder.readString();
space = manage->getSpaceByName(nm);
if (space == (AddrSpace *)0)
throw LowlevelError("Unknown space name: "+nm);
space = decoder.readSpace();
decoder.rewindAttributes();
offset = space->decodeAttributes(decoder,size);
break;
}
else if (attribId == ATTRIB_NAME) {
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
const Translate *trans = decoder.getAddrSpaceManager()->getDefaultCodeSpace()->getTrans();
const VarnodeData &point(trans->getRegister(decoder.readString()));
*this = point;
break;

View file

@ -45,10 +45,10 @@ struct VarnodeData {
AddrSpace *getSpaceFromConst(void) const;
/// Recover this object from a stream
void decode(Decoder &decoder,const AddrSpaceManager *manage);
void decode(Decoder &decoder);
/// Recover \b this object from attributes of the current open element
void decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage);
void decodeFromAttributes(Decoder &decoder);
/// Does \b this container another given VarnodeData
bool contains(const VarnodeData &op2) const;

View file

@ -16,345 +16,278 @@
#include "prettyprint.hh"
#include "funcdata.hh"
const char *EmitXml::highlight[] = { "color=\"keyword\"",
"color=\"comment\"",
"color=\"type\"",
"color=\"funcname\"",
"color=\"var\"",
"color=\"const\"",
"color=\"param\"",
"color=\"global\"",
AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",136);
AttributeId ATTRIB_CLOSE = AttributeId("close",137);
AttributeId ATTRIB_COLOR = AttributeId("color",138);
AttributeId ATTRIB_INDENT = AttributeId("indent",139);
AttributeId ATTRIB_OFF = AttributeId("off",140);
AttributeId ATTRIB_OPEN = AttributeId("open",141);
AttributeId ATTRIB_OPREF = AttributeId("opref",142);
AttributeId ATTRIB_VARREF = AttributeId("varref",143);
ElementId ELEM_BREAK = ElementId("break",208);
ElementId ELEM_CLANG_DOCUMENT = ElementId("clang_document",209);
ElementId ELEM_FUNCNAME = ElementId("funcname",210);
ElementId ELEM_FUNCPROTO = ElementId("funcproto",211);
ElementId ELEM_LABEL = ElementId("label",212);
ElementId ELEM_RETURN_TYPE = ElementId("return_type",213);
ElementId ELEM_STATEMENT = ElementId("statement",214);
ElementId ELEM_SYNTAX = ElementId("syntax",215);
ElementId ELEM_VARDECL = ElementId("vardecl",216);
ElementId ELEM_VARIABLE = ElementId("variable",217);
const string Emit::EMPTY_STRING = "";
const string EmitMarkup::highlight[] = { "keyword",
"comment",
"type",
"funcname",
"var",
"const",
"param",
"global",
"" };
/// Inform the emitter that generation of the source code document has begun
/// \return an id associated with the document
int4 EmitXml::beginDocument(void) {
*s << "<clang_document " << highlight[(int4)no_color] << '>';
return 0;
}
/// Inform the emitter that generation of the source code document is finished
/// \param id is the id associated with the document (as returned by beginDocument)
void EmitXml::endDocument(int4 id) {
*s << "</clang_document>";
}
/// Inform the emitter that generation of a function body has begun
/// \return an id associated with the function body
int4 EmitXml::beginFunction(const Funcdata *fd) {
*s << "<function " << highlight[(int4)no_color];
*s << '>';
return 0;
}
/// Inform the emitter that generation of a function body has ended
/// \param id is the id associated with the function body (as returned by beginFunction)
void EmitXml::endFunction(int4 id) {
*s << "</function>";
}
/// Inform the emitter that a new control-flow section is starting. This is a source code unit
/// usually surrounded with curly braces '{' and '}'.
/// \param bl is the block structure object associated with the section
/// \return an id associated with the section
int4 EmitXml::beginBlock(const FlowBlock *bl) {
*s << "<block " << highlight[(int4)no_color] << " blockref=\"0x" << hex <<
bl->getIndex() << "\">";
return 0;
}
/// Inform the emitter that a control-flow section is ending.
/// \param id is the id associated with the section (as returned by beginBlock)
void EmitXml::endBlock(int4 id) {
*s << "</block>";
}
/// Tell the emitter that a new line is desired at the current indent level
void EmitXml::tagLine(void) {
emitPending();
*s << "<break " << highlight[(int4)no_color] << " indent=\"0x" << hex <<
indentlevel << "\"/>";
}
/// Tell the emitter that a new line is desired at a specific indent level. The indent level
/// is overridden only for the line, then it returns to its previous value.
/// \param indent is the desired indent level for the new line
void EmitXml::tagLine(int4 indent) {
emitPending();
*s << "<break " << highlight[(int4)no_color] << " indent=\"0x" << hex <<
indent << "\"/>";
}
/// Inform the emitter that generation of a function's return type is starting.
/// \param vn (if non-null) is the storage location for the return value
/// \return an id associated with the return type
int4 EmitXml::beginReturnType(const Varnode *vn) {
*s << "<return_type " << highlight[(int4)no_color];
if (vn != (const Varnode *)0)
*s << " varref=\"0x" << hex << vn->getCreateIndex() << "\">";
else
*s << '>';
return 0;
}
/// Inform the emitter that generation of a function's return type is ending.
/// \param id is the id associated with the return type (as returned by beginReturnType)
void EmitXml::endReturnType(int4 id) {
*s << "</return_type>";
}
/// Inform the emitter that a variable declaration has started.
/// \param sym is the symbol being declared
/// \return an id associated with the declaration
int4 EmitXml::beginVarDecl(const Symbol *sym) {
*s << "<vardecl " << highlight[(int4)no_color];
*s << " symref=\"0x" << hex << sym->getId() << "\">";
return 0;
}
/// Inform the emitter that a variable declaration has ended.
/// \param id is the id associated with the declaration (as returned by beginVarDecl)
void EmitXml::endVarDecl(int4 id) {
*s << "</vardecl>";
}
/// Inform the emitter that a source code statement is beginning.
/// \param op is the root p-code operation of the statement
/// \return an id associated with the statement
int4 EmitXml::beginStatement(const PcodeOp *op) {
*s << "<statement " << highlight[(int4)no_color];
if (op != (const PcodeOp *)0)
*s << " opref=\"0x" << hex << op->getTime() << "\">";
else
*s << '>';
return 0;
}
/// Inform the emitter that a source code statement is ending.
/// \param id is the id associated with the statement (as returned by beginStatement)
void EmitXml::endStatement(int4 id) {
*s << "</statement>";
}
/// Inform the emitter that a function prototype is starting.
/// \return an id associated with the prototype
int4 EmitXml::beginFuncProto(void) {
*s << "<funcproto " << highlight[(int4)no_color] << '>';
return 0;
}
/// Inform the emitter that a function prototype is ending.
/// \param id is the id associated with the prototype (as returned by beginFuncProto)
void EmitXml::endFuncProto(int4 id) {
*s << "</funcproto>";
}
/// \brief Emit a variable token
///
/// An identifier string representing the variable is output, possibly with additional markup.
/// \param ptr is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param vn is the Varnode representing the variable within the syntax tree
/// \param op is a p-code operation related to the use of the variable (may be null)
void EmitXml::tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op)
{
*s << "<variable " << highlight[(int4)hl];
if (vn != (const Varnode *)0)
*s << " varref=\"0x" << hex << vn->getCreateIndex() << '\"';
if (op != (const PcodeOp *)0)
*s << " opref=\"0x" << hex << op->getTime() << '\"';
*s << '>';
xml_escape(*s,ptr);
*s << "</variable>";
}
/// \brief Emit an operation token
///
/// The string representing the operation as appropriate for the source language is emitted,
/// possibly with additional markup.
/// \param ptr is the character data for the emitted representation
/// \param hl indicates how the token should be highlighted
/// \param op is the PcodeOp object associated with the operation with the syntax tree
void EmitXml::tagOp(const char *ptr,syntax_highlight hl,
const PcodeOp *op)
{
*s << "<op " << highlight[(int4)hl];
if (op != (const PcodeOp *)0)
*s << " opref=\"0x" << hex << op->getTime() << "\">";
else
*s << '>';
xml_escape(*s,ptr);
*s << "</op>";
}
/// \brief Emit a function identifier
///
/// An identifier string representing the symbol name of the function is emitted, possible
/// with additional markup.
/// \param ptr is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param fd is the function
/// \param op is the CALL operation associated within the syntax tree or null for a declaration
void EmitXml::tagFuncName(const char *ptr,syntax_highlight hl,
const Funcdata *fd,const PcodeOp *op)
{
*s << "<funcname " << highlight[(int4)hl];
if (op != (const PcodeOp *)0)
*s << " opref=\"0x" << hex << op->getTime() << "\">";
else
*s << '>';
xml_escape(*s,ptr);
*s << "</funcname>";
}
/// \brief Emit a data-type identifier
///
/// A string representing the name of a data-type, as appropriate for the source language
/// is emitted, possibly with additional markup.
/// \param ptr is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type description object
void EmitXml::tagType(const char *ptr,syntax_highlight hl,const Datatype *ct) {
*s << "<type " << highlight[(int4)hl];
if (ct->getId() != 0) {
*s << " id=\"0x" << hex << ct->getId() << '\"';
}
*s << '>';
xml_escape(*s,ptr);
*s << "</type>";
}
/// \brief Emit an identifier for a field within a structured data-type
///
/// A string representing an individual component of a structured data-type is emitted,
/// possibly with additional markup.
/// \param ptr is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type associated with the field
/// \param o is the (byte) offset of the field within its structured data-type
/// \param op is the PcodeOp associated with the field (usually PTRSUB or SUBPIECE)
void EmitXml::tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 o,const PcodeOp *op) {
*s << "<field " << highlight[(int4)hl];
if (ct != (const Datatype *)0) {
*s << " name=\"";
xml_escape(*s,ct->getName().c_str());
if (ct->getId() != 0) {
*s << "\" id=\"0x" << hex << ct->getId();
}
*s << "\" off=\"" << dec << o << '\"';
if (op != (const PcodeOp *)0)
*s << " opref=\"0x" << hex << op->getTime() << "\"";
}
*s << '>';
xml_escape(*s,ptr);
*s << "</field>";
}
/// \brief Emit a comment string as part of the generated source code
///
/// Individual comments can be broken up and emitted using multiple calls to this method,
/// but ultimately the comment delimiters and the body of the comment are both emitted with
/// this method, which may provide addition markup.
/// \param ptr is the character data for the comment
/// \param hl indicates how the comment should be highlighted
/// \param spc is the address space of the address where the comment is attached
/// \param off is the offset of the address where the comment is attached
void EmitXml::tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << "<comment " << highlight[(int4)hl];
a_v(*s,"space",spc->getName());
a_v_u(*s,"off",off);
*s << '>';
xml_escape(*s,ptr);
*s << "</comment>";
}
/// \brief Emit a code label identifier
///
/// A string describing a control-flow destination, as appropriate for the source language
/// is output, possibly with additional markup.
/// \param ptr is the character data of the label
/// \param hl indicates how the label should be highlighted
/// \param spc is the address space of the code address being labeled
/// \param off is the offset of the code address being labeled
void EmitXml::tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << "<label " << highlight[(int4)hl];
a_v(*s,"space",spc->getName());
a_v_u(*s,"off",off);
*s << '>';
xml_escape(*s,ptr);
*s << "</label>";
}
/// \brief Emit other (more unusual) syntax as part of source code generation
///
/// This method is used to emit syntax not covered by the other methods, such as
/// spaces, semi-colons, braces, and other punctuation.
/// \param str is the character data of the syntax being emitted
/// \param hl indicates how the syntax should be highlighted
void EmitXml::print(const char *str,syntax_highlight hl)
{
*s << "<syntax " << highlight[(int4)hl] << '>';
xml_escape(*s,str);
*s << "</syntax>";
}
/// This method emits the parenthesis character itself and also starts a printing unit
/// of the source code being surrounded by the parentheses.
/// \param o is the open parenthesis character to emit
/// \param id is an id to associate with the parenthesis
/// \return an id associated with the parenthesis
int4 EmitXml::openParen(char o,int4 id)
{
*s << "<syntax " << highlight[(int4)no_color];
*s << " open=\"" << dec << id << "\">";
*s << o;
*s << "</syntax>";
parenlevel += 1;
return 0;
}
/// This method emits the parenthesis character itself and ends the printing unit that
/// was started by the matching open parenthesis.
/// \param c is the close parenthesis character to emit
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
void EmitXml::closeParen(char c,int4 id)
{
*s << "<syntax " << highlight[(int4)no_color];
*s << " close=\"" << dec << id << "\">";
*s << c;
*s << "</syntax>";
parenlevel -= 1;
}
/// \brief Emit a sequence of space characters as part of source code
///
/// \param num is the number of space characters to emit
/// \param bump is the number of characters to indent if the spaces force a line break
void EmitXml::spaces(int4 num,int4 bump)
void Emit::spaces(int4 num,int4 bump)
{
const char *tenspaces = " ";
static const string spacearray[] = { "", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " " };
if (num <= 10)
print(tenspaces+(10-num));
print(spacearray[num]);
else {
string spc;
for(int4 i=0;i<num;++i)
spc += ' ';
print(spc.c_str());
print(spc);
}
}
void EmitXml::resetDefaults(void)
EmitMarkup::~EmitMarkup(void)
{
resetDefaultsInternal();
if (encoder != (Encoder *)0)
delete encoder;
}
int4 EmitMarkup::beginDocument(void) {
encoder->openElement(ELEM_CLANG_DOCUMENT);
return 0;
}
void EmitMarkup::endDocument(int4 id) {
encoder->closeElement(ELEM_CLANG_DOCUMENT);
}
int4 EmitMarkup::beginFunction(const Funcdata *fd) {
encoder->openElement(ELEM_FUNCTION);
return 0;
}
void EmitMarkup::endFunction(int4 id) {
encoder->closeElement(ELEM_FUNCTION);
}
int4 EmitMarkup::beginBlock(const FlowBlock *bl) {
encoder->openElement(ELEM_BLOCK);
encoder->writeSignedInteger(ATTRIB_BLOCKREF, bl->getIndex());
return 0;
}
void EmitMarkup::endBlock(int4 id) {
encoder->closeElement(ELEM_BLOCK);
}
void EmitMarkup::tagLine(void) {
emitPending();
encoder->openElement(ELEM_BREAK);
encoder->writeSignedInteger(ATTRIB_INDENT, indentlevel);
encoder->closeElement(ELEM_BREAK);
}
void EmitMarkup::tagLine(int4 indent) {
emitPending();
encoder->openElement(ELEM_BREAK);
encoder->writeSignedInteger(ATTRIB_INDENT, indent);
encoder->closeElement(ELEM_BREAK);
}
int4 EmitMarkup::beginReturnType(const Varnode *vn) {
encoder->openElement(ELEM_RETURN_TYPE);
if (vn != (const Varnode *)0)
encoder->writeUnsignedInteger(ATTRIB_VARREF, vn->getCreateIndex());
return 0;
}
void EmitMarkup::endReturnType(int4 id) {
encoder->closeElement(ELEM_RETURN_TYPE);
}
int4 EmitMarkup::beginVarDecl(const Symbol *sym) {
encoder->openElement(ELEM_VARDECL);
encoder->writeUnsignedInteger(ATTRIB_SYMREF, sym->getId());
return 0;
}
void EmitMarkup::endVarDecl(int4 id) {
encoder->closeElement(ELEM_VARDECL);
}
int4 EmitMarkup::beginStatement(const PcodeOp *op) {
encoder->openElement(ELEM_STATEMENT);
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
return 0;
}
void EmitMarkup::endStatement(int4 id) {
encoder->closeElement(ELEM_STATEMENT);
}
int4 EmitMarkup::beginFuncProto(void) {
encoder->openElement(ELEM_FUNCPROTO);
return 0;
}
void EmitMarkup::endFuncProto(int4 id) {
encoder->closeElement(ELEM_FUNCPROTO);
}
void EmitMarkup::tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op)
{
encoder->openElement(ELEM_VARIABLE);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR, highlight[(int4)hl]);
if (vn != (const Varnode *)0)
encoder->writeUnsignedInteger(ATTRIB_VARREF, vn->getCreateIndex());
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_VARIABLE);
}
void EmitMarkup::tagOp(const string &name,syntax_highlight hl,const PcodeOp *op)
{
encoder->openElement(ELEM_OP);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_OP);
}
void EmitMarkup::tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op)
{
encoder->openElement(ELEM_FUNCNAME);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_FUNCNAME);
}
void EmitMarkup::tagType(const string &name,syntax_highlight hl,const Datatype *ct)
{
encoder->openElement(ELEM_TYPE);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
if (ct->getId() != 0) {
encoder->writeUnsignedInteger(ATTRIB_ID, ct->getId());
}
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_TYPE);
}
void EmitMarkup::tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 o,const PcodeOp *op)
{
encoder->openElement(ELEM_FIELD);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
if (ct != (const Datatype *)0) {
encoder->writeString(ATTRIB_NAME,ct->getName());
if (ct->getId() != 0) {
encoder->writeUnsignedInteger(ATTRIB_ID, ct->getId());
}
encoder->writeSignedInteger(ATTRIB_OFF, o);
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
}
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_FIELD);
}
void EmitMarkup::tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)
{
encoder->openElement(ELEM_COMMENT);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
encoder->writeSpace(ATTRIB_SPACE, spc);
encoder->writeUnsignedInteger(ATTRIB_OFF, off);
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_COMMENT);
}
void EmitMarkup::tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)
{
encoder->openElement(ELEM_LABEL);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
encoder->writeSpace(ATTRIB_SPACE,spc);
encoder->writeUnsignedInteger(ATTRIB_OFF, off);
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_LABEL);
}
void EmitMarkup::print(const string &data,syntax_highlight hl)
{
encoder->openElement(ELEM_SYNTAX);
if (hl != no_color)
encoder->writeString(ATTRIB_COLOR,highlight[(int4)hl]);
encoder->writeString(ATTRIB_CONTENT,data);
encoder->closeElement(ELEM_SYNTAX);
}
int4 EmitMarkup::openParen(const string &paren,int4 id)
{
encoder->openElement(ELEM_SYNTAX);
encoder->writeSignedInteger(ATTRIB_OPEN, id);
encoder->writeString(ATTRIB_CONTENT,paren);
encoder->closeElement(ELEM_SYNTAX);
parenlevel += 1;
return 0;
}
void EmitMarkup::closeParen(const string &paren,int4 id)
{
encoder->openElement(ELEM_SYNTAX);
encoder->writeSignedInteger(ATTRIB_CLOSE, id);
encoder->writeString(ATTRIB_CONTENT,paren);
encoder->closeElement(ELEM_SYNTAX);
parenlevel -= 1;
}
void EmitMarkup::setOutputStream(ostream *t)
{
if (encoder != (Encoder *)0)
delete encoder;
s = t;
encoder = new XmlEncode(*s);
}
int4 TokenSplit::countbase = 0;
@ -363,7 +296,7 @@ int4 TokenSplit::countbase = 0;
/// The API method matching the token type is called, feeding it content contained in
/// the object.
/// \param emit is the low-level emitter to output to
void TokenSplit::print(EmitXml *emit) const
void TokenSplit::print(Emit *emit) const
{
switch(tagtype) {
@ -410,34 +343,34 @@ void TokenSplit::print(EmitXml *emit) const
emit->endFuncProto(count);
break;
case vari_t: // tagVariable
emit->tagVariable(tok.c_str(),hl,ptr_second.vn,op);
emit->tagVariable(tok,hl,ptr_second.vn,op);
break;
case op_t: // tagOp
emit->tagOp(tok.c_str(),hl,op);
emit->tagOp(tok,hl,op);
break;
case fnam_t: // tagFuncName
emit->tagFuncName(tok.c_str(),hl,ptr_second.fd,op);
emit->tagFuncName(tok,hl,ptr_second.fd,op);
break;
case type_t: // tagType
emit->tagType(tok.c_str(),hl,ptr_second.ct);
emit->tagType(tok,hl,ptr_second.ct);
break;
case field_t: // tagField
emit->tagField(tok.c_str(),hl,ptr_second.ct,(int4)off,op);
emit->tagField(tok,hl,ptr_second.ct,(int4)off,op);
break;
case comm_t: // tagComment
emit->tagComment(tok.c_str(),hl,ptr_second.spc,off);
emit->tagComment(tok,hl,ptr_second.spc,off);
break;
case label_t: // tagLabel
emit->tagLabel(tok.c_str(),hl,ptr_second.spc,off);
emit->tagLabel(tok,hl,ptr_second.spc,off);
break;
case synt_t: // print
emit->print(tok.c_str(),hl);
emit->print(tok,hl);
break;
case opar_t: // openParen
emit->openParen(tok[0],count);
emit->openParen(tok,count);
break;
case cpar_t: // closeParen
emit->closeParen(tok[0],count);
emit->closeParen(tok,count);
break;
case oinv_t: // Invisible open
break;
@ -550,10 +483,10 @@ void TokenSplit::printDebug(ostream &s) const
#endif
EmitPrettyPrint::EmitPrettyPrint(void)
: EmitXml(), scanqueue( 3*100 ), tokqueue( 3*100 )
: Emit(), scanqueue( 3*100 ), tokqueue( 3*100 )
{
lowlevel = new EmitNoXml(); // Do not emit xml by default
lowlevel = new EmitNoMarkup(); // Do not emit xml by default
spaceremain = maxlinesize;
needbreak = false;
commentmode = false;
@ -614,7 +547,7 @@ void EmitPrettyPrint::overflow(void)
spaceremain = newspaceremain;
lowlevel->tagLine(maxlinesize-spaceremain);
if (commentmode &&(commentfill.size() != 0)) {
lowlevel->print(commentfill.c_str(),EmitXml::comment_color);
lowlevel->print(commentfill,EmitMarkup::comment_color);
spaceremain -= commentfill.size();
}
}
@ -699,7 +632,7 @@ void EmitPrettyPrint::print(const TokenSplit &tok)
}
lowlevel->tagLine(maxlinesize-spaceremain);
if (commentmode &&(commentfill.size() != 0)) {
lowlevel->print(commentfill.c_str(),EmitXml::comment_color);
lowlevel->print(commentfill,EmitMarkup::comment_color);
spaceremain -= commentfill.size();
}
}
@ -745,7 +678,7 @@ void EmitPrettyPrint::advanceleft(void)
/// This is the heart of the pretty printing algorithm. The new token is assigned
/// a size, the queue of open references and line breaks is updated. The amount
/// of space currently available and the size of printing groups are updated.
/// If the current line is going to overflow, a decision is mode where in the uncommented
/// If the current line is going to overflow, a decision is made where in the uncommented
/// tokens a line break needs to be inserted and what its indent level will be. If the
/// leftmost print group closes without needing a line break, all the content it contains
/// is \e committed and is sent to the low-level emitter.
@ -846,7 +779,7 @@ void EmitPrettyPrint::checkend(void)
{
if (!needbreak) {
TokenSplit &tok( tokqueue.push() );
tok.print("",EmitXml::no_color); // Add a blank string
tok.print(EMPTY_STRING,EmitMarkup::no_color); // Add a blank string
scan();
}
needbreak = true;
@ -860,7 +793,7 @@ void EmitPrettyPrint::checkbreak(void)
{
if (!needbreak) {
TokenSplit &tok( tokqueue.push() );
tok.print("",EmitXml::no_color); // Add a blank string
tok.print(EMPTY_STRING,EmitMarkup::no_color); // Add a blank string
scan();
}
needbreak = false;
@ -1021,95 +954,95 @@ void EmitPrettyPrint::endFuncProto(int4 id)
scan();
}
void EmitPrettyPrint::tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagVariable(ptr,hl,vn,op);
scan();
}
void EmitPrettyPrint::tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op)
void EmitPrettyPrint::tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagOp(ptr,hl,op);
tok.tagVariable(name,hl,vn,op);
scan();
}
void EmitPrettyPrint::tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op)
void EmitPrettyPrint::tagOp(const string &name,syntax_highlight hl,const PcodeOp *op)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagFuncName(ptr,hl,fd,op);
tok.tagOp(name,hl,op);
scan();
}
void EmitPrettyPrint::tagType(const char *ptr,syntax_highlight hl,const Datatype *ct)
void EmitPrettyPrint::tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagType(ptr,hl,ct);
tok.tagFuncName(name,hl,fd,op);
scan();
}
void EmitPrettyPrint::tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 o,const PcodeOp *op)
void EmitPrettyPrint::tagType(const string &name,syntax_highlight hl,const Datatype *ct)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagField(ptr,hl,ct,o,op);
tok.tagType(name,hl,ct);
scan();
}
void EmitPrettyPrint::tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagComment(ptr,hl,spc,off);
scan();
}
void EmitPrettyPrint::tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagLabel(ptr,hl,spc,off);
scan();
}
void EmitPrettyPrint::print(const char *str,syntax_highlight hl)
void EmitPrettyPrint::tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 o,const PcodeOp *op)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.print(str,hl);
tok.tagField(name,hl,ct,o,op);
scan();
}
int4 EmitPrettyPrint::openParen(char o,int4 id)
void EmitPrettyPrint::tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagComment(name,hl,spc,off);
scan();
}
void EmitPrettyPrint::tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagLabel(name,hl,spc,off);
scan();
}
void EmitPrettyPrint::print(const string &data,syntax_highlight hl)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.print(data,hl);
scan();
}
int4 EmitPrettyPrint::openParen(const string &paren,int4 id)
{
id = openGroup(); // Open paren automatically opens group
TokenSplit &tok( tokqueue.push() );
tok.openParen(o,id);
tok.openParen(paren,id);
scan();
needbreak = true;
return id;
}
void EmitPrettyPrint::closeParen(char c,int4 id)
void EmitPrettyPrint::closeParen(const string &paren,int4 id)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.closeParen(c,id);
tok.closeParen(paren,id);
scan();
closeGroup(id);
}
@ -1155,7 +1088,7 @@ void EmitPrettyPrint::stopComment(int4 id)
void EmitPrettyPrint::clear(void)
{
EmitXml::clear();
Emit::clear();
lowlevel->clear();
indentstack.clear();
scanqueue.clear();
@ -1212,18 +1145,18 @@ void EmitPrettyPrint::flush(void)
lowlevel->flush();
}
/// This method toggles the low-level emitter between EmitXml and EmitNoXml depending
/// on whether XML markup is desired.
/// \param val is \b true if XML markup is desired
void EmitPrettyPrint::setXML(bool val)
/// This method toggles the low-level emitter between EmitMarkup and EmitNoMarkup depending
/// on whether markup is desired.
/// \param val is \b true if markup is desired
void EmitPrettyPrint::setMarkup(bool val)
{
ostream *t = lowlevel->getOutputStream();
delete lowlevel;
if (val)
lowlevel = new EmitXml;
lowlevel = new EmitMarkup;
else
lowlevel = new EmitNoXml;
lowlevel = new EmitNoMarkup;
lowlevel->setOutputStream(t);
}

View file

@ -28,11 +28,30 @@ class Funcdata;
class Symbol;
class PendPrint;
/// \brief Base class (and interface) for pretty printing and XML markup of tokens
extern AttributeId ATTRIB_BLOCKREF; ///< Marshaling attribute "blockref"
extern AttributeId ATTRIB_CLOSE; ///< Marshaling attribute "close"
extern AttributeId ATTRIB_COLOR; ///< Marshaling attribute "color"
extern AttributeId ATTRIB_INDENT; ///< Marshaling attribute "indent"
extern AttributeId ATTRIB_OFF; ///< Marshaling attribute "off"
extern AttributeId ATTRIB_OPEN; ///< Marshaling attribute "open"
extern AttributeId ATTRIB_OPREF; ///< Marshaling attribute "opref"
extern AttributeId ATTRIB_VARREF; ///< Marshaling attribute "varref"
extern ElementId ELEM_BREAK; ///< Marshaling element \<break>
extern ElementId ELEM_CLANG_DOCUMENT; ///< Marshaling element \<clang_document>
extern ElementId ELEM_FUNCNAME; ///< Marshaling element \<funcname>
extern ElementId ELEM_FUNCPROTO; ///< Marshaling element \<funcproto>
extern ElementId ELEM_LABEL; ///< Marshaling element \<label>
extern ElementId ELEM_RETURN_TYPE; ///< Marshaling element \<return_type>
extern ElementId ELEM_STATEMENT; ///< Marshaling element \<statement>
extern ElementId ELEM_SYNTAX; ///< Marshaling element \<syntax>
extern ElementId ELEM_VARDECL; ///< Marshaling element \<vardecl>
extern ElementId ELEM_VARIABLE; ///< Marshaling element \<variable>
/// \brief Interface for emitting the Decompiler's formal output: source code
///
/// There are two basic functions being implemented through this interface:
///
/// \b XML \b markup: allows recording of the natural grouping of the high-level tokens
/// \b Markup: allows recording of the natural grouping of the high-level tokens
/// and directly links the nodes of the abstract syntax tree to the emitted tokens.
///
/// \b Pretty \b printing: Line breaks and additional white space characters are
@ -70,23 +89,19 @@ class PendPrint;
/// - tagLine forces a line break
/// - tagLine(indent) forces a line break with an indent override
///
/// This base class does not actually do any pretty printing it only does the XML
/// markup. For an implementation that actually does pretty printing, see EmitPrettyPrint.
/// This class can be used as the low-level back-end to EmitPrettyPrint to provide a solution
/// that does both pretty printing and XML markup.
class EmitXml {
static const char *highlight[]; ///< Map from syntax_highlight enumeration to color attribute string
/// For an implementation that actually does pretty printing, see EmitPrettyPrint.
class Emit {
public:
static const string EMPTY_STRING; ///< An empty string
protected:
ostream *s; ///< Stream being emitted to
int4 indentlevel; ///< Current indent level (in fixed width characters)
int4 parenlevel; ///< Current depth of parentheses
int4 indentincrement; ///< Change in indentlevel per level of nesting
PendPrint *pendPrint; ///< Pending print callback
void resetDefaultsInternal(void) { indentincrement = 2; } ///< Set options to default values for EmitXml
void resetDefaultsInternal(void) { indentincrement = 2; } ///< Set options to default values for EmitMarkup
void emitPending(void); ///< Emit any pending print commands
public:
EmitXml(void) { s = (ostream *)0; indentlevel=0; parenlevel=0; pendPrint=(PendPrint *)0; resetDefaultsInternal(); } ///< Constructor
Emit(void) { indentlevel=0; parenlevel=0; pendPrint=(PendPrint *)0; resetDefaultsInternal(); } ///< Constructor
/// \brief Possible types of syntax highlighting
enum syntax_highlight {
keyword_color = 0, ///< Keyword in the high-level language
@ -99,34 +114,202 @@ public:
global_color = 7, ///< Global variable identifiers
no_color = 8 ///< Un-highlighted
};
virtual ~EmitXml(void) {} ///< Destructor
virtual int4 beginDocument(void); ///< Begin a whole document of output
virtual void endDocument(int4 id); ///< End a whole document of output
virtual int4 beginFunction(const Funcdata *fd); ///< Begin a whole declaration and body of a function
virtual void endFunction(int4 id); ///< End a whole declaration and body of a function
virtual int4 beginBlock(const FlowBlock *bl); ///< Begin a control-flow element
virtual void endBlock(int4 id); ///< End a control-flow element
virtual void tagLine(void); ///< Force a line break
virtual void tagLine(int4 indent); ///< Force a line break and indent level
virtual int4 beginReturnType(const Varnode *vn); ///< Begin a return type declaration
virtual void endReturnType(int4 id); ///< End a return type declaration
virtual int4 beginVarDecl(const Symbol *sym); ///< Begin a variable declaration
virtual void endVarDecl(int4 id); ///< End a variable declaration
virtual int4 beginStatement(const PcodeOp *op); ///< Begin a source code statement
virtual void endStatement(int4 id); ///< End a source code statement
virtual int4 beginFuncProto(void); ///< Begin a function prototype declaration
virtual void endFuncProto(int4 id); ///< End a function prototype declaration
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const char *str,syntax_highlight hl=no_color);
virtual int4 openParen(char o,int4 id=0); ///< Emit an open parenthesis
virtual void closeParen(char c,int4 id); ///< Emit a close parenthesis
virtual ~Emit(void) {} ///< Destructor
/// \brief Begin a whole document of output
///
/// Inform the emitter that generation of the source code document has begun
/// \return an id associated with the document
virtual int4 beginDocument(void)=0;
/// \brief End a whole document of output
///
/// Inform the emitter that generation of the source code document is finished
/// \param id is the id associated with the document (as returned by beginDocument)
virtual void endDocument(int4 id)=0;
/// \brief Begin a whole declaration and body of a function
///
/// Inform the emitter that generation of a function body has begun
/// \return an id associated with the function body
virtual int4 beginFunction(const Funcdata *fd)=0;
/// \brief End a whole declaration and body of a function
///
/// Inform the emitter that generation of a function body has ended
/// \param id is the id associated with the function body (as returned by beginFunction)
virtual void endFunction(int4 id)=0;
/// \brief Begin a control-flow element
///
/// Inform the emitter that a new control-flow section is starting. This is a source code unit
/// usually surrounded with curly braces '{' and '}'.
/// \param bl is the block structure object associated with the section
/// \return an id associated with the section
virtual int4 beginBlock(const FlowBlock *bl)=0;
/// \brief End a control-flow element
///
/// Inform the emitter that a control-flow section is ending.
/// \param id is the id associated with the section (as returned by beginBlock)
virtual void endBlock(int4 id)=0;
/// \brief Force a line break
///
/// Tell the emitter that a new line is desired at the current indent level
virtual void tagLine(void)=0;
/// \brief Force a line break and indent level
///
/// Tell the emitter that a new line is desired at a specific indent level. The indent level
/// is overridden only for the line, then it returns to its previous value.
/// \param indent is the desired indent level for the new line
virtual void tagLine(int4 indent)=0;
/// \brief Begin a return type declaration
///
/// Inform the emitter that generation of a function's return type is starting.
/// \param vn (if non-null) is the storage location for the return value
/// \return an id associated with the return type
virtual int4 beginReturnType(const Varnode *vn)=0;
/// \brief End a return type declaration
///
/// Inform the emitter that generation of a function's return type is ending.
/// \param id is the id associated with the return type (as returned by beginReturnType)
virtual void endReturnType(int4 id)=0;
/// \brief Begin a variable declaration
///
/// Inform the emitter that a variable declaration has started.
/// \param sym is the symbol being declared
/// \return an id associated with the declaration
virtual int4 beginVarDecl(const Symbol *sym)=0;
/// \brief End a variable declaration
///
/// Inform the emitter that a variable declaration has ended.
/// \param id is the id associated with the declaration (as returned by beginVarDecl)
virtual void endVarDecl(int4 id)=0;
/// \brief Begin a source code statement
///
/// Inform the emitter that a source code statement is beginning.
/// \param op is the root p-code operation of the statement
/// \return an id associated with the statement
virtual int4 beginStatement(const PcodeOp *op)=0;
/// \brief End a source code statement
///
/// Inform the emitter that a source code statement is ending.
/// \param id is the id associated with the statement (as returned by beginStatement)
virtual void endStatement(int4 id)=0;
/// \brief Begin a function prototype declaration
///
/// Inform the emitter that a function prototype is starting.
/// \return an id associated with the prototype
virtual int4 beginFuncProto(void)=0;
/// \brief End a function prototype declaration
///
/// Inform the emitter that a function prototype is ending.
/// \param id is the id associated with the prototype (as returned by beginFuncProto)
virtual void endFuncProto(int4 id)=0;
/// \brief Emit a variable token
///
/// An identifier string representing the variable is output, possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param vn is the Varnode representing the variable within the syntax tree
/// \param op is a p-code operation related to the use of the variable (may be null)
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op)=0;
/// \brief Emit an operation token
///
/// The string representing the operation as appropriate for the source language is emitted,
/// possibly with additional markup.
/// \param name is the character data for the emitted representation
/// \param hl indicates how the token should be highlighted
/// \param op is the PcodeOp object associated with the operation with the syntax tree
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op)=0;
/// \brief Emit a function identifier
///
/// An identifier string representing the symbol name of the function is emitted, possible
/// with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param fd is the function
/// \param op is the CALL operation associated within the syntax tree or null for a declaration
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op)=0;
/// \brief Emit a data-type identifier
///
/// A string representing the name of a data-type, as appropriate for the source language
/// is emitted, possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type description object
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct)=0;
/// \brief Emit an identifier for a field within a structured data-type
///
/// A string representing an individual component of a structured data-type is emitted,
/// possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type associated with the field
/// \param off is the (byte) offset of the field within its structured data-type
/// \param op is the PcodeOp associated with the field (usually PTRSUB or SUBPIECE)
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op)=0;
/// \brief Emit a comment string as part of the generated source code
///
/// Individual comments can be broken up and emitted using multiple calls to this method,
/// but ultimately the comment delimiters and the body of the comment are both emitted with
/// this method, which may provide addition markup.
/// \param name is the character data for the comment
/// \param hl indicates how the comment should be highlighted
/// \param spc is the address space of the address where the comment is attached
/// \param off is the offset of the address where the comment is attached
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0;
/// \brief Emit a code label identifier
///
/// A string describing a control-flow destination, as appropriate for the source language
/// is output, possibly with additional markup.
/// \param name is the character data of the label
/// \param hl indicates how the label should be highlighted
/// \param spc is the address space of the code address being labeled
/// \param off is the offset of the code address being labeled
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0;
/// \brief Emit other (more unusual) syntax as part of source code generation
///
/// This method is used to emit syntax not covered by the other methods, such as
/// spaces, semi-colons, braces, and other punctuation.
/// \param data is the character data of the syntax being emitted
/// \param hl indicates how the syntax should be highlighted
virtual void print(const string &data,syntax_highlight hl=no_color)=0;
/// \brief Emit an open parenthesis
///
/// This method emits the parenthesis character itself and also starts a printing unit
/// of the source code being surrounded by the parentheses.
/// \param paren is the open parenthesis character to emit
/// \param id is an id to associate with the parenthesis
/// \return an id associated with the parenthesis
virtual int4 openParen(const string &paren,int4 id=0)=0;
/// \brief Emit a close parenthesis
///
/// This method emits the parenthesis character itself and ends the printing unit that
/// was started by the matching open parenthesis.
/// \param paren is the close parenthesis character to emit
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
virtual void closeParen(const string &paren,int4 id)=0;
/// \brief Start a group of things that are printed together
///
@ -140,8 +323,8 @@ public:
/// \param id is the id associated with the group (as returned by openGroup)
virtual void closeGroup(int4 id) {}
virtual void clear(void) { parenlevel = 0; indentlevel=0; pendPrint=(PendPrint *)0; } ///< Reset the emitter to its initial state
virtual void setOutputStream(ostream *t) { s = t; } ///< Set the output stream for the emitter
virtual ostream *getOutputStream(void) const { return s; } ///< Get the current output stream
virtual void setOutputStream(ostream *t)=0; ///< Set the output stream for the emitter
virtual ostream *getOutputStream(void) const=0; ///< Get the current output stream
virtual void spaces(int4 num,int4 bump=0);
/// \brief Start a new indent level
@ -198,10 +381,10 @@ public:
/// \brief Determine if \b this is an XML markup emitter
///
/// \return \b true if \b this produces an XML markup of its emitted source code
virtual bool emitsXml(void) const { return true; }
virtual bool emitsMarkup(void) const=0;
/// \brief (Re)set the default emitting options
virtual void resetDefaults(void);
virtual void resetDefaults(void) { resetDefaultsInternal(); }
/// \brief Get the current parentheses depth
///
@ -235,22 +418,81 @@ public:
/// \param pend is the given print callback to check
/// \return \b true if the specific print callback is pending
bool hasPendingPrint(PendPrint *pend) const { return (pendPrint == pend); }
};
/// \brief Emitter that associates markup with individual tokens
///
/// Variable and operation tokens are associated with their corresponding Varnode or PcodeOp object in
/// the data-flow graph of the decompiled function.
///
/// Explicit descriptions of various token groups is emitted, including:
/// - Function prototypes
/// - Variable declarations
/// - Control-flow blocks
/// - Statements
///
/// Tokens are emitted with syntax highlighting information.
///
/// This class can be used as the low-level back-end to EmitPrettyPrint to provide a solution
/// that does both pretty printing and markup.
class EmitMarkup : public Emit {
static const string highlight[]; ///< Map from syntax_highlight enumeration to color attribute string
protected:
ostream *s; ///< Stream being emitted to
Encoder *encoder; ///< How markup is encoded to the output stream
public:
EmitMarkup(void) : Emit() { s = (ostream *)0; encoder = (Encoder *)0; } ///< Constructor
virtual ~EmitMarkup(void);
virtual int4 beginDocument(void);
virtual void endDocument(int4 id);
virtual int4 beginFunction(const Funcdata *fd);
virtual void endFunction(int4 id);
virtual int4 beginBlock(const FlowBlock *bl);
virtual void endBlock(int4 id);
virtual void tagLine(void);
virtual void tagLine(int4 indent);
virtual int4 beginReturnType(const Varnode *vn);
virtual void endReturnType(int4 id);
virtual int4 beginVarDecl(const Symbol *sym);
virtual void endVarDecl(int4 id);
virtual int4 beginStatement(const PcodeOp *op);
virtual void endStatement(int4 id);
virtual int4 beginFuncProto(void);
virtual void endFuncProto(int4 id);
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id);
virtual void setOutputStream(ostream *t);
virtual ostream *getOutputStream(void) const { return s; }
virtual bool emitsMarkup(void) const { return true; }
};
/// \brief A trivial emitter that outputs syntax straight to the stream
///
/// This emitter does neither pretty printing nor XML markup. It dumps any tokens
/// This emitter does neither pretty printing nor markup. It dumps any tokens
/// straight to the final output stream. It can be used as the low-level back-end
/// for EmitPrettyPrint.
class EmitNoXml : public EmitXml {
class EmitNoMarkup : public Emit {
ostream *s; ///< The stream to output tokens to
public:
EmitNoXml(void) : EmitXml() {} ///< Constructor
EmitNoMarkup(void) : Emit() { s = (ostream *)0; } ///< Constructor
virtual int4 beginDocument(void) { return 0; }
virtual void endDocument(int4 id) {}
virtual int4 beginFunction(const Funcdata *fd) { return 0; }
virtual void endFunction(int4 id) {}
virtual int4 beginBlock(const FlowBlock *bl) { return 0; }
virtual void endBlock(int4 id) {}
virtual void tagLine(void) {
*s << endl; for(int4 i=indentlevel;i>0;--i) *s << ' '; }
virtual void tagLine(int4 indent) {
*s << endl; for(int4 i=indent;i>0;--i) *s << ' '; }
virtual int4 beginReturnType(const Varnode *vn) { return 0; }
@ -261,30 +503,29 @@ public:
virtual void endStatement(int4 id) {}
virtual int4 beginFuncProto(void) { return 0; }
virtual void endFuncProto(int4 id) {}
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op) {
*s << ptr; }
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op) {
*s << ptr; }
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
*s << ptr; }
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct) {
*s << ptr; }
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
*s << ptr; }
virtual void tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << ptr; }
virtual void tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << ptr; }
virtual void print(const char *str,syntax_highlight hl=no_color) {
*s << str; }
virtual int4 openParen(char o,int4 id=0) {
*s << o; parenlevel += 1; return id; }
virtual void closeParen(char c,int4 id) {
*s << c; parenlevel -= 1; }
virtual bool emitsXml(void) const { return false; }
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op) {
*s << name; }
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op) {
*s << name; }
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
*s << name; }
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct) {
*s << name; }
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
*s << name; }
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*s << name; }
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*s << name; }
virtual void print(const string &data,syntax_highlight hl=no_color) {
*s << data; }
virtual int4 openParen(const string &paren,int4 id=0) {
*s << paren; parenlevel += 1; return id; }
virtual void closeParen(const string &paren,int4 id) {
*s << paren; parenlevel -= 1; }
virtual void setOutputStream(ostream *t) { s = t; }
virtual ostream *getOutputStream(void) const { return s; }
virtual bool emitsMarkup(void) const { return false; }
};
/// \brief A token/command object in the pretty printing stream
@ -299,7 +540,7 @@ public:
/// the token is one of the begin/end delimiters or is actual content.
/// Instances also have a \e tag_type that indicate the specific function of the
/// token within the stream, which mirror the begin/end/open/close/tag methods
/// on the emitter classes (EmitXml).
/// on the emitter classes (EmitMarkup).
class TokenSplit {
public:
/// \brief An enumeration denoting the general class of a token
@ -351,7 +592,7 @@ private:
tag_type tagtype; ///< Type of token
printclass delimtype; ///< The general class of the token
string tok; ///< Characters of token (if any)
EmitXml::syntax_highlight hl; ///< Highlighting for token
EmitMarkup::syntax_highlight hl; ///< Highlighting for token
// Additional markup elements for token
const PcodeOp *op; ///< Pcode-op associated with \b this token
union {
@ -461,98 +702,95 @@ public:
/// \brief Create a variable identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param v is the Varnode representing the variable within the syntax tree
/// \param o is a p-code operation related to the use of the variable (may be null)
void tagVariable(const char *ptr,EmitXml::syntax_highlight h,
const Varnode *v,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagVariable(const string &name,EmitMarkup::syntax_highlight h,const Varnode *v,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=vari_t; delimtype=tokenstring; hl=h; ptr_second.vn=v; op=o; }
/// \brief Create an operator token
///
/// \param ptr is the character data for the emitted representation
/// \param name is the character data for the emitted representation
/// \param h indicates how the token should be highlighted
/// \param o is the PcodeOp object associated with the operation with the syntax tree
void tagOp(const char *ptr,EmitXml::syntax_highlight h,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagOp(const string &name,EmitMarkup::syntax_highlight h,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=op_t; delimtype=tokenstring; hl=h; op=o; }
/// \brief Create a function identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param f is the function
/// \param o is the CALL operation associated within the syntax tree or null for a declaration
void tagFuncName(const char *ptr,EmitXml::syntax_highlight h,const Funcdata *f,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagFuncName(const string &name,EmitMarkup::syntax_highlight h,const Funcdata *f,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=fnam_t; delimtype=tokenstring; hl=h; ptr_second.fd=f; op=o; }
/// \brief Create a data-type identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param ct is the data-type description object
void tagType(const char *ptr,EmitXml::syntax_highlight h,const Datatype *ct) {
tok = ptr; size = tok.size();
void tagType(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct) {
tok = name; size = tok.size();
tagtype=type_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; }
/// \brief Create an identifier for a field within a structured data-type
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param ct is the data-type associated with the field
/// \param o is the (byte) offset of the field within its structured data-type
/// \param inOp is the PcodeOp associated with the field (usually PTRSUB or SUBPIECE)
void tagField(const char *ptr,EmitXml::syntax_highlight h,const Datatype *ct,int4 o,const PcodeOp *inOp) {
tok = ptr; size = tok.size();
void tagField(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct,int4 o,const PcodeOp *inOp) {
tok = name; size = tok.size();
tagtype=field_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; off=(uintb)o; op=inOp; }
/// \brief Create a comment string in the generated source code
///
/// \param ptr is the character data for the comment
/// \param name is the character data for the comment
/// \param h indicates how the comment should be highlighted
/// \param s is the address space of the address where the comment is attached
/// \param o is the offset of the address where the comment is attached
void tagComment(const char *ptr,EmitXml::syntax_highlight h,
const AddrSpace *s,uintb o) {
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
void tagComment(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
tagtype=comm_t; delimtype=tokenstring; hl=h; }
/// \brief Create a code label identifier token
///
/// \param ptr is the character data of the label
/// \param name is the character data of the label
/// \param h indicates how the label should be highlighted
/// \param s is the address space of the code address being labeled
/// \param o is the offset of the code address being labeled
void tagLabel(const char *ptr,EmitXml::syntax_highlight h,
const AddrSpace *s,uintb o) {
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
void tagLabel(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
tagtype=label_t; delimtype=tokenstring; hl=h; }
/// \brief Create a token for other (more unusual) syntax in source code
///
/// \param str is the character data of the syntax being emitted
/// \param data is the character data of the syntax being emitted
/// \param h indicates how the syntax should be highlighted
void print(const char *str,EmitXml::syntax_highlight h) {
tok = str; size=tok.size();
void print(const string &data,EmitMarkup::syntax_highlight h) {
tok = data; size=tok.size();
tagtype=synt_t; delimtype=tokenstring; hl=h; }
/// \brief Create an open parenthesis
///
/// \param o is the open parenthesis character to emit
/// \param paren is the open parenthesis character to emit
/// \param id is an id to associate with the parenthesis
void openParen(char o,int4 id) {
tok = o; size = 1;
void openParen(const string &paren,int4 id) {
tok = paren; size = 1;
tagtype=opar_t; delimtype=tokenstring; count=id; }
/// \brief Create a close parenthesis
///
/// \param c is the close parenthesis character to emit
/// \param paren is the close parenthesis character to emit
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
void closeParen(char c,int4 id) {
tok = c; size = 1;
void closeParen(const string &paren,int4 id) {
tok = paren; size = 1;
tagtype=cpar_t; delimtype=tokenstring; count=id; }
/// \brief Create a "start a printing group" command
@ -608,7 +846,7 @@ public:
void tagLine(int4 indent) {
tagtype=line_t; delimtype=tokenbreak; numspaces=999999; indentbump=indent; }
void print(EmitXml *emit) const; ///< Send \b this token to emitter
void print(Emit *emit) const; ///< Send \b this token to emitter
int4 getIndentBump(void) const { return indentbump; } ///< Get the extra indent after a line break
int4 getNumSpaces(void) const { return numspaces; } ///< Get the number of characters of whitespace
int4 getSize(void) const { return size; } ///< Get the number of content characters
@ -724,12 +962,12 @@ void circularqueue<_type>::expand(int4 amount)
/// about formatting issues.
///
/// This emitter encapsulates a lower-level emitter that does the final emitting to
/// stream and may add XML markup.
class EmitPrettyPrint : public EmitXml {
/// stream and may add markup.
class EmitPrettyPrint : public Emit {
#ifdef PRETTY_DEBUG
vector<int4> checkid;
#endif
EmitXml *lowlevel; ///< The low-level emitter
Emit *lowlevel; ///< The low-level emitter
vector<int4> indentstack; ///< Space available for currently active nesting levels
int4 spaceremain; ///< Space remaining in current line
int4 maxlinesize; ///< Maximum number of characters allowed in a line
@ -769,19 +1007,16 @@ public:
virtual void endStatement(int4 id);
virtual int4 beginFuncProto(void);
virtual void endFuncProto(int4 id);
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off);
virtual void tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off);
virtual void print(const char *str,syntax_highlight hl=no_color);
virtual int4 openParen(char o,int4 id=0);
virtual void closeParen(char c,int4 id);
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id);
virtual int4 openGroup(void);
virtual void closeGroup(int4 id);
virtual void clear(void);
@ -796,9 +1031,9 @@ public:
virtual void setMaxLineSize(int4 val);
virtual int4 getMaxLineSize(void) const { return maxlinesize; }
virtual void setCommentFill(const string &fill) { commentfill = fill; }
virtual bool emitsXml(void) const { return lowlevel->emitsXml(); }
virtual bool emitsMarkup(void) const { return lowlevel->emitsMarkup(); }
virtual void resetDefaults(void);
void setXML(bool val); ///< Toggle whether the low-level emitter emits XML markup or not
void setMarkup(bool val); ///< Toggle whether the low-level emitter emits markup or not
};
/// \brief Helper class for sending cancelable print commands to an ExitXml
@ -810,10 +1045,10 @@ public:
class PendPrint {
public:
virtual ~PendPrint(void) {} ///< Destructor
virtual void callback(EmitXml *emit)=0; ///< Callback that executes the actual print commands
virtual void callback(Emit *emit)=0; ///< Callback that executes the actual print commands
};
inline void EmitXml::emitPending(void)
inline void Emit::emitPending(void)
{
if (pendPrint != (PendPrint *)0) {

File diff suppressed because it is too large Load diff

View file

@ -47,7 +47,7 @@ struct PartialSymbolEntry {
const TypeField *field; ///< The component object describing the field
const Datatype *parent; ///< The parent data-type owning the field
string fieldname; ///< The name of the field
EmitXml::syntax_highlight hilite; ///< Highlight information for the field token
EmitMarkup::syntax_highlight hilite; ///< Highlight information for the field token
};
/// \brief The c-language token emitter
@ -113,7 +113,33 @@ protected:
static OpToken ptr_expr; ///< Pointer adornment for a type declaration
static OpToken array_expr; ///< Array adornment for a type declaration
static OpToken enum_cat; ///< The \e concatenation operator for enumerated values
public:
static const string EMPTY_STRING; ///< An empty token
static const string OPEN_CURLY; ///< "{" token
static const string CLOSE_CURLY; ///< "}" token
static const string SEMICOLON; ///< ";" token
static const string COLON; ///< ":" token
static const string EQUALSIGN; ///< "=" token
static const string COMMA; ///< "," token
static const string DOTDOTDOT; ///< "..." token
static const string KEYWORD_VOID; ///< "void" keyword
static const string KEYWORD_TRUE; ///< "true" keyword
static const string KEYWORD_FALSE; ///< "false" keyword
static const string KEYWORD_IF; ///< "if" keyword
static const string KEYWORD_ELSE; ///< "else" keyword
static const string KEYWORD_DO; ///< "do" keyword
static const string KEYWORD_WHILE; ///< "while" keyword
static const string KEYWORD_FOR; ///< "for" keyword
static const string KEYWORD_GOTO; ///< "goto" keyword
static const string KEYWORD_BREAK; ///< "break" keyword
static const string KEYWORD_CONTINUE; ///< "continue" keyword
static const string KEYWORD_CASE; ///< "case" keyword
static const string KEYWORD_SWITCH; ///< "switch" keyword
static const string KEYWORD_DEFAULT; ///< "default" keyword
static const string KEYWORD_RETURN; ///< "return" keyword
static const string KEYWORD_NEW; ///< "new" keyword
static const string typePointerRelToken; ///< The token to print indicating PTRSUB relative to a TypePointerRel
protected:
bool option_NULL; ///< Set to \b true if we should emit NULL keyword
bool option_inplace_ops; ///< Set to \b true if we should use '+=' '&=' etc.
bool option_convention; ///< Set to \b true if we should print calling convention
@ -314,7 +340,7 @@ class PendingBrace : public PendPrint {
public:
PendingBrace(void) { indentId = -1; } ///< Constructor
int4 getIndentId(void) const { return indentId; } ///< If commands have been issued, returns the new indent level id.
virtual void callback(EmitXml *emit);
virtual void callback(Emit *emit);
};
/// \brief Push a token indicating a PTRSUB (a -> operator) is acting at an offset from the original pointer
@ -326,7 +352,7 @@ inline void PrintC::pushTypePointerRel(const PcodeOp *op)
{
pushOp(&function_call,op);
pushAtom(Atom(typePointerRelToken,optoken,EmitXml::funcname_color,op));
pushAtom(Atom(typePointerRelToken,optoken,EmitMarkup::funcname_color,op));
}
#endif

View file

@ -16,7 +16,7 @@
#include "printjava.hh"
#include "funcdata.hh"
OpToken PrintJava::instanceof = { "instanceof", 2, 60, true, OpToken::binary, 1, 0, (OpToken *)0 };
OpToken PrintJava::instanceof = { "instanceof", "", 2, 60, true, OpToken::binary, 1, 0, (OpToken *)0 };
// Constructing this registers the capability
PrintJavaCapability PrintJavaCapability::printJavaCapability;
@ -102,13 +102,13 @@ void PrintJava::pushTypeStart(const Datatype *ct,bool noident)
if (ct->getName().size()==0) { // Check for anonymous type
// We could support a struct or enum declaration here
string nm = genericTypeName(ct);
pushAtom(Atom(nm,typetoken,EmitXml::type_color,ct));
pushAtom(Atom(nm,typetoken,EmitMarkup::type_color,ct));
}
else {
pushAtom(Atom(ct->getName(),typetoken,EmitXml::type_color,ct));
pushAtom(Atom(ct->getName(),typetoken,EmitMarkup::type_color,ct));
}
for(int4 i=0;i<arrayCount;++i)
pushAtom(Atom("",blanktoken,EmitXml::no_color)); // Fill in the blank array index
pushAtom(Atom(EMPTY_STRING,blanktoken,EmitMarkup::no_color)); // Fill in the blank array index
}
void PrintJava::pushTypeEnd(const Datatype *ct)
@ -119,8 +119,8 @@ void PrintJava::pushTypeEnd(const Datatype *ct)
void PrintJava::adjustTypeOperators(void)
{
scope.print = ".";
shift_right.print = ">>>";
scope.print1 = ".";
shift_right.print1 = ">>>";
TypeOp::selectJavaOperators(glb->inst,true);
}
@ -285,7 +285,7 @@ void PrintJava::opCallind(const PcodeOp *op)
}
else { // A void function
pushVn(op->getIn(0),op,mods);
pushAtom(Atom("",blanktoken,EmitXml::no_color));
pushAtom(Atom(EMPTY_STRING,blanktoken,EmitMarkup::no_color));
}
}
@ -299,7 +299,7 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
refs.push_back(op->getIn(i)->getOffset());
const CPoolRecord *rec = glb->cpool->getRecord(refs);
if (rec == (const CPoolRecord *)0) {
pushAtom(Atom("UNKNOWNREF",syntax,EmitXml::const_color,op,outvn));
pushAtom(Atom("UNKNOWNREF",syntax,EmitMarkup::const_color,op,outvn));
}
else {
switch(rec->getTag()) {
@ -316,11 +316,11 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
else {
str << "...\"";
}
pushAtom(Atom(str.str(),vartoken,EmitXml::const_color,op,outvn));
pushAtom(Atom(str.str(),vartoken,EmitMarkup::const_color,op,outvn));
break;
}
case CPoolRecord::class_reference:
pushAtom(Atom(rec->getToken(),vartoken,EmitXml::type_color,op,outvn));
pushAtom(Atom(rec->getToken(),vartoken,EmitMarkup::type_color,op,outvn));
break;
case CPoolRecord::instance_of:
{
@ -330,7 +330,7 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
}
pushOp(&instanceof,op);
pushVn(vn0,op,mods);
pushAtom(Atom(dt->getName(),syntax,EmitXml::type_color,op,outvn));
pushAtom(Atom(dt->getName(),syntax,EmitMarkup::type_color,op,outvn));
break;
}
case CPoolRecord::primitive: // Should be eliminated
@ -341,11 +341,11 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
default:
{
Datatype *ct = rec->getType();
EmitXml::syntax_highlight color = EmitXml::var_color;
EmitMarkup::syntax_highlight color = EmitMarkup::var_color;
if (ct->getMetatype() == TYPE_PTR) {
ct = ((TypePointer *)ct)->getPtrTo();
if (ct->getMetatype() == TYPE_CODE)
color = EmitXml::funcname_color;
color = EmitMarkup::funcname_color;
}
if (vn0->isConstant()) { // If this is NOT relative to an object reference
pushAtom(Atom(rec->getToken(),vartoken,color,op,outvn));

View file

@ -17,6 +17,9 @@
#include "printlanguage.hh"
#include "funcdata.hh"
const string PrintLanguage::OPEN_PAREN = "(";
const string PrintLanguage::CLOSE_PAREN = ")";
vector<PrintLanguageCapability *> PrintLanguageCapability::thelist;
/// This retrieves the capability with its \b isdefault field set or
@ -138,7 +141,7 @@ void PrintLanguage::pushOp(const OpToken *tok,const PcodeOp *op)
emitOp(revpol.back());
paren = parentheses(tok);
if (paren)
id = emit->openParen('(');
id = emit->openParen(OPEN_PAREN);
else
id = emit->openGroup();
}
@ -170,7 +173,7 @@ void PrintLanguage::pushAtom(const Atom &atom)
if (revpol.back().visited == revpol.back().tok->stage) {
emitOp(revpol.back());
if (revpol.back().paren)
emit->closeParen(')',revpol.back().id);
emit->closeParen(CLOSE_PAREN,revpol.back().id);
else
emit->closeGroup(revpol.back().id);
revpol.pop_back();
@ -327,32 +330,32 @@ void PrintLanguage::emitOp(const ReversePolish &entry)
case OpToken::binary:
if (entry.visited!=1) return;
emit->spaces(entry.tok->spacing,entry.tok->bump); // Spacing around operator
emit->tagOp(entry.tok->print,EmitXml::no_color,entry.op);
emit->tagOp(entry.tok->print1,EmitMarkup::no_color,entry.op);
emit->spaces(entry.tok->spacing,entry.tok->bump);
break;
case OpToken::unary_prefix:
if (entry.visited!=0) return;
emit->tagOp(entry.tok->print,EmitXml::no_color,entry.op);
emit->tagOp(entry.tok->print1,EmitMarkup::no_color,entry.op);
emit->spaces(entry.tok->spacing,entry.tok->bump);
break;
case OpToken::postsurround:
if (entry.visited==0) return;
if (entry.visited==1) { // Front surround token
emit->spaces(entry.tok->spacing,entry.tok->bump);
entry.id2 = emit->openParen(entry.tok->print[0]);
entry.id2 = emit->openParen(entry.tok->print1);
emit->spaces(0,entry.tok->bump);
}
else { // Back surround token
emit->closeParen(entry.tok->print[1],entry.id2);
emit->closeParen(entry.tok->print2,entry.id2);
}
break;
case OpToken::presurround:
if (entry.visited==2) return;
if (entry.visited==0) { // Front surround token
entry.id2 = emit->openParen(entry.tok->print[0]);
entry.id2 = emit->openParen(entry.tok->print1);
}
else { // Back surround token
emit->closeParen(entry.tok->print[1],entry.id2);
emit->closeParen(entry.tok->print2,entry.id2);
emit->spaces(entry.tok->spacing,entry.tok->bump);
}
break;
@ -372,24 +375,22 @@ void PrintLanguage::emitAtom(const Atom &atom)
{
switch(atom.type) {
case syntax:
emit->print(atom.name.c_str(),atom.highlight);
emit->print(atom.name,atom.highlight);
break;
case vartoken:
emit->tagVariable(atom.name.c_str(),atom.highlight,
atom.ptr_second.vn,atom.op);
emit->tagVariable(atom.name,atom.highlight,atom.ptr_second.vn,atom.op);
break;
case functoken:
emit->tagFuncName(atom.name.c_str(),atom.highlight,
atom.ptr_second.fd,atom.op);
emit->tagFuncName(atom.name,atom.highlight,atom.ptr_second.fd,atom.op);
break;
case optoken:
emit->tagOp(atom.name.c_str(),atom.highlight,atom.op);
emit->tagOp(atom.name,atom.highlight,atom.op);
break;
case typetoken:
emit->tagType(atom.name.c_str(),atom.highlight,atom.ptr_second.ct);
emit->tagType(atom.name,atom.highlight,atom.ptr_second.ct);
break;
case fieldtoken:
emit->tagField(atom.name.c_str(),atom.highlight,atom.ptr_second.ct,atom.offset,atom.op);
emit->tagField(atom.name,atom.highlight,atom.ptr_second.ct,atom.offset,atom.op);
break;
case blanktoken:
break; // Print nothing
@ -592,7 +593,7 @@ void PrintLanguage::emitLineComment(int4 indent,const Comment *comm)
int4 id = emit->startComment();
// The comment delimeters should not be printed as
// comment tags, so that they won't get filled
emit->tagComment(commentstart.c_str(),EmitXml::comment_color,
emit->tagComment(commentstart,EmitMarkup::comment_color,
spc,off);
int4 pos = 0;
while(pos < text.size()) {
@ -620,24 +621,21 @@ void PrintLanguage::emitLineComment(int4 indent,const Comment *comm)
pos += 1;
}
string sub = text.substr(pos-count,count);
emit->tagComment(sub.c_str(),EmitXml::comment_color,
spc,off);
emit->tagComment(sub,EmitMarkup::comment_color,spc,off);
}
}
if (commentend.size() != 0)
emit->tagComment(commentend.c_str(),EmitXml::comment_color,
spc,off);
emit->tagComment(commentend,EmitMarkup::comment_color,spc,off);
emit->stopComment(id);
comm->setEmitted(true);
}
/// Tell the emitter whether to emit just the raw tokens or if
/// output is in XML format with additional mark-up on the raw tokens.
/// \param val is \b true for XML mark-up
void PrintLanguage::setXML(bool val)
/// Tell the emitter whether to emit just the raw tokens or if additional mark-up should be provided.
/// \param val is \b true for additional mark-up
void PrintLanguage::setMarkup(bool val)
{
((EmitPrettyPrint *)emit)->setXML(val);
((EmitPrettyPrint *)emit)->setMarkup(val);
}
/// Emitting formal code structuring can be turned off, causing all control-flow

View file

@ -90,7 +90,8 @@ public:
space, ///< No explicitly printed token
hiddenfunction ///< Operation that isn't explicitly printed
};
const char *print; ///< Printing characters for the token
string print1; ///< Printing characters for the token
string print2; ///< (terminating) characters for the token
int4 stage; ///< Additional elements consumed from the RPN stack when emitting this token
int4 precedence; ///< Precedence level of this token (higher binds more tightly)
bool associative; ///< True if the operator is associative
@ -134,6 +135,9 @@ public:
/// stack to provide a printing context mechanism for derived classes.
class PrintLanguage {
public:
static const string OPEN_PAREN; ///< "(" token
static const string CLOSE_PAREN; ///< ")" token
/// \brief Possible context sensitive modifiers to how tokens get emitted
enum modifiers {
force_hex = 1, ///< Force printing of hex
@ -203,7 +207,7 @@ public:
struct Atom {
const string &name; ///< The actual printed characters of the token
tagtype type; ///< The type of Atom
EmitXml::syntax_highlight highlight; ///< The type of highlighting to use when emitting the token
EmitMarkup::syntax_highlight highlight; ///< The type of highlighting to use when emitting the token
const PcodeOp *op; ///< A p-code operation associated with the token
union {
const Varnode *vn; ///< A Varnode associated with the token
@ -213,27 +217,27 @@ public:
int4 offset; ///< The offset (within the parent structure) for a \e field token
/// \brief Construct a token with no associated data-flow annotations
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl)
: name(nm) { type = t; highlight = hl; }
/// \brief Construct a token for a data-type name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const Datatype *c)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const Datatype *c)
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; }
/// \brief Construct a token for a field name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const Datatype *c,int4 off,const PcodeOp *o)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const Datatype *c,int4 off,const PcodeOp *o)
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; offset = off; op = o; }
/// \brief Construct a token with an associated PcodeOp
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o)
: name(nm) { type = t; highlight = hl; op = o; }
/// \brief Construct a token with an associated PcodeOp and Varnode
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o,const Varnode *v)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o,const Varnode *v)
: name(nm) { type=t; highlight = hl; ptr_second.vn = v; op = o; }
/// \brief Construct a token for a function name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o,const Funcdata *f)
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o,const Funcdata *f)
: name(nm) { type=t; highlight = hl; op = o; ptr_second.fd = f; }
};
private:
@ -250,7 +254,7 @@ protected:
Architecture *glb; ///< The Architecture owning the language emitter
const Scope *curscope; ///< The current symbol scope
CastStrategy *castStrategy; ///< The strategy for emitting explicit \e case operations
EmitXml *emit; ///< The low-level token emitter
Emit *emit; ///< The low-level token emitter
uint4 mods; ///< Currently active printing modifications
uint4 instr_comment_type; ///< Type of instruction comments to display
uint4 head_comment_type; ///< Type of header comments to display
@ -431,8 +435,8 @@ public:
void setNamespaceStrategy(namespace_strategy strat) { namespc_strategy = strat; } ///< Set how namespace tokens are displayed
uint4 getHeaderComment(void) const { return head_comment_type; } ///< Get the type of comments suitable for a function header
void setHeaderComment(uint4 val) { head_comment_type = val; } ///< Set the type of comments suitable for a function header
bool emitsXml(void) const { return emit->emitsXml(); } ///< Does the low-level emitter, emit XML markup
void setXML(bool val); ///< Set whether the low-level emitter, emits XML markup
bool emitsMarkup(void) const { return emit->emitsMarkup(); } ///< Does the low-level emitter, emit markup
void setMarkup(bool val); ///< Set whether the low-level emitter, emits markup
void setFlat(bool val); ///< Set whether nesting code structure should be emitted
virtual void initializeFromArchitecture(void)=0; ///< Initialize architecture specific aspects of printer

View file

@ -122,7 +122,7 @@ void SleighArchitecture::loadLanguageDescription(const string &specfile,ostream
ifstream s(specfile.c_str());
if (!s) return;
XmlDecode decoder;
XmlDecode decoder((const AddrSpaceManager *)0);
try {
decoder.ingestStream(s);
}

View file

@ -268,7 +268,7 @@ void SleighBase::restoreXml(const Element *el)
}
indexer.restoreXml(*iter);
iter++;
XmlDecode decoder(*iter);
XmlDecode decoder(this,*iter);
decodeSpaces(decoder,this);
iter++;
symtab.restoreXml(*iter,this);

View file

@ -134,7 +134,7 @@ void AddrSpace::truncateSpace(uint4 newsize)
void AddrSpace::encodeAttributes(Encoder &encoder,uintb offset) const
{
encoder.writeString(ATTRIB_SPACE,getName());
encoder.writeSpace(ATTRIB_SPACE,this);
encoder.writeUnsignedInteger(ATTRIB_OFFSET, offset);
}
@ -147,7 +147,7 @@ void AddrSpace::encodeAttributes(Encoder &encoder,uintb offset) const
void AddrSpace::encodeAttributes(Encoder &encoder,uintb offset,int4 size) const
{
encoder.writeString(ATTRIB_SPACE, getName());
encoder.writeSpace(ATTRIB_SPACE, this);
encoder.writeUnsignedInteger(ATTRIB_OFFSET, offset);
encoder.writeSignedInteger(ATTRIB_SIZE, size);
}
@ -482,7 +482,7 @@ void JoinSpace::encodeAttributes(Encoder &encoder,uintb offset) const
static AttributeId *pieceArray[] = { &ATTRIB_PIECE1, &ATTRIB_PIECE2, &ATTRIB_PIECE3, &ATTRIB_PIECE4,
&ATTRIB_PIECE5, &ATTRIB_PIECE6, &ATTRIB_PIECE7, &ATTRIB_PIECE8, &ATTRIB_PIECE9 };
JoinRecord *rec = getManager()->findJoin(offset); // Record must already exist
encoder.writeString(ATTRIB_SPACE, getName());
encoder.writeSpace(ATTRIB_SPACE, this);
int4 num = rec->numPieces();
if (num >= 8)
throw LowlevelError("Cannot encode more than 8 pieces");
@ -657,10 +657,7 @@ void OverlaySpace::decode(Decoder &decoder)
name = decoder.readString(ATTRIB_NAME);
index = decoder.readSignedInteger(ATTRIB_INDEX);
string basename = decoder.readString(ATTRIB_BASE);
baseSpace = getManager()->getSpaceByName(basename);
if (baseSpace == (AddrSpace *)0)
throw LowlevelError("Base space does not exist for overlay space: "+name);
baseSpace = decoder.readSpace(ATTRIB_BASE);
decoder.closeElement(elemId);
addressSize = baseSpace->getAddrSize();
wordsize = baseSpace->getWordSize();

View file

@ -119,15 +119,14 @@ void StringManager::encode(Encoder &encoder) const
/// Parse a \<stringmanage> element, with \<string> children.
/// \param decoder is the stream decoder
/// \param m is the manager for looking up AddressSpaces
void StringManager::decode(Decoder &decoder, const AddrSpaceManager *m)
void StringManager::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_STRINGMANAGE);
for (;;) {
uint4 subId = decoder.openElement();
if (subId != ELEM_STRING) break;
Address addr = Address::decode(decoder, m);
Address addr = Address::decode(decoder);
StringData &stringData(stringMap[addr]);
uint4 subId2 = decoder.openElement(ELEM_BYTES);
stringData.isTruncated = decoder.readBool(ATTRIB_TRUNC);

View file

@ -63,7 +63,7 @@ public:
virtual const vector<uint1> &getStringData(const Address &addr,Datatype *charType,bool &isTrunc)=0;
void encode(Encoder &encoder) const; ///< Encode cached strings to a stream
void decode(Decoder &decoder,const AddrSpaceManager *m); ///< Restore string cache from a stream
void decode(Decoder &decoder); ///< Restore string cache from a stream
static bool hasCharTerminator(const uint1 *buffer,int4 size,int4 charsize); ///< Check for a unicode string terminator
static int4 readUtf16(const uint1 *buf,bool bigend); ///< Read a UTF16 code point from a byte array

View file

@ -281,9 +281,8 @@ void LanedRegister::LanedIterator::normalize(void)
/// Parse any vector lane sizes.
/// \param decoder is the stream decoder
/// \param manage is used to map register names to storage info
/// \return \b true if the XML description provides lane sizes
bool LanedRegister::decode(Decoder &decoder,const AddrSpaceManager *manage)
bool LanedRegister::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_REGISTER);
@ -303,7 +302,7 @@ bool LanedRegister::decode(Decoder &decoder,const AddrSpaceManager *manage)
decoder.rewindAttributes();
VarnodeData storage;
storage.space = (AddrSpace *)0;
storage.decodeFromAttributes(decoder, manage);
storage.decodeFromAttributes(decoder);
decoder.closeElement(elemId);
wholeSize = storage.size;
sizeBitMask = 0;

View file

@ -111,7 +111,7 @@ private:
public:
LanedRegister(void) { wholeSize = 0; sizeBitMask = 0; } ///< Constructor for use with decode
LanedRegister(int4 sz,uint4 mask) { wholeSize = sz; sizeBitMask = mask; } ///< Constructor
bool decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Parse \<register> elements for lane sizes
bool decode(Decoder &decoder); ///< Parse \<register> elements for lane sizes
int4 getWholeSize(void) const { return wholeSize; } ///< Get the size in bytes of the whole laned register
uint4 getSizeBitMask(void) const { return sizeBitMask; } ///< Get the bit mask of possible lane sizes
void addLaneSize(int4 size) { sizeBitMask |= ((uint4)1 << size); } ///< Add a new \e size to the allowed list

View file

@ -132,7 +132,7 @@ void SpacebaseSpace::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_SPACE_BASE);
decodeBasicAttributes(decoder);
contain = getManager()->getSpaceByName(decoder.readString(ATTRIB_CONTAIN));
contain = decoder.readSpace(ATTRIB_CONTAIN);
decoder.closeElement(elemId);
}
@ -907,8 +907,7 @@ const FloatFormat *Translate::getFloatFormat(int4 size) const
/// A single pcode operation is parsed from an \<op> element and
/// returned to the application via the PcodeEmit::dump method.
/// \param decoder is the stream decoder
/// \param manage is the AddrSpace manager object of the associated processor
void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
void PcodeEmit::decodeOp(Decoder &decoder)
{
int4 opcode;
@ -918,7 +917,7 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
uint4 elemId = decoder.openElement(ELEM_OP);
opcode = decoder.readSignedInteger(ATTRIB_CODE);
Address pc = Address::decode(decoder,manage);
Address pc = Address::decode(decoder);
uint4 subId = decoder.peekElement();
if (subId == ELEM_VOID) {
decoder.openElement();
@ -926,7 +925,7 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
outptr = (VarnodeData *)0;
}
else {
outvar.decode(decoder,manage);
outvar.decode(decoder);
outptr = &outvar;
}
int4 isize = 0;
@ -935,13 +934,13 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
if (subId == 0) break;
if (subId == ELEM_SPACEID) {
decoder.openElement();
invar[isize].space = manage->getConstantSpace();
invar[isize].offset = (uintb)(uintp)manage->getSpaceByName( decoder.readString(ATTRIB_NAME) );
invar[isize].space = decoder.getAddrSpaceManager()->getConstantSpace();
invar[isize].offset = (uintb)(uintp)decoder.readSpace(ATTRIB_NAME);
invar[isize].size = sizeof(void *);
decoder.closeElement(subId);
}
else
invar[isize].decode(decoder,manage);
invar[isize].decode(decoder);
isize += 1;
}
decoder.closeElement(elemId);

View file

@ -108,7 +108,7 @@ public:
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)=0;
/// Emit pcode directly from an \<op> element
void decodeOp(Decoder &decoder,const AddrSpaceManager *trans);
void decodeOp(Decoder &decoder);
enum { // Tags for packed pcode format
unimpl_tag = 0x20,

View file

@ -763,7 +763,7 @@ void TypePointer::encode(Encoder &encoder) const
if (wordsize != 1)
encoder.writeSignedInteger(ATTRIB_WORDSIZE, wordsize);
if (spaceid != (AddrSpace *)0)
encoder.writeString(ATTRIB_SPACE, spaceid->getName());
encoder.writeSpace(ATTRIB_SPACE, spaceid);
ptrto->encodeRef(encoder);
encoder.closeElement(ELEM_TYPE);
}
@ -784,7 +784,7 @@ void TypePointer::decode(Decoder &decoder,TypeFactory &typegrp)
wordsize = decoder.readUnsignedInteger();
}
else if (attrib == ATTRIB_SPACE) {
spaceid = typegrp.getArch()->getSpaceByName(decoder.readString());
spaceid = decoder.readSpace();
}
}
ptrto = typegrp.decodeType( decoder );
@ -1871,7 +1871,7 @@ void TypePointerRel::decode(Decoder &decoder,TypeFactory &typegrp)
wordsize = decoder.readUnsignedInteger();
}
else if (attrib == ATTRIB_SPACE) {
spaceid = typegrp.getArch()->getSpaceByName(decoder.readString());
spaceid = decoder.readSpace();
}
}
ptrto = typegrp.decodeType( decoder );
@ -2397,7 +2397,7 @@ void TypeSpacebase::encode(Encoder &encoder) const
}
encoder.openElement(ELEM_TYPE);
encodeBasic(metatype,encoder);
encoder.writeString(ATTRIB_SPACE, spaceid->getName());
encoder.writeSpace(ATTRIB_SPACE, spaceid);
localframe.encode(encoder);
encoder.closeElement(ELEM_TYPE);
}
@ -2410,8 +2410,8 @@ void TypeSpacebase::decode(Decoder &decoder,TypeFactory &typegrp)
{
// uint4 elemId = decoder.openElement();
decodeBasic(decoder);
spaceid = glb->getSpaceByName(decoder.readString(ATTRIB_SPACE));
localframe = Address::decode(decoder,typegrp.getArch());
spaceid = decoder.readSpace(ATTRIB_SPACE);
localframe = Address::decode(decoder);
// decoder.closeElement(elemId);
}

View file

@ -20,7 +20,7 @@ Datatype *TypeFactoryGhidra::findById(const string &n,uint8 id,int4 sz)
{
Datatype *ct = TypeFactory::findById(n,id,sz); // Try internal find
if (ct != (Datatype *)0) return ct;
XmlDecode decoder;
XmlDecode decoder(glb);
try {
if (!((ArchitectureGhidra *)glb)->getType(n,id,decoder)) // See if ghidra knows about type
return (Datatype *)0;

View file

@ -134,7 +134,7 @@ void SegmentOp::decode(Decoder &decoder)
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
if (attribId == ATTRIB_SPACE)
spc = glb->getSpaceByName(decoder.readString());
spc = decoder.readSpace();
else if (attribId == ATTRIB_FARPOINTER)
supportsfarpointer = true;
else if (attribId == ATTRIB_USEROP) { // Based on existing sleigh op
@ -157,7 +157,7 @@ void SegmentOp::decode(Decoder &decoder)
int4 sz;
decoder.openElement();
if (decoder.peekElement() != 0) {
Address addr = Address::decode(decoder,glb,sz);
Address addr = Address::decode(decoder,sz);
constresolve.space = addr.getSpace();
constresolve.offset = addr.getOffset();
constresolve.size = sz;

View file

@ -373,7 +373,7 @@ void ScopeLocal::encode(Encoder &encoder) const
{
encoder.openElement(ELEM_LOCALDB);
encoder.writeString(ATTRIB_MAIN, space->getName());
encoder.writeSpace(ATTRIB_MAIN, space);
encoder.writeBool(ATTRIB_LOCK, rangeLocked);
ScopeInternal::encode(encoder);
encoder.closeElement(ELEM_LOCALDB);
@ -392,7 +392,7 @@ void ScopeLocal::decodeWrappingAttributes(Decoder &decoder)
rangeLocked = false;
if (decoder.readBool(ATTRIB_LOCK))
rangeLocked = true;
space = glb->getSpaceByName(decoder.readString(ATTRIB_MAIN));
space = decoder.readSpace(ATTRIB_MAIN);
}
/// The given range can no longer hold a \e mapped local variable. This indicates the range