mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-2237 AddrSpace as marshaling primitive and prettyprint update
This commit is contained in:
parent
4807ec354a
commit
6be9943b8a
58 changed files with 1333 additions and 1098 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"); }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue