mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +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);
|
encoder.closeElement(ELEM_SEQNUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
SeqNum SeqNum::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
SeqNum SeqNum::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintm uniq = ~((uintm)0);
|
uintm uniq = ~((uintm)0);
|
||||||
uint4 elemId = decoder.openElement(ELEM_SEQNUM);
|
uint4 elemId = decoder.openElement(ELEM_SEQNUM);
|
||||||
Address pc = Address::decode(decoder,manage); // Recover address
|
Address pc = Address::decode(decoder); // Recover address
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
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
|
/// or a \e name attribute can be used to recover an address
|
||||||
/// based on a register name.
|
/// based on a register name.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the address space manager for the program
|
|
||||||
/// \return the resulting Address
|
/// \return the resulting Address
|
||||||
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
Address Address::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeData var;
|
VarnodeData var;
|
||||||
|
|
||||||
var.decode(decoder,manage);
|
var.decode(decoder);
|
||||||
return Address(var.space,var.offset);
|
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
|
/// and size based on a register name. If a size is recovered
|
||||||
/// it is stored in \e size reference.
|
/// it is stored in \e size reference.
|
||||||
/// \param decoder is the stream decoder
|
/// \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
|
/// \param size is the reference to any recovered size
|
||||||
/// \return the resulting Address
|
/// \return the resulting Address
|
||||||
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage,int4 &size)
|
Address Address::decode(Decoder &decoder,int4 &size)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeData var;
|
VarnodeData var;
|
||||||
|
|
||||||
var.decode(decoder,manage);
|
var.decode(decoder);
|
||||||
size = var.size;
|
size = var.size;
|
||||||
return Address(var.space,var.offset);
|
return Address(var.space,var.offset);
|
||||||
}
|
}
|
||||||
|
@ -293,7 +291,7 @@ void Range::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
encoder.openElement(ELEM_RANGE);
|
encoder.openElement(ELEM_RANGE);
|
||||||
encoder.writeString(ATTRIB_SPACE, spc->getName());
|
encoder.writeSpace(ATTRIB_SPACE, spc);
|
||||||
encoder.writeUnsignedInteger(ATTRIB_FIRST, first);
|
encoder.writeUnsignedInteger(ATTRIB_FIRST, first);
|
||||||
encoder.writeUnsignedInteger(ATTRIB_LAST, last);
|
encoder.writeUnsignedInteger(ATTRIB_LAST, last);
|
||||||
encoder.closeElement(ELEM_RANGE);
|
encoder.closeElement(ELEM_RANGE);
|
||||||
|
@ -301,21 +299,19 @@ void Range::encode(Encoder &encoder) const
|
||||||
|
|
||||||
/// Reconstruct this object from a \<range> or \<register> element
|
/// Reconstruct this object from a \<range> or \<register> element
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the space manager for recovering AddrSpace objects
|
void Range::decode(Decoder &decoder)
|
||||||
void Range::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
||||||
throw XmlError("Expecting <range> or <register> element");
|
throw XmlError("Expecting <range> or <register> element");
|
||||||
decodeFromAttributes(decoder,manage);
|
decodeFromAttributes(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconstruct from attributes that may not be part of a \<range> element.
|
/// Reconstruct from attributes that may not be part of a \<range> element.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the space manager for recovering AddrSpace objects
|
void Range::decodeFromAttributes(Decoder &decoder)
|
||||||
void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
spc = (AddrSpace *)0;
|
spc = (AddrSpace *)0;
|
||||||
|
@ -326,10 +322,7 @@ void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
if (attribId == 0) break;
|
||||||
if (attribId == ATTRIB_SPACE) {
|
if (attribId == ATTRIB_SPACE) {
|
||||||
string spcname = decoder.readString();
|
spc = decoder.readSpace();
|
||||||
spc = manage->getSpaceByName(spcname);
|
|
||||||
if (spc == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Undefined space: "+spcname);
|
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_FIRST) {
|
else if (attribId == ATTRIB_FIRST) {
|
||||||
first = decoder.readUnsignedInteger();
|
first = decoder.readUnsignedInteger();
|
||||||
|
@ -339,7 +332,7 @@ void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage
|
||||||
seenLast = true;
|
seenLast = true;
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_NAME) {
|
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()));
|
const VarnodeData &point(trans->getRegister(decoder.readString()));
|
||||||
spc = point.space;
|
spc = point.space;
|
||||||
first = point.offset;
|
first = point.offset;
|
||||||
|
@ -620,14 +613,13 @@ void RangeList::encode(Encoder &encoder) const
|
||||||
|
|
||||||
/// Recover each individual disjoint Range for \b this RangeList.
|
/// Recover each individual disjoint Range for \b this RangeList.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is manager for retrieving address spaces
|
void RangeList::decode(Decoder &decoder)
|
||||||
void RangeList::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_RANGELIST);
|
uint4 elemId = decoder.openElement(ELEM_RANGELIST);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,manage);
|
range.decode(decoder);
|
||||||
tree.insert(range);
|
tree.insert(range);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
|
|
@ -96,10 +96,10 @@ public:
|
||||||
void encode(Encoder &encoder,int4 size) const; ///< Encode \b this and a size to a stream
|
void encode(Encoder &encoder,int4 size) const; ///< Encode \b this and a size to a stream
|
||||||
|
|
||||||
/// Restore an address from parsed XML
|
/// 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
|
/// 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
|
/// \brief A class for uniquely labelling and comparing PcodeOps
|
||||||
|
@ -158,7 +158,7 @@ public:
|
||||||
void encode(Encoder &encoder) const;
|
void encode(Encoder &encoder) const;
|
||||||
|
|
||||||
/// Decode a SeqNum from a stream
|
/// 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
|
/// Write out a SeqNum in human readable form to a stream
|
||||||
friend ostream &operator<<(ostream &s,const SeqNum &sq);
|
friend ostream &operator<<(ostream &s,const SeqNum &sq);
|
||||||
|
@ -202,8 +202,8 @@ public:
|
||||||
return (first < op2.first); }
|
return (first < op2.first); }
|
||||||
void printBounds(ostream &s) const; ///< Print \b this Range to a stream
|
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 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 decode(Decoder &decoder); ///< Restore \b this from a stream
|
||||||
void decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage); ///< Read \b from attributes on another tag
|
void decodeFromAttributes(Decoder &decoder); ///< Read \b from attributes on another tag
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A partially parsed description of a Range
|
/// \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
|
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 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 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
|
/// Precalculated masks indexed by size
|
||||||
|
|
|
@ -409,13 +409,13 @@ void Architecture::setPrintLanguage(const string &nm)
|
||||||
PrintLanguageCapability *capa = PrintLanguageCapability::findCapability(nm);
|
PrintLanguageCapability *capa = PrintLanguageCapability::findCapability(nm);
|
||||||
if (capa == (PrintLanguageCapability *)0)
|
if (capa == (PrintLanguageCapability *)0)
|
||||||
throw LowlevelError("Unknown print language: "+nm);
|
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();
|
ostream *t = print->getOutputStream();
|
||||||
print = capa->buildLanguage(this);
|
print = capa->buildLanguage(this);
|
||||||
print->setOutputStream(t); // Restore settings from previous language
|
print->setOutputStream(t); // Restore settings from previous language
|
||||||
print->initializeFromArchitecture();
|
print->initializeFromArchitecture();
|
||||||
if (printxml)
|
if (printMarkup)
|
||||||
print->setXML(true);
|
print->setMarkup(true);
|
||||||
printlist.push_back(print);
|
printlist.push_back(print);
|
||||||
print->adjustTypeOperators();
|
print->adjustTypeOperators();
|
||||||
return;
|
return;
|
||||||
|
@ -446,8 +446,8 @@ void Architecture::decodeFlowOverride(Decoder &decoder)
|
||||||
uint4 subId = decoder.openElement();
|
uint4 subId = decoder.openElement();
|
||||||
if (subId != ELEM_FLOW) break;
|
if (subId != ELEM_FLOW) break;
|
||||||
string flowType = decoder.readString(ATTRIB_TYPE);
|
string flowType = decoder.readString(ATTRIB_TYPE);
|
||||||
Address funcaddr = Address::decode(decoder,this);
|
Address funcaddr = Address::decode(decoder);
|
||||||
Address overaddr = Address::decode(decoder,this);
|
Address overaddr = Address::decode(decoder);
|
||||||
Funcdata *fd = symboltab->getGlobalScope()->queryFunction(funcaddr);
|
Funcdata *fd = symboltab->getGlobalScope()->queryFunction(funcaddr);
|
||||||
if (fd != (Funcdata *)0)
|
if (fd != (Funcdata *)0)
|
||||||
fd->getOverride().insertFlowOverride(overaddr,Override::stringToType(flowType));
|
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());
|
const Element *el = store.getTag(ELEM_SAVE_STATE.getName());
|
||||||
if (el == (const Element *)0)
|
if (el == (const Element *)0)
|
||||||
throw LowlevelError("Could not find save_state tag");
|
throw LowlevelError("Could not find save_state tag");
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
uint4 elemId = decoder.openElement(ELEM_SAVE_STATE);
|
uint4 elemId = decoder.openElement(ELEM_SAVE_STATE);
|
||||||
loadersymbols_parsed = false;
|
loadersymbols_parsed = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -500,11 +500,11 @@ void Architecture::restoreXml(DocumentStorage &store)
|
||||||
else if (subId == ELEM_DB)
|
else if (subId == ELEM_DB)
|
||||||
symboltab->decode(decoder);
|
symboltab->decode(decoder);
|
||||||
else if (subId == ELEM_CONTEXT_POINTS)
|
else if (subId == ELEM_CONTEXT_POINTS)
|
||||||
context->decode(decoder,this);
|
context->decode(decoder);
|
||||||
else if (subId == ELEM_COMMENTDB)
|
else if (subId == ELEM_COMMENTDB)
|
||||||
commentdb->decode(decoder,this);
|
commentdb->decode(decoder);
|
||||||
else if (subId == ELEM_STRINGMANAGE)
|
else if (subId == ELEM_STRINGMANAGE)
|
||||||
stringManager->decode(decoder,this);
|
stringManager->decode(decoder);
|
||||||
else if (subId == ELEM_CONSTANTPOOL)
|
else if (subId == ELEM_CONSTANTPOOL)
|
||||||
cpool->decode(decoder,*types);
|
cpool->decode(decoder,*types);
|
||||||
else if (subId == ELEM_OPTIONSLIST)
|
else if (subId == ELEM_OPTIONSLIST)
|
||||||
|
@ -607,7 +607,7 @@ void Architecture::buildTypegrp(DocumentStorage &store)
|
||||||
const Element *el = store.getTag("coretypes");
|
const Element *el = store.getTag("coretypes");
|
||||||
types = new TypeFactory(this); // Initialize the object
|
types = new TypeFactory(this); // Initialize the object
|
||||||
if (el != (const Element *)0) {
|
if (el != (const Element *)0) {
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
types->decodeCoreTypes(decoder);
|
types->decodeCoreTypes(decoder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -929,7 +929,7 @@ void Architecture::decodeReadOnly(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_READONLY);
|
uint4 elemId = decoder.openElement(ELEM_READONLY);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,this);
|
range.decode(decoder);
|
||||||
symboltab->setPropertyRange(Varnode::readonly,range);
|
symboltab->setPropertyRange(Varnode::readonly,range);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -945,7 +945,7 @@ void Architecture::decodeVolatile(Decoder &decoder)
|
||||||
userops.decodeVolatile(decoder,this);
|
userops.decodeVolatile(decoder,this);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,this); // Tag itself is range
|
range.decode(decoder); // Tag itself is range
|
||||||
symboltab->setPropertyRange(Varnode::volatil,range);
|
symboltab->setPropertyRange(Varnode::volatil,range);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -962,7 +962,7 @@ void Architecture::decodeReturnAddress(Decoder &decoder)
|
||||||
if (subId != 0) {
|
if (subId != 0) {
|
||||||
if (defaultReturnAddr.space != (AddrSpace *)0)
|
if (defaultReturnAddr.space != (AddrSpace *)0)
|
||||||
throw LowlevelError("Multiple <returnaddress> tags in .cspec");
|
throw LowlevelError("Multiple <returnaddress> tags in .cspec");
|
||||||
defaultReturnAddr.decode(decoder,this);
|
defaultReturnAddr.decode(decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
@ -976,7 +976,7 @@ void Architecture::decodeIncidentalCopy(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_INCIDENTALCOPY);
|
uint4 elemId = decoder.openElement(ELEM_INCIDENTALCOPY);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
VarnodeData vdata;
|
VarnodeData vdata;
|
||||||
vdata.decode(decoder,this);
|
vdata.decode(decoder);
|
||||||
Range range( vdata.space, vdata.offset, vdata.offset+vdata.size-1);
|
Range range( vdata.space, vdata.offset, vdata.offset+vdata.size-1);
|
||||||
symboltab->setPropertyRange(Varnode::incidental_copy,range);
|
symboltab->setPropertyRange(Varnode::incidental_copy,range);
|
||||||
}
|
}
|
||||||
|
@ -994,7 +994,7 @@ void Architecture::decodeLaneSizes(Decoder &decoder)
|
||||||
|
|
||||||
uint4 elemId = decoder.openElement(ELEM_REGISTER_DATA);
|
uint4 elemId = decoder.openElement(ELEM_REGISTER_DATA);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
if (lanedRegister.decode(decoder, this)) {
|
if (lanedRegister.decode(decoder)) {
|
||||||
int4 sizeIndex = lanedRegister.getWholeSize();
|
int4 sizeIndex = lanedRegister.getWholeSize();
|
||||||
while (maskList.size() <= sizeIndex)
|
while (maskList.size() <= sizeIndex)
|
||||||
maskList.push_back(0);
|
maskList.push_back(0);
|
||||||
|
@ -1016,10 +1016,10 @@ void Architecture::decodeStackPointer(Decoder &decoder)
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_STACKPOINTER);
|
uint4 elemId = decoder.openElement(ELEM_STACKPOINTER);
|
||||||
|
|
||||||
string spaceName;
|
|
||||||
string registerName;
|
string registerName;
|
||||||
bool stackGrowth = true; // Default stack growth is in negative direction
|
bool stackGrowth = true; // Default stack growth is in negative direction
|
||||||
bool isreversejustify = false;
|
bool isreversejustify = false;
|
||||||
|
AddrSpace *basespace = (AddrSpace *)0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
if (attribId == 0) break;
|
||||||
|
@ -1028,14 +1028,13 @@ void Architecture::decodeStackPointer(Decoder &decoder)
|
||||||
else if (attribId == ATTRIB_GROWTH)
|
else if (attribId == ATTRIB_GROWTH)
|
||||||
stackGrowth = decoder.readString() == "negative";
|
stackGrowth = decoder.readString() == "negative";
|
||||||
else if (attribId == ATTRIB_SPACE)
|
else if (attribId == ATTRIB_SPACE)
|
||||||
spaceName = decoder.readString();
|
basespace = decoder.readSpace();
|
||||||
else if (attribId == ATTRIB_REGISTER)
|
else if (attribId == ATTRIB_REGISTER)
|
||||||
registerName = decoder.readString();
|
registerName = decoder.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
AddrSpace *basespace = getSpaceByName(spaceName);
|
|
||||||
if (basespace == (AddrSpace *)0)
|
if (basespace == (AddrSpace *)0)
|
||||||
throw LowlevelError("Unknown space name: "+spaceName);
|
throw LowlevelError(ELEM_STACKPOINTER.getName() + " element missing \"space\" attribute");
|
||||||
|
|
||||||
VarnodeData point = translate->getRegister(registerName);
|
VarnodeData point = translate->getRegister(registerName);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -1056,10 +1055,7 @@ void Architecture::decodeDeadcodeDelay(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_DEADCODEDELAY);
|
uint4 elemId = decoder.openElement(ELEM_DEADCODEDELAY);
|
||||||
string spaceName = decoder.readString(ATTRIB_SPACE);
|
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
|
||||||
AddrSpace *spc = getSpaceByName(spaceName);
|
|
||||||
if (spc == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Unknown space name: "+spaceName);
|
|
||||||
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
|
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
|
||||||
if (delay >= 0)
|
if (delay >= 0)
|
||||||
setDeadcodeDelay(spc,delay);
|
setDeadcodeDelay(spc,delay);
|
||||||
|
@ -1075,7 +1071,7 @@ void Architecture::decodeInferPtrBounds(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_INFERPTRBOUNDS);
|
uint4 elemId = decoder.openElement(ELEM_INFERPTRBOUNDS);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,this);
|
range.decode(decoder);
|
||||||
setInferPtrBounds(range);
|
setInferPtrBounds(range);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -1113,12 +1109,9 @@ void Architecture::decodeSpacebase(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_SPACEBASE);
|
uint4 elemId = decoder.openElement(ELEM_SPACEBASE);
|
||||||
string nameString = decoder.readString(ATTRIB_NAME);
|
string nameString = decoder.readString(ATTRIB_NAME);
|
||||||
string registerName = decoder.readString(ATTRIB_REGISTER);
|
string registerName = decoder.readString(ATTRIB_REGISTER);
|
||||||
string spaceName = decoder.readString(ATTRIB_SPACE);
|
AddrSpace *basespace = decoder.readSpace(ATTRIB_SPACE);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
const VarnodeData &point(translate->getRegister(registerName));
|
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);
|
addSpacebase(basespace,nameString,point,point.size,false,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1131,7 +1124,7 @@ void Architecture::decodeNoHighPtr(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_NOHIGHPTR);
|
uint4 elemId = decoder.openElement(ELEM_NOHIGHPTR);
|
||||||
while(decoder.peekElement() != 0) { // Iterate over every range tag in the list
|
while(decoder.peekElement() != 0) { // Iterate over every range tag in the list
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,this);
|
range.decode(decoder);
|
||||||
addNoHighPtr(range);
|
addNoHighPtr(range);
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -1151,7 +1144,7 @@ void Architecture::decodePreferSplit(Decoder &decoder)
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
splitrecords.emplace_back();
|
splitrecords.emplace_back();
|
||||||
PreferSplitRecord &record( splitrecords.back() );
|
PreferSplitRecord &record( splitrecords.back() );
|
||||||
record.storage.decode( decoder, this );
|
record.storage.decode( decoder );
|
||||||
record.splitoffset = record.storage.size/2;
|
record.splitoffset = record.storage.size/2;
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
@ -1203,7 +1196,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
|
||||||
const Element *el = store.getTag("processor_spec");
|
const Element *el = store.getTag("processor_spec");
|
||||||
if (el == (const Element *)0)
|
if (el == (const Element *)0)
|
||||||
throw LowlevelError("No processor configuration tag found");
|
throw LowlevelError("No processor configuration tag found");
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
|
|
||||||
uint4 elemId = decoder.openElement(ELEM_PROCESSOR_SPEC);
|
uint4 elemId = decoder.openElement(ELEM_PROCESSOR_SPEC);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -1218,7 +1211,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
|
||||||
else if (subId == ELEM_INCIDENTALCOPY)
|
else if (subId == ELEM_INCIDENTALCOPY)
|
||||||
decodeIncidentalCopy(decoder);
|
decodeIncidentalCopy(decoder);
|
||||||
else if (subId == ELEM_CONTEXT_DATA)
|
else if (subId == ELEM_CONTEXT_DATA)
|
||||||
context->decodeFromSpec(decoder,this);
|
context->decodeFromSpec(decoder);
|
||||||
else if (subId == ELEM_JUMPASSIST)
|
else if (subId == ELEM_JUMPASSIST)
|
||||||
userops.decodeJumpAssist(decoder, this);
|
userops.decodeJumpAssist(decoder, this);
|
||||||
else if (subId == ELEM_SEGMENTOP)
|
else if (subId == ELEM_SEGMENTOP)
|
||||||
|
@ -1228,11 +1221,8 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_DATA_SPACE) {
|
else if (subId == ELEM_DATA_SPACE) {
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
string spaceName = decoder.readString(ATTRIB_SPACE);
|
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
AddrSpace *spc = getSpaceByName(spaceName);
|
|
||||||
if (spc == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Undefined space: "+spaceName);
|
|
||||||
setDefaultDataSpace(spc->getIndex());
|
setDefaultDataSpace(spc->getIndex());
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_INFERPTRBOUNDS) {
|
else if (subId == ELEM_INFERPTRBOUNDS) {
|
||||||
|
@ -1273,7 +1263,7 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
|
||||||
const Element *el = store.getTag("compiler_spec");
|
const Element *el = store.getTag("compiler_spec");
|
||||||
if (el == (const Element *)0)
|
if (el == (const Element *)0)
|
||||||
throw LowlevelError("No compiler configuration tag found");
|
throw LowlevelError("No compiler configuration tag found");
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
|
|
||||||
uint4 elemId = decoder.openElement(ELEM_COMPILER_SPEC);
|
uint4 elemId = decoder.openElement(ELEM_COMPILER_SPEC);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -1306,7 +1296,7 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
|
||||||
else if (subId == ELEM_READONLY)
|
else if (subId == ELEM_READONLY)
|
||||||
decodeReadOnly(decoder);
|
decodeReadOnly(decoder);
|
||||||
else if (subId == ELEM_CONTEXT_DATA)
|
else if (subId == ELEM_CONTEXT_DATA)
|
||||||
context->decodeFromSpec(decoder,this);
|
context->decodeFromSpec(decoder);
|
||||||
else if (subId == ELEM_RESOLVEPROTOTYPE)
|
else if (subId == ELEM_RESOLVEPROTOTYPE)
|
||||||
decodeProto(decoder);
|
decodeProto(decoder);
|
||||||
else if (subId == ELEM_EVAL_CALLED_PROTOTYPE)
|
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
|
el = store.getTag("specextensions"); // Look for any user-defined configuration document
|
||||||
if (el != (const Element *)0) {
|
if (el != (const Element *)0) {
|
||||||
XmlDecode decoderExt(el);
|
XmlDecode decoderExt(this,el);
|
||||||
elemId = decoderExt.openElement(ELEM_SPECEXTENSIONS);
|
elemId = decoderExt.openElement(ELEM_SPECEXTENSIONS);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 subId = decoderExt.peekElement();
|
uint4 subId = decoderExt.peekElement();
|
||||||
|
@ -1388,7 +1378,7 @@ void Architecture::parseExtraRules(DocumentStorage &store)
|
||||||
{
|
{
|
||||||
const Element *expertag = store.getTag("experimental_rules");
|
const Element *expertag = store.getTag("experimental_rules");
|
||||||
if (expertag != (const Element *)0) {
|
if (expertag != (const Element *)0) {
|
||||||
XmlDecode decoder(expertag);
|
XmlDecode decoder(this,expertag);
|
||||||
uint4 elemId = decoder.openElement(ELEM_EXPERIMENTAL_RULES);
|
uint4 elemId = decoder.openElement(ELEM_EXPERIMENTAL_RULES);
|
||||||
while(decoder.peekElement() != 0)
|
while(decoder.peekElement() != 0)
|
||||||
decodeDynamicRule( decoder );
|
decodeDynamicRule( decoder );
|
||||||
|
|
|
@ -1324,10 +1324,10 @@ void BlockGraph::encodeBody(Encoder &encoder) const
|
||||||
list[i]->encode(encoder);
|
list[i]->encode(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockGraph::decodeBody(Decoder &decoder,BlockMap &resolver)
|
void BlockGraph::decodeBody(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockMap newresolver(resolver);
|
BlockMap newresolver;
|
||||||
vector<FlowBlock *> tmplist;
|
vector<FlowBlock *> tmplist;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -1352,11 +1352,10 @@ void BlockGraph::decodeBody(Decoder &decoder,BlockMap &resolver)
|
||||||
/// Parse a \<block> element. This is currently just a wrapper around the
|
/// Parse a \<block> element. This is currently just a wrapper around the
|
||||||
/// FlowBlock::decode() that sets of the BlockMap resolver
|
/// FlowBlock::decode() that sets of the BlockMap resolver
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param m is the address space manager
|
void BlockGraph::decode(Decoder &decoder)
|
||||||
void BlockGraph::decode(Decoder &decoder,const AddrSpaceManager *m)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockMap resolver(m);
|
BlockMap resolver;
|
||||||
FlowBlock::decode(decoder,resolver);
|
FlowBlock::decode(decoder,resolver);
|
||||||
// Restore goto references here
|
// Restore goto references here
|
||||||
}
|
}
|
||||||
|
@ -2417,7 +2416,7 @@ void FlowBlock::decode(Decoder &decoder,BlockMap &resolver)
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_BLOCK);
|
uint4 elemId = decoder.openElement(ELEM_BLOCK);
|
||||||
decodeHeader(decoder);
|
decodeHeader(decoder);
|
||||||
decodeBody(decoder,resolver);
|
decodeBody(decoder);
|
||||||
decodeEdges(decoder,resolver);
|
decodeEdges(decoder,resolver);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
@ -2562,10 +2561,10 @@ void BlockBasic::encodeBody(Encoder &encoder) const
|
||||||
cover.encode(encoder);
|
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
|
void BlockBasic::printHeader(ostream &s) const
|
||||||
|
@ -3440,12 +3439,6 @@ FlowBlock *BlockSwitch::nextFlowAfter(const FlowBlock *bl) const
|
||||||
return getParent()->nextFlowAfter(this);
|
return getParent()->nextFlowAfter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockMap::BlockMap(const BlockMap &op2)
|
|
||||||
|
|
||||||
{
|
|
||||||
manage = op2.manage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \param bt is the block_type
|
/// \param bt is the block_type
|
||||||
/// \return a new instance of the specialized FlowBlock
|
/// \return a new instance of the specialized FlowBlock
|
||||||
FlowBlock *BlockMap::resolveBlock(FlowBlock::block_type bt)
|
FlowBlock *BlockMap::resolveBlock(FlowBlock::block_type bt)
|
||||||
|
|
|
@ -190,8 +190,7 @@ public:
|
||||||
/// \brief Restore details about \b this FlowBlock from an element stream
|
/// \brief Restore details about \b this FlowBlock from an element stream
|
||||||
///
|
///
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param resolver is used to recover FlowBlock objects based on elment references
|
virtual void decodeBody(Decoder &decoder) {}
|
||||||
virtual void decodeBody(Decoder &decoder,BlockMap &resolver) {}
|
|
||||||
void encodeEdges(Encoder &encoder) const; ///< Encode edge information to a stream
|
void encodeEdges(Encoder &encoder) const; ///< Encode edge information to a stream
|
||||||
void decodeEdges(Decoder &decoder,BlockMap &resolver);
|
void decodeEdges(Decoder &decoder,BlockMap &resolver);
|
||||||
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||||
|
@ -310,8 +309,8 @@ public:
|
||||||
virtual void finalTransform(Funcdata &data);
|
virtual void finalTransform(Funcdata &data);
|
||||||
virtual void finalizePrinting(Funcdata &data) const;
|
virtual void finalizePrinting(Funcdata &data) const;
|
||||||
virtual void encodeBody(Encoder &encoder) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
virtual void decodeBody(Decoder &decoder,BlockMap &resolver);
|
virtual void decodeBody(Decoder &decoder);
|
||||||
void decode(Decoder &decoder,const AddrSpaceManager *m); ///< Restore \b this BlockGraph from an XML stream
|
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 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 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
|
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 block_type getType(void) const { return t_basic; }
|
||||||
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; }
|
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; }
|
||||||
virtual void encodeBody(Encoder &encoder) const;
|
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 printHeader(ostream &s) const;
|
||||||
virtual void printRaw(ostream &s) const;
|
virtual void printRaw(ostream &s) const;
|
||||||
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
|
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
|
/// list of FlowBlock objects sorted by index and then looks up the FlowBlock matching a given
|
||||||
/// index as edges specify them.
|
/// index as edges specify them.
|
||||||
class BlockMap {
|
class BlockMap {
|
||||||
const AddrSpaceManager *manage; ///< Address space manager used to decode FlowBlock address ranges
|
|
||||||
vector<FlowBlock *> sortlist; ///< The list of deserialized FlowBlock objects
|
vector<FlowBlock *> sortlist; ///< The list of deserialized FlowBlock objects
|
||||||
FlowBlock *resolveBlock(FlowBlock::block_type bt); ///< Construct a FlowBlock of the given type
|
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
|
static FlowBlock *findBlock(const vector<FlowBlock *> &list,int4 ind); ///< Locate a FlowBlock with a given index
|
||||||
public:
|
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
|
void sortList(void); ///< Sort the list of FlowBlock objects
|
||||||
|
|
||||||
/// \brief Find the FlowBlock matching the given index
|
/// \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);
|
uint4 elemId = decoder.openElement(ELEM_EDGE);
|
||||||
const AddrSpaceManager *manage = graph->getArch();
|
|
||||||
Address fromaddr,toaddr,siteaddr;
|
Address fromaddr,toaddr,siteaddr;
|
||||||
|
|
||||||
fromaddr = Address::decode(decoder,manage);
|
fromaddr = Address::decode(decoder);
|
||||||
toaddr = Address::decode(decoder,manage);
|
toaddr = Address::decode(decoder);
|
||||||
siteaddr = Address::decode(decoder,manage);
|
siteaddr = Address::decode(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
|
||||||
CallGraphNode *fromnode = graph->findNode(fromaddr);
|
CallGraphNode *fromnode = graph->findNode(fromaddr);
|
||||||
|
@ -83,7 +82,7 @@ void CallGraphNode::decode(Decoder &decoder,CallGraph *graph)
|
||||||
if (attribId == ATTRIB_NAME)
|
if (attribId == ATTRIB_NAME)
|
||||||
name = decoder.readString();
|
name = decoder.readString();
|
||||||
}
|
}
|
||||||
Address addr = Address::decode(decoder,graph->getArch());
|
Address addr = Address::decode(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
graph->addNode(addr,name);
|
graph->addNode(addr,name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,6 @@ class CallGraph {
|
||||||
void iterateFunctionsAddrOrder(Scope *scope);
|
void iterateFunctionsAddrOrder(Scope *scope);
|
||||||
public:
|
public:
|
||||||
CallGraph(Architecture *g) { glb = g; }
|
CallGraph(Architecture *g) { glb = g; }
|
||||||
Architecture *getArch(void) const { return glb; }
|
|
||||||
CallGraphNode *addNode(Funcdata *f);
|
CallGraphNode *addNode(Funcdata *f);
|
||||||
CallGraphNode *addNode(const Address &addr,const string &nm);
|
CallGraphNode *addNode(const Address &addr,const string &nm);
|
||||||
CallGraphNode *findNode(const Address &addr);
|
CallGraphNode *findNode(const Address &addr);
|
||||||
|
|
|
@ -52,16 +52,15 @@ void Comment::encode(Encoder &encoder) const
|
||||||
|
|
||||||
/// Parse a \<comment> element from the given stream decoder
|
/// Parse a \<comment> element from the given stream decoder
|
||||||
/// \param decoder is 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)
|
||||||
void Comment::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
emitted = false;
|
emitted = false;
|
||||||
type = 0;
|
type = 0;
|
||||||
uint4 elemId = decoder.openElement(ELEM_COMMENT);
|
uint4 elemId = decoder.openElement(ELEM_COMMENT);
|
||||||
type = Comment::encodeCommentType(decoder.readString(ATTRIB_TYPE));
|
type = Comment::encodeCommentType(decoder.readString(ATTRIB_TYPE));
|
||||||
funcaddr = Address::decode(decoder,manage);
|
funcaddr = Address::decode(decoder);
|
||||||
addr = Address::decode(decoder,manage);
|
addr = Address::decode(decoder);
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId != 0) {
|
if (subId != 0) {
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
|
@ -249,13 +248,13 @@ void CommentDatabaseInternal::encode(Encoder &encoder) const
|
||||||
encoder.closeElement(ELEM_COMMENTDB);
|
encoder.closeElement(ELEM_COMMENTDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentDatabaseInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
void CommentDatabaseInternal::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_COMMENTDB);
|
uint4 elemId = decoder.openElement(ELEM_COMMENTDB);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Comment com;
|
Comment com;
|
||||||
com.decode(decoder,manage);
|
com.decode(decoder);
|
||||||
addComment(com.getType(),com.getFuncAddr(),com.getAddr(),com.getText());
|
addComment(com.getType(),com.getFuncAddr(),com.getAddr(),com.getText());
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index
|
int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index
|
||||||
const string &getText(void) const { return text; } ///< Get the body of the comment
|
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 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 uint4 encodeCommentType(const string &name); ///< Convert name string to comment property
|
||||||
static string decodeCommentType(uint4 val); ///< Convert comment property to string
|
static string decodeCommentType(uint4 val); ///< Convert comment property to string
|
||||||
};
|
};
|
||||||
|
@ -147,8 +147,7 @@ public:
|
||||||
/// \brief Restore all comments from a \<commentdb> element
|
/// \brief Restore all comments from a \<commentdb> element
|
||||||
///
|
///
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is a manager for resolving address space references
|
virtual void decode(Decoder &decoder)=0;
|
||||||
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,7 +170,7 @@ public:
|
||||||
virtual CommentSet::const_iterator beginComment(const Address &fad) const;
|
virtual CommentSet::const_iterator beginComment(const Address &fad) const;
|
||||||
virtual CommentSet::const_iterator endComment(const Address &fad) const;
|
virtual CommentSet::const_iterator endComment(const Address &fad) const;
|
||||||
virtual void encode(Encoder &encoder) 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
|
/// \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);
|
iter = cache.beginComment(fad);
|
||||||
iterend = cache.endComment(fad);
|
iterend = cache.endComment(fad);
|
||||||
|
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
if (ghidra->getComments(fad,commentfilter,decoder)) {
|
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 CommentSet::const_iterator endComment(const Address &fad) const;
|
||||||
virtual void encode(Encoder &encoder) const {
|
virtual void encode(Encoder &encoder) const {
|
||||||
throw LowlevelError("commentdb::encode unimplemented"); }
|
throw LowlevelError("commentdb::encode unimplemented"); }
|
||||||
virtual void decode(Decoder &decoder,const AddrSpaceManager *trans) {
|
virtual void decode(Decoder &decoder) {
|
||||||
throw LowlevelError("CommentDatabaseGhidra::decode unimplemented"); }
|
throw LowlevelError("CommentDatabaseGhidra::decode unimplemented"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ const CPoolRecord *ConstantPoolGhidra::getRecord(const vector<uintb> &refs) cons
|
||||||
{
|
{
|
||||||
const CPoolRecord *rec = cache.getRecord(refs);
|
const CPoolRecord *rec = cache.getRecord(refs);
|
||||||
if (rec == (const CPoolRecord *)0) {
|
if (rec == (const CPoolRecord *)0) {
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
bool success;
|
bool success;
|
||||||
try {
|
try {
|
||||||
success = ghidra->getCPoolRef(refs,decoder);
|
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
|
/// if the symbol is dynamic. Then parse the \b uselimit describing the valid
|
||||||
/// range of code addresses.
|
/// range of code addresses.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is an address space manager for constructing Address objects
|
|
||||||
/// \return the advanced iterator
|
/// \return the advanced iterator
|
||||||
void SymbolEntry::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
void SymbolEntry::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.peekElement();
|
uint4 elemId = decoder.peekElement();
|
||||||
|
@ -224,10 +223,10 @@ void SymbolEntry::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr = Address::decode(decoder,manage);
|
addr = Address::decode(decoder);
|
||||||
hash = 0;
|
hash = 0;
|
||||||
}
|
}
|
||||||
uselimit.decode(decoder,manage);
|
uselimit.decode(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Examine the data-type to decide if the Symbol has the special property
|
/// 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
|
if (attribId == ATTRIB_NAME) // Unless we see it explicitly
|
||||||
name = decoder.readString();
|
name = decoder.readString();
|
||||||
}
|
}
|
||||||
refaddr = Address::decode(decoder,scope->getArch());
|
refaddr = Address::decode(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
buildNameType();
|
buildNameType();
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1582,7 @@ Symbol *Scope::addMapSym(Decoder &decoder)
|
||||||
addSymbolInternal(sym); // This routine may throw, but it will delete sym in this case
|
addSymbolInternal(sym); // This routine may throw, but it will delete sym in this case
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
SymbolEntry entry(sym);
|
SymbolEntry entry(sym);
|
||||||
entry.decode(decoder,glb);
|
entry.decode(decoder);
|
||||||
if (entry.isInvalid()) {
|
if (entry.isInvalid()) {
|
||||||
glb->printMessage("WARNING: Throwing out symbol with invalid mapping: "+sym->getName());
|
glb->printMessage("WARNING: Throwing out symbol with invalid mapping: "+sym->getName());
|
||||||
removeSymbol(sym);
|
removeSymbol(sym);
|
||||||
|
@ -2632,7 +2631,7 @@ void ScopeInternal::decodeHole(Decoder &decoder)
|
||||||
uint4 elemId = decoder.openElement(ELEM_HOLE);
|
uint4 elemId = decoder.openElement(ELEM_HOLE);
|
||||||
uint4 flags = 0;
|
uint4 flags = 0;
|
||||||
Range range;
|
Range range;
|
||||||
range.decodeFromAttributes(decoder, glb);
|
range.decodeFromAttributes(decoder);
|
||||||
decoder.rewindAttributes();
|
decoder.rewindAttributes();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
@ -2717,7 +2716,7 @@ void ScopeInternal::decode(Decoder &decoder)
|
||||||
}
|
}
|
||||||
if (subId== ELEM_RANGELIST) {
|
if (subId== ELEM_RANGELIST) {
|
||||||
RangeList newrangetree;
|
RangeList newrangetree;
|
||||||
newrangetree.decode(decoder,glb);
|
newrangetree.decode(decoder);
|
||||||
glb->symboltab->setRange(this,newrangetree);
|
glb->symboltab->setRange(this,newrangetree);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_RANGEEQUALSSYMBOLS) {
|
else if (subId == ELEM_RANGEEQUALSSYMBOLS) {
|
||||||
|
@ -3262,7 +3261,7 @@ void Database::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
uint4 val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
uint4 val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
vData.decodeFromAttributes(decoder, glb);
|
vData.decodeFromAttributes(decoder);
|
||||||
Address addr = vData.getAddr();
|
Address addr = vData.getAddr();
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
flagbase.split(addr) = val;
|
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
|
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 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 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
|
typedef rangemap<SymbolEntry> EntryMap; ///< A rangemap of SymbolEntry
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ Scope *ScopeGhidra::reresolveScope(uint8 id) const
|
||||||
if (cacheScope != (Scope *)0)
|
if (cacheScope != (Scope *)0)
|
||||||
return cacheScope; // Scope was previously cached
|
return cacheScope; // Scope was previously cached
|
||||||
|
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
if (!ghidra->getNamespacePath(id,decoder))
|
if (!ghidra->getNamespacePath(id,decoder))
|
||||||
throw LowlevelError("Could not get namespace info");
|
throw LowlevelError("Could not get namespace info");
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ void ScopeGhidra::decodeHole(Decoder &decoder) const
|
||||||
uint4 elemId = decoder.openElement(ELEM_HOLE);
|
uint4 elemId = decoder.openElement(ELEM_HOLE);
|
||||||
uint4 flags = 0;
|
uint4 flags = 0;
|
||||||
Range range;
|
Range range;
|
||||||
range.decodeFromAttributes(decoder,ghidra);
|
range.decodeFromAttributes(decoder);
|
||||||
decoder.rewindAttributes();
|
decoder.rewindAttributes();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
@ -212,7 +212,7 @@ Symbol *ScopeGhidra::removeQuery(const Address &addr) const
|
||||||
|
|
||||||
// Have we queried this address before
|
// Have we queried this address before
|
||||||
if (holes.inRange(addr,1)) return (Symbol *)0;
|
if (holes.inRange(addr,1)) return (Symbol *)0;
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
if (ghidra->getMappedSymbolsXML(addr,decoder)) { // Query GHIDRA about this address
|
if (ghidra->getMappedSymbolsXML(addr,decoder)) { // Query GHIDRA about this address
|
||||||
sym = dump2Cache(decoder); // Add it to the cache
|
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
|
// If the function isn't in cache, we use the special
|
||||||
// getExternalRefXML interface to recover the external function
|
// getExternalRefXML interface to recover the external function
|
||||||
SymbolEntry *entry = sym->getFirstWholeMap();
|
SymbolEntry *entry = sym->getFirstWholeMap();
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
if (ghidra->getExternalRefXML(entry->getAddr(),decoder)) {
|
if (ghidra->getExternalRefXML(entry->getAddr(),decoder)) {
|
||||||
FunctionSymbol *funcSym;
|
FunctionSymbol *funcSym;
|
||||||
// Make sure referenced function is cached
|
// 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
|
/// \brief Decode a \<pentry> element into \b this object
|
||||||
///
|
///
|
||||||
/// \param decoder is the stream decoder
|
/// \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 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 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
|
/// \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;
|
flags = 0;
|
||||||
|
@ -499,7 +498,7 @@ void ParamEntry::decode(Decoder &decoder,const AddrSpaceManager *manage,bool nor
|
||||||
if (alignment == size)
|
if (alignment == size)
|
||||||
alignment = 0;
|
alignment = 0;
|
||||||
Address addr;
|
Address addr;
|
||||||
addr = Address::decode(decoder,manage);
|
addr = Address::decode(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
spaceid = addr.getSpace();
|
spaceid = addr.getSpace();
|
||||||
addressbase = addr.getOffset();
|
addressbase = addr.getOffset();
|
||||||
|
@ -1107,18 +1106,17 @@ void ParamListStandard::populateResolver(void)
|
||||||
/// \brief Parse a \<pentry> element and add it to \b this list
|
/// \brief Parse a \<pentry> element and add it to \b this list
|
||||||
///
|
///
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is manager for parsing address spaces
|
|
||||||
/// \param effectlist holds any passed back effect records
|
/// \param effectlist holds any passed back effect records
|
||||||
/// \param groupid is the group to which the new ParamEntry is assigned
|
/// \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 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 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 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
|
/// \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)
|
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped)
|
||||||
{
|
{
|
||||||
entry.emplace_back(groupid);
|
entry.emplace_back(groupid);
|
||||||
entry.back().decode(decoder,manage,normalstack,grouped,entry);
|
entry.back().decode(decoder,normalstack,grouped,entry);
|
||||||
if (splitFloat) {
|
if (splitFloat) {
|
||||||
if (!grouped && entry.back().getType() == TYPE_FLOAT) {
|
if (!grouped && entry.back().getType() == TYPE_FLOAT) {
|
||||||
if (resourceTwoStart >= 0)
|
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.
|
/// All ParamEntry objects will share the same \b group id.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is manager for parsing address spaces
|
|
||||||
/// \param effectlist holds any passed back effect records
|
/// \param effectlist holds any passed back effect records
|
||||||
/// \param groupid is the group to which all ParamEntry elements are assigned
|
/// \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 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 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 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 groupid,bool normalstack,bool autokill,bool splitFloat)
|
||||||
{
|
{
|
||||||
int4 basegroup = numgroup;
|
int4 basegroup = numgroup;
|
||||||
|
@ -1156,7 +1153,7 @@ void ParamListStandard::parseGroup(Decoder &decoder,const AddrSpaceManager *mana
|
||||||
ParamEntry *previous2 = (ParamEntry *)0;
|
ParamEntry *previous2 = (ParamEntry *)0;
|
||||||
uint4 elemId = decoder.openElement(ELEM_GROUP);
|
uint4 elemId = decoder.openElement(ELEM_GROUP);
|
||||||
while(decoder.peekElement() != 0) {
|
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() );
|
ParamEntry &pentry( entry.back() );
|
||||||
if (pentry.getSpace()->getType() == IPTR_JOIN)
|
if (pentry.getSpace()->getType() == IPTR_JOIN)
|
||||||
throw LowlevelError("<pentry> in the join space not allowed in <group> tag");
|
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,
|
void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack)
|
||||||
vector<EffectRecord> &effectlist,bool normalstack)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
numgroup = 0;
|
numgroup = 0;
|
||||||
|
@ -1362,10 +1358,10 @@ void ParamListStandard::decode(Decoder &decoder,const AddrSpaceManager *manage,
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_PENTRY) {
|
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) {
|
else if (subId == ELEM_GROUP) {
|
||||||
parseGroup(decoder, manage, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
|
parseGroup(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
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
|
// Check for double precision entries
|
||||||
list<ParamEntry>::iterator iter;
|
list<ParamEntry>::iterator iter;
|
||||||
ParamEntry *previous1 = (ParamEntry *)0;
|
ParamEntry *previous1 = (ParamEntry *)0;
|
||||||
|
@ -1901,7 +1897,7 @@ void FspecSpace::encodeAttributes(Encoder &encoder,uintb offset) const
|
||||||
encoder.writeString(ATTRIB_SPACE, "fspec");
|
encoder.writeString(ATTRIB_SPACE, "fspec");
|
||||||
else {
|
else {
|
||||||
AddrSpace *id = fc->getEntryAddress().getSpace();
|
AddrSpace *id = fc->getEntryAddress().getSpace();
|
||||||
encoder.writeString(ATTRIB_SPACE, id->getName());
|
encoder.writeSpace(ATTRIB_SPACE, id);
|
||||||
encoder.writeUnsignedInteger(ATTRIB_OFFSET, fc->getEntryAddress().getOffset());
|
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");
|
encoder.writeString(ATTRIB_SPACE, "fspec");
|
||||||
else {
|
else {
|
||||||
AddrSpace *id = fc->getEntryAddress().getSpace();
|
AddrSpace *id = fc->getEntryAddress().getSpace();
|
||||||
encoder.writeString(ATTRIB_SPACE, id->getName());
|
encoder.writeSpace(ATTRIB_SPACE, id);
|
||||||
encoder.writeUnsignedInteger(ATTRIB_OFFSET, fc->getEntryAddress().getOffset());
|
encoder.writeUnsignedInteger(ATTRIB_OFFSET, fc->getEntryAddress().getOffset());
|
||||||
encoder.writeSignedInteger(ATTRIB_SIZE, size);
|
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.
|
/// 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 grouptype is the effect inherited from the parent
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is a manager to resolve address space references
|
void EffectRecord::decode(uint4 grouptype,Decoder &decoder)
|
||||||
void EffectRecord::decode(uint4 grouptype,Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
type = grouptype;
|
type = grouptype;
|
||||||
range.decode(decoder,manage);
|
range.decode(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoModel::defaultLocalRange(void)
|
void ProtoModel::defaultLocalRange(void)
|
||||||
|
@ -2333,7 +2328,7 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_INPUT) {
|
if (subId == ELEM_INPUT) {
|
||||||
input->decode(decoder,glb,effectlist,stackgrowsnegative);
|
input->decode(decoder,effectlist,stackgrowsnegative);
|
||||||
if (stackspc != (AddrSpace *)0) {
|
if (stackspc != (AddrSpace *)0) {
|
||||||
input->getRangeList(stackspc,paramrange);
|
input->getRangeList(stackspc,paramrange);
|
||||||
if (!paramrange.empty())
|
if (!paramrange.empty())
|
||||||
|
@ -2341,13 +2336,13 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_OUTPUT) {
|
else if (subId == ELEM_OUTPUT) {
|
||||||
output->decode(decoder,glb,effectlist,stackgrowsnegative);
|
output->decode(decoder,effectlist,stackgrowsnegative);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_UNAFFECTED) {
|
else if (subId == ELEM_UNAFFECTED) {
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::unaffected,decoder,glb);
|
effectlist.back().decode(EffectRecord::unaffected,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
@ -2355,7 +2350,7 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::killedbycall,decoder,glb);
|
effectlist.back().decode(EffectRecord::killedbycall,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
@ -2363,7 +2358,7 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::return_address,decoder,glb);
|
effectlist.back().decode(EffectRecord::return_address,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
sawretaddr = true;
|
sawretaddr = true;
|
||||||
|
@ -2373,7 +2368,7 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,glb);
|
range.decode(decoder);
|
||||||
localrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
localrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
|
@ -2383,7 +2378,7 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
Range range;
|
Range range;
|
||||||
range.decode(decoder,glb);
|
range.decode(decoder);
|
||||||
paramrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
paramrange.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
|
@ -2392,13 +2387,13 @@ void ProtoModel::decode(Decoder &decoder)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
likelytrash.emplace_back();
|
likelytrash.emplace_back();
|
||||||
likelytrash.back().decode(decoder,glb);
|
likelytrash.back().decode(decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_PCODE) {
|
else if (subId == ELEM_PCODE) {
|
||||||
int4 injectId = glb->pcodeinjectlib->decodeInject("Protomodel : "+name, name,
|
int4 injectId = glb->pcodeinjectlib->decodeInject("Protomodel : "+name, name,
|
||||||
InjectPayload::CALLMECHANISM_TYPE,decoder);
|
InjectPayload::CALLMECHANISM_TYPE,decoder);
|
||||||
InjectPayload *payload = glb->pcodeinjectlib->getPayload(injectId);
|
InjectPayload *payload = glb->pcodeinjectlib->getPayload(injectId);
|
||||||
if (payload->getName().find("uponentry") != string::npos)
|
if (payload->getName().find("uponentry") != string::npos)
|
||||||
injectUponEntry = injectId;
|
injectUponEntry = injectId;
|
||||||
|
@ -3219,7 +3214,7 @@ void ProtoStoreInternal::decode(Decoder &decoder,ProtoModel *model)
|
||||||
namelist.push_back(name);
|
namelist.push_back(name);
|
||||||
pieces.emplace_back();
|
pieces.emplace_back();
|
||||||
ParameterPieces &curparam( pieces.back() );
|
ParameterPieces &curparam( pieces.back() );
|
||||||
curparam.addr = Address::decode(decoder,glb);
|
curparam.addr = Address::decode(decoder);
|
||||||
curparam.type = glb->types->decodeType(decoder);
|
curparam.type = glb->types->decodeType(decoder);
|
||||||
curparam.flags = flags;
|
curparam.flags = flags;
|
||||||
if (curparam.addr.isInvalid())
|
if (curparam.addr.isInvalid())
|
||||||
|
@ -4422,14 +4417,14 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
||||||
outputlock = decoder.readBool();
|
outputlock = decoder.readBool();
|
||||||
}
|
}
|
||||||
int4 tmpsize;
|
int4 tmpsize;
|
||||||
outpieces.addr = Address::decode(decoder,glb,tmpsize);
|
outpieces.addr = Address::decode(decoder,tmpsize);
|
||||||
outpieces.type = glb->types->decodeType(decoder);
|
outpieces.type = glb->types->decodeType(decoder);
|
||||||
outpieces.flags = 0;
|
outpieces.flags = 0;
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_ADDR) { // Old-style specification of return (supported partially for backward compat)
|
else if (subId == ELEM_ADDR) { // Old-style specification of return (supported partially for backward compat)
|
||||||
int4 tmpsize;
|
int4 tmpsize;
|
||||||
outpieces.addr = Address::decode(decoder,glb,tmpsize);
|
outpieces.addr = Address::decode(decoder,tmpsize);
|
||||||
outpieces.type = glb->types->decodeType(decoder);
|
outpieces.type = glb->types->decodeType(decoder);
|
||||||
outpieces.flags = 0;
|
outpieces.flags = 0;
|
||||||
}
|
}
|
||||||
|
@ -4452,7 +4447,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::unaffected,decoder,glb);
|
effectlist.back().decode(EffectRecord::unaffected,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
@ -4460,7 +4455,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::killedbycall,decoder,glb);
|
effectlist.back().decode(EffectRecord::killedbycall,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
@ -4468,7 +4463,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
effectlist.emplace_back();
|
effectlist.emplace_back();
|
||||||
effectlist.back().decode(EffectRecord::return_address,decoder,glb);
|
effectlist.back().decode(EffectRecord::return_address,decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
@ -4476,7 +4471,7 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
likelytrash.emplace_back();
|
likelytrash.emplace_back();
|
||||||
likelytrash.back().decode(decoder,glb);
|
likelytrash.back().decode(decoder);
|
||||||
}
|
}
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public:
|
||||||
AddrSpace *getSpace(void) const { return spaceid; } ///< Get the address space containing \b this entry
|
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
|
uintb getBase(void) const { return addressbase; } ///< Get the starting offset of \b this entry
|
||||||
Address getAddrBySlot(int4 &slot,int4 sz) const;
|
Address getAddrBySlot(int4 &slot,int4 sz) 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 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
|
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
|
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; ///< Equality operator
|
||||||
bool operator!=(const EffectRecord &op2) const; ///< Inequality operator
|
bool operator!=(const EffectRecord &op2) const; ///< Inequality operator
|
||||||
void encode(Encoder &encoder) const; ///< Encode the record to a stream
|
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);
|
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
|
/// \brief Restore the model from an \<input> or \<output> element in the stream
|
||||||
///
|
///
|
||||||
/// \param decoder is the stream decoder
|
/// \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 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
|
/// \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
|
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 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 addResolverRange(AddrSpace *spc,uintb first,uintb last,ParamEntry *paramEntry,int4 position);
|
||||||
void populateResolver(void); ///< Build the ParamEntry resolver maps
|
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);
|
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);
|
int4 groupid,bool normalstack,bool autokill,bool splitFloat);
|
||||||
public:
|
public:
|
||||||
ParamListStandard(void) {} ///< Construct for use with decode()
|
ParamListStandard(void) {} ///< Construct for use with decode()
|
||||||
|
@ -594,7 +593,7 @@ public:
|
||||||
virtual AddrSpace *getSpacebase(void) const { return spacebase; }
|
virtual AddrSpace *getSpacebase(void) const { return spacebase; }
|
||||||
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
|
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
|
||||||
virtual int4 getMaxDelay(void) const { return maxdelay; }
|
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;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -646,7 +645,7 @@ public:
|
||||||
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListRegisterOut(op2) {} ///< Copy constructor
|
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListRegisterOut(op2) {} ///< Copy constructor
|
||||||
virtual uint4 getType(void) const { return p_standard_out; }
|
virtual uint4 getType(void) const { return p_standard_out; }
|
||||||
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
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;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -735,7 +735,7 @@ uint8 Funcdata::decode(Decoder &decoder)
|
||||||
throw LowlevelError("Missing function name");
|
throw LowlevelError("Missing function name");
|
||||||
if (size == -1)
|
if (size == -1)
|
||||||
throw LowlevelError("Missing function size");
|
throw LowlevelError("Missing function size");
|
||||||
baseaddr = Address::decode( decoder, glb );
|
baseaddr = Address::decode( decoder );
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
|
|
|
@ -343,7 +343,7 @@ void ArchitectureGhidra::buildTypegrp(DocumentStorage &store)
|
||||||
const Element *el = store.getTag("coretypes");
|
const Element *el = store.getTag("coretypes");
|
||||||
types = new TypeFactoryGhidra(this);
|
types = new TypeFactoryGhidra(this);
|
||||||
if (el != (const Element *)0) {
|
if (el != (const Element *)0) {
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
types->decodeCoreTypes(decoder);
|
types->decodeCoreTypes(decoder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -864,7 +864,7 @@ ArchitectureGhidra::ArchitectureGhidra(const string &pspec,const string &cspec,c
|
||||||
: Architecture(), sin(i), sout(o), encoder(sout)
|
: Architecture(), sin(i), sout(o), encoder(sout)
|
||||||
|
|
||||||
{
|
{
|
||||||
print->setXML(true);
|
print->setMarkup(true);
|
||||||
print->setOutputStream(&sout);
|
print->setOutputStream(&sout);
|
||||||
pspecxml = pspec;
|
pspecxml = pspec;
|
||||||
cspecxml = cspec;
|
cspecxml = cspec;
|
||||||
|
|
|
@ -19,22 +19,22 @@ const TrackedSet &ContextGhidra::getTrackedSet(const Address &addr) const
|
||||||
|
|
||||||
{
|
{
|
||||||
cache.clear();
|
cache.clear();
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(glb);
|
||||||
((ArchitectureGhidra *)glb)->getTrackedRegisters(addr,decoder);
|
glb->getTrackedRegisters(addr,decoder);
|
||||||
|
|
||||||
uint4 elemId = decoder.openElement(ELEM_TRACKED_POINTSET);
|
uint4 elemId = decoder.openElement(ELEM_TRACKED_POINTSET);
|
||||||
decodeTracked(decoder,glb,cache);
|
decodeTracked(decoder,cache);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextGhidra::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
void ContextGhidra::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
decoder.skipElement(); // Ignore details handled by ghidra
|
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
|
decoder.skipElement(); // Ignore details handled by ghidra
|
||||||
|
|
|
@ -51,8 +51,8 @@ public:
|
||||||
virtual const TrackedSet &getTrackedSet(const Address &addr) const;
|
virtual const TrackedSet &getTrackedSet(const Address &addr) const;
|
||||||
|
|
||||||
// Ignored routines (taken care of by GHIDRA)
|
// Ignored routines (taken care of by GHIDRA)
|
||||||
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
|
virtual void decodeFromSpec(Decoder &decoder);
|
||||||
|
|
||||||
// Unimplemented routines (should never be called)
|
// Unimplemented routines (should never be called)
|
||||||
virtual int getContextSize(void) const {
|
virtual int getContextSize(void) const {
|
||||||
|
|
|
@ -47,15 +47,15 @@ void connect_to_console(Funcdata *fd)
|
||||||
decomp_data->fd = fd;
|
decomp_data->fd = fd;
|
||||||
decomp_data->conf = fd->getArch();
|
decomp_data->conf = fd->getArch();
|
||||||
ostream *oldPrintStream = decomp_data->conf->print->getOutputStream();
|
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->setDebugStream(remote->getOutputStream());
|
||||||
decomp_data->conf->print->setOutputStream(remote->getOutputStream());
|
decomp_data->conf->print->setOutputStream(remote->getOutputStream());
|
||||||
decomp_data->conf->print->setXML(false);
|
decomp_data->conf->print->setMarkup(false);
|
||||||
ghidra_dcp->reset();
|
ghidra_dcp->reset();
|
||||||
mainloop(ghidra_dcp);
|
mainloop(ghidra_dcp);
|
||||||
decomp_data->conf->clearAnalysis(fd);
|
decomp_data->conf->clearAnalysis(fd);
|
||||||
decomp_data->conf->print->setOutputStream(oldPrintStream);
|
decomp_data->conf->print->setOutputStream(oldPrintStream);
|
||||||
decomp_data->conf->print->setXML(emitXml);
|
decomp_data->conf->print->setMarkup(emitMarkup);
|
||||||
fd->debugDisable();
|
fd->debugDisable();
|
||||||
decomp_data->conf->allacts.getCurrent()->clearBreakPoints();
|
decomp_data->conf->allacts.getCurrent()->clearBreakPoints();
|
||||||
}
|
}
|
||||||
|
@ -274,9 +274,9 @@ void DecompileAt::loadParameters(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
ArchitectureGhidra::readStream(sin,decoder); // Read encoded address directly from in stream
|
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)
|
void DecompileAt::rawAction(void)
|
||||||
|
@ -328,9 +328,9 @@ void StructureGraph::loadParameters(void)
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
|
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
ArchitectureGhidra::readStream(sin,decoder);
|
ArchitectureGhidra::readStream(sin,decoder);
|
||||||
ingraph.decode(decoder,ghidra);
|
ingraph.decode(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StructureGraph::rawAction(void)
|
void StructureGraph::rawAction(void)
|
||||||
|
@ -408,8 +408,8 @@ void SetOptions::loadParameters(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
decoder.clear();
|
optionsListTag.clear();
|
||||||
ArchitectureGhidra::readStream(sin,decoder);
|
ArchitectureGhidra::readStringStream(sin, optionsListTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOptions::rawAction(void)
|
void SetOptions::rawAction(void)
|
||||||
|
@ -418,8 +418,12 @@ void SetOptions::rawAction(void)
|
||||||
res = false;
|
res = false;
|
||||||
|
|
||||||
ghidra->resetDefaults();
|
ghidra->resetDefaults();
|
||||||
|
DocumentStorage storage;
|
||||||
|
istringstream s(optionsListTag);
|
||||||
|
Document *doc = storage.parseDocument(s);
|
||||||
|
XmlDecode decoder(ghidra,doc->getRoot());
|
||||||
ghidra->options->decode(decoder);
|
ghidra->options->decode(decoder);
|
||||||
decoder.clear();
|
optionsListTag.clear();
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ public:
|
||||||
/// The command returns a single character message, 't' or 'f', indicating whether the
|
/// The command returns a single character message, 't' or 'f', indicating whether the
|
||||||
/// configuration succeeded.
|
/// configuration succeeded.
|
||||||
class SetOptions : public GhidraCommand {
|
class SetOptions : public GhidraCommand {
|
||||||
XmlDecode decoder; ///< The XML option document
|
string optionsListTag; ///< The <optionslist> XML tag
|
||||||
virtual void loadParameters(void);
|
virtual void loadParameters(void);
|
||||||
virtual void sendResult(void);
|
virtual void sendResult(void);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,7 +36,7 @@ void GhidraTranslate::initialize(DocumentStorage &store)
|
||||||
const Element *el = store.getTag("sleigh");
|
const Element *el = store.getTag("sleigh");
|
||||||
if (el == (const Element *)0)
|
if (el == (const Element *)0)
|
||||||
throw LowlevelError("Could not find ghidra sleigh tag");
|
throw LowlevelError("Could not find ghidra sleigh tag");
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(this,el);
|
||||||
decode(decoder);
|
decode(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
||||||
map<string,VarnodeData>::const_iterator iter = nm2addr.find(nm);
|
map<string,VarnodeData>::const_iterator iter = nm2addr.find(nm);
|
||||||
if (iter != nm2addr.end())
|
if (iter != nm2addr.end())
|
||||||
return (*iter).second;
|
return (*iter).second;
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(glb);
|
||||||
try {
|
try {
|
||||||
if (!glb->getRegister(nm,decoder)) // Ask Ghidra client about the register
|
if (!glb->getRegister(nm,decoder)) // Ask Ghidra client about the register
|
||||||
throw LowlevelError("No register named "+nm);
|
throw LowlevelError("No register named "+nm);
|
||||||
|
@ -59,7 +59,7 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
||||||
}
|
}
|
||||||
Address regaddr;
|
Address regaddr;
|
||||||
int4 regsize;
|
int4 regsize;
|
||||||
regaddr = Address::decode( decoder, this, regsize);
|
regaddr = Address::decode( decoder, regsize);
|
||||||
VarnodeData vndata;
|
VarnodeData vndata;
|
||||||
vndata.space = regaddr.getSpace();
|
vndata.space = regaddr.getSpace();
|
||||||
vndata.offset = regaddr.getOffset();
|
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.
|
/// Parse a \<set> element to fill in the storage and value details.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the manager used to decode address references
|
void TrackedContext::decode(Decoder &decoder)
|
||||||
void TrackedContext::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_SET);
|
uint4 elemId = decoder.openElement(ELEM_SET);
|
||||||
loc.decodeFromAttributes(decoder, manage);
|
loc.decodeFromAttributes(decoder);
|
||||||
|
|
||||||
val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||||
decoder.closeElement(elemId);
|
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
|
/// Parse a \<tracked_pointset> element, decoding each child in turn to populate a list of
|
||||||
/// TrackedContext objects.
|
/// TrackedContext objects.
|
||||||
/// \param decoder is the given stream decoder
|
/// \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
|
/// \param vec is the container that will hold the new TrackedContext objects
|
||||||
void ContextDatabase::decodeTracked(Decoder &decoder,const AddrSpaceManager *manage,
|
void ContextDatabase::decodeTracked(Decoder &decoder,TrackedSet &vec)
|
||||||
TrackedSet &vec)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
vec.clear(); // Clear out any old stuff
|
vec.clear(); // Clear out any old stuff
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
vec.emplace_back();
|
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);
|
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);
|
uint4 elemId = decoder.openElement(ELEM_CONTEXT_POINTS);
|
||||||
|
@ -513,14 +510,14 @@ void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
vData.decodeFromAttributes(decoder, manage);
|
vData.decodeFromAttributes(decoder);
|
||||||
decodeContext(decoder,vData.getAddr(),Address());
|
decodeContext(decoder,vData.getAddr(),Address());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_TRACKED_POINTSET) {
|
else if (subId == ELEM_TRACKED_POINTSET) {
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
vData.decodeFromAttributes(decoder, manage);
|
vData.decodeFromAttributes(decoder);
|
||||||
decodeTracked(decoder,manage,trackbase.split(vData.getAddr()) );
|
decodeTracked(decoder,trackbase.split(vData.getAddr()) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Bad <context_points> tag");
|
throw LowlevelError("Bad <context_points> tag");
|
||||||
|
@ -529,7 +526,7 @@ void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextInternal::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)
|
void ContextInternal::decodeFromSpec(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_CONTEXT_DATA);
|
uint4 elemId = decoder.openElement(ELEM_CONTEXT_DATA);
|
||||||
|
@ -537,14 +534,14 @@ void ContextInternal::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *ma
|
||||||
uint4 subId = decoder.openElement();
|
uint4 subId = decoder.openElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
Range range;
|
Range range;
|
||||||
range.decodeFromAttributes(decoder, manage); // There MUST be a range
|
range.decodeFromAttributes(decoder); // There MUST be a range
|
||||||
Address addr1 = range.getFirstAddr();
|
Address addr1 = range.getFirstAddr();
|
||||||
Address addr2 = range.getLastAddrOpen(manage);
|
Address addr2 = range.getLastAddrOpen(decoder.getAddrSpaceManager());
|
||||||
if (subId == ELEM_CONTEXT_SET) {
|
if (subId == ELEM_CONTEXT_SET) {
|
||||||
decodeContext(decoder,addr1,addr2);
|
decodeContext(decoder,addr1,addr2);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_TRACKED_SET) {
|
else if (subId == ELEM_TRACKED_SET) {
|
||||||
decodeTracked(decoder,manage,createSet(addr1,addr2));
|
decodeTracked(decoder,createSet(addr1,addr2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Bad <context_data> tag");
|
throw LowlevelError("Bad <context_data> tag");
|
||||||
|
|
|
@ -76,8 +76,8 @@ public:
|
||||||
struct TrackedContext {
|
struct TrackedContext {
|
||||||
VarnodeData loc; ///< Storage details of the register being tracked
|
VarnodeData loc; ///< Storage details of the register being tracked
|
||||||
uintb val; ///< The value of the register
|
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
|
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)
|
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 {
|
class ContextDatabase {
|
||||||
protected:
|
protected:
|
||||||
static void encodeTracked(Encoder &encoder,const Address &addr,const TrackedSet &vec);
|
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
|
/// \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
|
/// \brief Restore the state of \b this database object from the given stream decoder
|
||||||
///
|
///
|
||||||
/// \param decoder is 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)=0;
|
||||||
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
|
|
||||||
|
|
||||||
/// \brief Add initial context state from elements in the compiler/processor specifications
|
/// \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
|
/// Parse a \<context_data> element from the given stream decoder from either the compiler
|
||||||
/// or processor specification file for the architecture, initializing this database.
|
/// or processor specification file for the architecture, initializing this database.
|
||||||
/// \param decoder is the given stream decoder
|
/// \param decoder is the given stream decoder
|
||||||
/// \param manage is used to resolve address space references
|
virtual void decodeFromSpec(Decoder &decoder)=0;
|
||||||
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)=0;
|
|
||||||
|
|
||||||
void setVariableDefault(const string &nm,uintm val); ///< Provide a default value for a context variable
|
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
|
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 TrackedSet &createSet(const Address &addr1,const Address &addr2);
|
||||||
|
|
||||||
virtual void encode(Encoder &encoder) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
|
virtual void decodeFromSpec(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A helper class for caching the active context blob to minimize database lookups
|
/// \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");
|
throw IfaceExecutionError("No function selected");
|
||||||
|
|
||||||
dcp->conf->print->setOutputStream(status->fileoptr);
|
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->docFunction(dcp->fd);
|
||||||
dcp->conf->print->setXML(false);
|
dcp->conf->print->setMarkup(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \class IfcPrintCStruct
|
/// \class IfcPrintCStruct
|
||||||
|
@ -2724,7 +2724,7 @@ void IfcCallGraphLoad::execute(istream &s)
|
||||||
Document *doc = store.parseDocument(is);
|
Document *doc = store.parseDocument(is);
|
||||||
|
|
||||||
dcp->allocateCallGraph();
|
dcp->allocateCallGraph();
|
||||||
XmlDecode decoder(doc->getRoot());
|
XmlDecode decoder(dcp->conf,doc->getRoot());
|
||||||
dcp->cgraph->decoder(decoder);
|
dcp->cgraph->decoder(decoder);
|
||||||
*status->optr << "Successfully read in callgraph" << endl;
|
*status->optr << "Successfully read in callgraph" << endl;
|
||||||
|
|
||||||
|
@ -3016,8 +3016,8 @@ void IfcStructureBlocks::execute(istream &s)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BlockGraph ingraph;
|
BlockGraph ingraph;
|
||||||
XmlDecode decoder(doc->getRoot());
|
XmlDecode decoder(dcp->conf,doc->getRoot());
|
||||||
ingraph.decode(decoder,dcp->conf);
|
ingraph.decode(decoder);
|
||||||
|
|
||||||
BlockGraph resultgraph;
|
BlockGraph resultgraph;
|
||||||
vector<FlowBlock *> rootlist;
|
vector<FlowBlock *> rootlist;
|
||||||
|
|
|
@ -48,7 +48,7 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
|
|
||||||
{
|
{
|
||||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
try {
|
try {
|
||||||
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||||
|
@ -61,7 +61,7 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
}
|
}
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
while(decoder.peekElement() != 0)
|
while(decoder.peekElement() != 0)
|
||||||
emit.decodeOp(decoder,ghidra->translate);
|
emit.decodeOp(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
|
|
||||||
{
|
{
|
||||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(ghidra);
|
||||||
try {
|
try {
|
||||||
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||||
|
@ -134,7 +134,7 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
}
|
}
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
while(decoder.peekElement() != 0)
|
while(decoder.peekElement() != 0)
|
||||||
emit.decodeOp(decoder,ghidra->translate);
|
emit.decodeOp(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ InjectPayloadDynamic::~InjectPayloadDynamic(void)
|
||||||
void InjectPayloadDynamic::decodeEntry(Decoder &decoder)
|
void InjectPayloadDynamic::decodeEntry(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
Address addr = Address::decode(decoder,glb);
|
Address addr = Address::decode(decoder);
|
||||||
uint4 subId = decoder.openElement(ELEM_PAYLOAD);
|
uint4 subId = decoder.openElement(ELEM_PAYLOAD);
|
||||||
istringstream s(decoder.readString(ATTRIB_CONTENT));
|
istringstream s(decoder.readString(ATTRIB_CONTENT));
|
||||||
try {
|
try {
|
||||||
|
@ -282,10 +282,10 @@ void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
|
||||||
if (eiter == addrMap.end())
|
if (eiter == addrMap.end())
|
||||||
throw LowlevelError("Missing dynamic inject");
|
throw LowlevelError("Missing dynamic inject");
|
||||||
const Element *el = (*eiter).second->getRoot();
|
const Element *el = (*eiter).second->getRoot();
|
||||||
XmlDecode decoder(el);
|
XmlDecode decoder(glb->translate,el);
|
||||||
uint4 rootId = decoder.openElement(ELEM_INST);
|
uint4 rootId = decoder.openElement(ELEM_INST);
|
||||||
while(decoder.peekElement() != 0)
|
while(decoder.peekElement() != 0)
|
||||||
emit.decodeOp(decoder,glb->translate);
|
emit.decodeOp(decoder);
|
||||||
decoder.closeElement(rootId);
|
decoder.closeElement(rootId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,13 @@ void LoadTable::encode(Encoder &encoder) const
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param glb is the architecture for resolving address space tags
|
void LoadTable::decode(Decoder &decoder)
|
||||||
void LoadTable::decode(Decoder &decoder,Architecture *glb)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_LOADTABLE);
|
uint4 elemId = decoder.openElement(ELEM_LOADTABLE);
|
||||||
size = decoder.readSignedInteger(ATTRIB_SIZE);
|
size = decoder.readSignedInteger(ATTRIB_SIZE);
|
||||||
num = decoder.readSignedInteger(ATTRIB_NUM);
|
num = decoder.readSignedInteger(ATTRIB_NUM);
|
||||||
addr = Address::decode( decoder, glb);
|
addr = Address::decode( decoder );
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1934,7 +1933,7 @@ void JumpBasicOverride::encode(Encoder &encoder) const
|
||||||
encoder.closeElement(ELEM_BASICOVERRIDE);
|
encoder.closeElement(ELEM_BASICOVERRIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JumpBasicOverride::decode(Decoder &decoder,Architecture *glb)
|
void JumpBasicOverride::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_BASICOVERRIDE);
|
uint4 elemId = decoder.openElement(ELEM_BASICOVERRIDE);
|
||||||
|
@ -1943,12 +1942,12 @@ void JumpBasicOverride::decode(Decoder &decoder,Architecture *glb)
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_DEST) {
|
if (subId == ELEM_DEST) {
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
vData.decodeFromAttributes(decoder, glb);
|
vData.decodeFromAttributes(decoder);
|
||||||
adset.insert( vData.getAddr() );
|
adset.insert( vData.getAddr() );
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_NORMADDR) {
|
else if (subId == ELEM_NORMADDR) {
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
vData.decodeFromAttributes(decoder, glb);
|
vData.decodeFromAttributes(decoder);
|
||||||
normaddress = vData.getAddr();
|
normaddress = vData.getAddr();
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_NORMHASH) {
|
else if (subId == ELEM_NORMHASH) {
|
||||||
|
@ -2645,7 +2644,7 @@ void JumpTable::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_JUMPTABLE);
|
uint4 elemId = decoder.openElement(ELEM_JUMPTABLE);
|
||||||
opaddress = Address::decode( decoder, glb);
|
opaddress = Address::decode( decoder );
|
||||||
bool missedlabel = false;
|
bool missedlabel = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
|
@ -2667,17 +2666,17 @@ void JumpTable::decode(Decoder &decoder)
|
||||||
}
|
}
|
||||||
if (!foundlabel) // No label attribute
|
if (!foundlabel) // No label attribute
|
||||||
missedlabel = true; // No following entries are allowed to have a 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) {
|
else if (subId == ELEM_LOADTABLE) {
|
||||||
loadpoints.emplace_back();
|
loadpoints.emplace_back();
|
||||||
loadpoints.back().decode(decoder,glb);
|
loadpoints.back().decode(decoder);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_BASICOVERRIDE) {
|
else if (subId == ELEM_BASICOVERRIDE) {
|
||||||
if (jmodel != (JumpModel *)0)
|
if (jmodel != (JumpModel *)0)
|
||||||
throw LowlevelError("Duplicate jumptable override specs");
|
throw LowlevelError("Duplicate jumptable override specs");
|
||||||
jmodel = new JumpBasicOverride(this);
|
jmodel = new JumpBasicOverride(this);
|
||||||
jmodel->decode(decoder,glb);
|
jmodel->decode(decoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
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
|
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
|
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 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
|
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 JumpModel *clone(JumpTable *jt) const=0; ///< Clone \b this model
|
||||||
virtual void clear(void) {} ///< Clear any non-permanent aspects of the 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 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
|
/// \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 JumpModel *clone(JumpTable *jt) const;
|
||||||
virtual void clear(void);
|
virtual void clear(void);
|
||||||
virtual void encode(Encoder &encoder) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void decode(Decoder &decoder,Architecture *glb);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JumpAssistOp;
|
class JumpAssistOp;
|
||||||
|
|
|
@ -81,27 +81,19 @@ void LoadImageXml::open(const AddrSpaceManager *m)
|
||||||
uint4 sz; // unused size
|
uint4 sz; // unused size
|
||||||
|
|
||||||
// Read parsed xml file
|
// Read parsed xml file
|
||||||
XmlDecode decoder(rootel);
|
XmlDecode decoder(m,rootel);
|
||||||
uint4 elemId = decoder.openElement(ELEM_BINARYIMAGE);
|
uint4 elemId = decoder.openElement(ELEM_BINARYIMAGE);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 subId = decoder.openElement();
|
uint4 subId = decoder.openElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId==ELEM_SYMBOL) {
|
if (subId==ELEM_SYMBOL) {
|
||||||
AddrSpace *base = (AddrSpace *)0;
|
AddrSpace *base = decoder.readSpace(ATTRIB_SPACE);
|
||||||
string spaceName = decoder.readString(ATTRIB_SPACE);
|
|
||||||
base = manage->getSpaceByName(spaceName);
|
|
||||||
if (base == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Unknown space name: "+spaceName);
|
|
||||||
Address addr(base,base->decodeAttributes(decoder,sz));
|
Address addr(base,base->decodeAttributes(decoder,sz));
|
||||||
string nm = decoder.readString(ATTRIB_NAME);
|
string nm = decoder.readString(ATTRIB_NAME);
|
||||||
addrtosymbol[addr] = nm;
|
addrtosymbol[addr] = nm;
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_BYTECHUNK) {
|
else if (subId == ELEM_BYTECHUNK) {
|
||||||
AddrSpace *base = (AddrSpace *)0;
|
AddrSpace *base = decoder.readSpace(ATTRIB_SPACE);
|
||||||
string spaceName = decoder.readString(ATTRIB_SPACE);
|
|
||||||
base = manage->getSpaceByName(spaceName);
|
|
||||||
if (base == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Unknown space name: "+spaceName);
|
|
||||||
Address addr(base,base->decodeAttributes(decoder,sz));
|
Address addr(base,base->decodeAttributes(decoder,sz));
|
||||||
map<Address,vector<uint1> >::iterator chnkiter;
|
map<Address,vector<uint1> >::iterator chnkiter;
|
||||||
vector<uint1> &vec( chunk[addr] );
|
vector<uint1> &vec( chunk[addr] );
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "marshal.hh"
|
#include "marshal.hh"
|
||||||
#include <sstream>
|
#include "translate.hh"
|
||||||
|
|
||||||
unordered_map<string,uint4> AttributeId::lookupAttributeId;
|
unordered_map<string,uint4> AttributeId::lookupAttributeId;
|
||||||
|
|
||||||
|
@ -348,6 +348,35 @@ string XmlDecode::readString(const AttributeId &attribId)
|
||||||
return el->getAttributeValue(index);
|
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)
|
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);
|
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
|
// Common attributes. Attributes with multiple uses
|
||||||
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
|
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
|
||||||
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
|
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
|
||||||
|
@ -457,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
|
||||||
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
||||||
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
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_DATA = ElementId("data",1);
|
||||||
ElementId ELEM_INPUT = ElementId("input",2);
|
ElementId ELEM_INPUT = ElementId("input",2);
|
||||||
|
@ -470,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
|
||||||
ElementId ELEM_VALUE = ElementId("value",9);
|
ElementId ELEM_VALUE = ElementId("value",9);
|
||||||
ElementId ELEM_VOID = ElementId("void",10);
|
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
|
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
|
/// \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
|
/// 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.
|
/// 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().
|
/// This attribute will not be traversed by getNextAttribute().
|
||||||
class Decoder {
|
class Decoder {
|
||||||
|
protected:
|
||||||
|
const AddrSpaceManager *spcManager; ///< Manager for decoding address space attributes
|
||||||
public:
|
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
|
virtual ~Decoder(void) {} ///< Destructor
|
||||||
|
|
||||||
/// \brief Clear any current decoding state
|
/// \brief Clear any current decoding state
|
||||||
|
@ -215,6 +223,21 @@ public:
|
||||||
/// \return the string associated with the attribute
|
/// \return the string associated with the attribute
|
||||||
virtual string readString(const AttributeId &attribId)=0;
|
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
|
/// \brief Skip parsing of the next element
|
||||||
///
|
///
|
||||||
/// The element skipped is the one that would be opened by the next call to openElement.
|
/// 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 attribId is the given AttributeId annotation
|
||||||
/// \param val is the string to encode
|
/// \param val is the string to encode
|
||||||
virtual void writeString(const AttributeId &attribId,const string &val)=0;
|
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
|
/// \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 attributeIndex; ///< Position of \e current attribute to parse (in \e current element)
|
||||||
int4 findMatchingAttribute(const Element *el,const string &attribName);
|
int4 findMatchingAttribute(const Element *el,const string &attribName);
|
||||||
public:
|
public:
|
||||||
XmlDecode(const Element *root) { document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root
|
XmlDecode(const AddrSpaceManager *spc,const Element *root) : Decoder(spc) {
|
||||||
XmlDecode(void) { document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
|
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 ~XmlDecode(void);
|
||||||
virtual void clear(void);
|
virtual void clear(void);
|
||||||
virtual void ingestStream(istream &s);
|
virtual void ingestStream(istream &s);
|
||||||
|
@ -318,6 +350,8 @@ public:
|
||||||
virtual uintb readUnsignedInteger(const AttributeId &attribId);
|
virtual uintb readUnsignedInteger(const AttributeId &attribId);
|
||||||
virtual string readString(void);
|
virtual string readString(void);
|
||||||
virtual string readString(const AttributeId &attribId);
|
virtual string readString(const AttributeId &attribId);
|
||||||
|
virtual AddrSpace *readSpace(void);
|
||||||
|
virtual AddrSpace *readSpace(const AttributeId &attribId);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An XML based encoder
|
/// \brief An XML based encoder
|
||||||
|
@ -337,6 +371,7 @@ public:
|
||||||
virtual void writeSignedInteger(const AttributeId &attribId,intb val);
|
virtual void writeSignedInteger(const AttributeId &attribId,intb val);
|
||||||
virtual void writeUnsignedInteger(const AttributeId &attribId,uintb val);
|
virtual void writeUnsignedInteger(const AttributeId &attribId,uintb val);
|
||||||
virtual void writeString(const AttributeId &attribId,const string &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
|
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))) {
|
if ((i==0)&&((code()==CPUI_STORE)||(code()==CPUI_LOAD))) {
|
||||||
AddrSpace *spc = vn->getSpaceFromConst();
|
AddrSpace *spc = vn->getSpaceFromConst();
|
||||||
encoder.openElement(ELEM_SPACEID);
|
encoder.openElement(ELEM_SPACEID);
|
||||||
encoder.writeString(ATTRIB_NAME, spc->getName());
|
encoder.writeSpace(ATTRIB_NAME, spc);
|
||||||
encoder.closeElement(ELEM_SPACEID);
|
encoder.closeElement(ELEM_SPACEID);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -310,7 +310,7 @@ void Override::encode(Encoder &encoder,Architecture *glb) const
|
||||||
if (deadcodedelay[i] < 0) continue;
|
if (deadcodedelay[i] < 0) continue;
|
||||||
AddrSpace *spc = glb->getSpace(i);
|
AddrSpace *spc = glb->getSpace(i);
|
||||||
encoder.openElement(ELEM_DEADCODEDELAY);
|
encoder.openElement(ELEM_DEADCODEDELAY);
|
||||||
encoder.writeString(ATTRIB_SPACE, spc->getName());
|
encoder.writeSpace(ATTRIB_SPACE, spc);
|
||||||
encoder.writeSignedInteger(ATTRIB_DELAY, deadcodedelay[i]);
|
encoder.writeSignedInteger(ATTRIB_DELAY, deadcodedelay[i]);
|
||||||
encoder.closeElement(ELEM_DEADCODEDELAY);
|
encoder.closeElement(ELEM_DEADCODEDELAY);
|
||||||
}
|
}
|
||||||
|
@ -359,36 +359,36 @@ void Override::decode(Decoder &decoder,Architecture *glb)
|
||||||
uint4 subId = decoder.openElement();
|
uint4 subId = decoder.openElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_INDIRECTOVERRIDE) {
|
if (subId == ELEM_INDIRECTOVERRIDE) {
|
||||||
Address callpoint = Address::decode(decoder,glb);
|
Address callpoint = Address::decode(decoder);
|
||||||
Address directcall = Address::decode(decoder,glb);
|
Address directcall = Address::decode(decoder);
|
||||||
insertIndirectOverride(callpoint,directcall);
|
insertIndirectOverride(callpoint,directcall);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_PROTOOVERRIDE) {
|
else if (subId == ELEM_PROTOOVERRIDE) {
|
||||||
Address callpoint = Address::decode(decoder,glb);
|
Address callpoint = Address::decode(decoder);
|
||||||
FuncProto *fp = new FuncProto();
|
FuncProto *fp = new FuncProto();
|
||||||
fp->setInternal(glb->defaultfp,glb->types->getTypeVoid());
|
fp->setInternal(glb->defaultfp,glb->types->getTypeVoid());
|
||||||
fp->decode(decoder,glb);
|
fp->decode(decoder,glb);
|
||||||
insertProtoOverride(callpoint,fp);
|
insertProtoOverride(callpoint,fp);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_FORCEGOTO) {
|
else if (subId == ELEM_FORCEGOTO) {
|
||||||
Address targetpc = Address::decode(decoder,glb);
|
Address targetpc = Address::decode(decoder);
|
||||||
Address destpc = Address::decode(decoder,glb);
|
Address destpc = Address::decode(decoder);
|
||||||
insertForceGoto(targetpc,destpc);
|
insertForceGoto(targetpc,destpc);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_DEADCODEDELAY) {
|
else if (subId == ELEM_DEADCODEDELAY) {
|
||||||
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
|
int4 delay = decoder.readSignedInteger(ATTRIB_DELAY);
|
||||||
AddrSpace *spc = glb->getSpaceByName( decoder.readString(ATTRIB_SPACE));
|
AddrSpace *spc = decoder.readSpace(ATTRIB_SPACE);
|
||||||
if ((spc == (AddrSpace *)0)||(delay < 0))
|
if (delay < 0)
|
||||||
throw LowlevelError("Bad deadcodedelay tag");
|
throw LowlevelError("Bad deadcodedelay tag");
|
||||||
insertDeadcodeDelay(spc,delay);
|
insertDeadcodeDelay(spc,delay);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_MULTISTAGEJUMP) {
|
else if (subId == ELEM_MULTISTAGEJUMP) {
|
||||||
Address callpoint = Address::decode(decoder,glb);
|
Address callpoint = Address::decode(decoder);
|
||||||
insertMultistageJump(callpoint);
|
insertMultistageJump(callpoint);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_FLOW) {
|
else if (subId == ELEM_FLOW) {
|
||||||
uint4 type = stringToType(decoder.readString(ATTRIB_TYPE));
|
uint4 type = stringToType(decoder.readString(ATTRIB_TYPE));
|
||||||
Address addr = Address::decode(decoder,glb);
|
Address addr = Address::decode(decoder);
|
||||||
if ((type == Override::NONE)||(addr.isInvalid()))
|
if ((type == Override::NONE)||(addr.isInvalid()))
|
||||||
throw LowlevelError("Bad flowoverride tag");
|
throw LowlevelError("Bad flowoverride tag");
|
||||||
insertFlowOverride(addr,type);
|
insertFlowOverride(addr,type);
|
||||||
|
|
|
@ -18,19 +18,17 @@
|
||||||
|
|
||||||
/// Build this VarnodeData from an \<addr>, \<register>, or \<varnode> element.
|
/// Build this VarnodeData from an \<addr>, \<register>, or \<varnode> element.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the address space manager
|
void VarnodeData::decode(Decoder &decoder)
|
||||||
void VarnodeData::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
decodeFromAttributes(decoder,manage);
|
decodeFromAttributes(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect attributes for the VarnodeData possibly from amidst other attributes
|
/// Collect attributes for the VarnodeData possibly from amidst other attributes
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the address space manager
|
void VarnodeData::decodeFromAttributes(Decoder &decoder)
|
||||||
void VarnodeData::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
space = (AddrSpace *)0;
|
space = (AddrSpace *)0;
|
||||||
|
@ -40,16 +38,13 @@ void VarnodeData::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *
|
||||||
if (attribId == 0)
|
if (attribId == 0)
|
||||||
break; // Its possible to have no attributes in an <addr/> tag
|
break; // Its possible to have no attributes in an <addr/> tag
|
||||||
if (attribId == ATTRIB_SPACE) {
|
if (attribId == ATTRIB_SPACE) {
|
||||||
string nm = decoder.readString();
|
space = decoder.readSpace();
|
||||||
space = manage->getSpaceByName(nm);
|
|
||||||
if (space == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Unknown space name: "+nm);
|
|
||||||
decoder.rewindAttributes();
|
decoder.rewindAttributes();
|
||||||
offset = space->decodeAttributes(decoder,size);
|
offset = space->decodeAttributes(decoder,size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_NAME) {
|
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()));
|
const VarnodeData &point(trans->getRegister(decoder.readString()));
|
||||||
*this = point;
|
*this = point;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -45,10 +45,10 @@ struct VarnodeData {
|
||||||
AddrSpace *getSpaceFromConst(void) const;
|
AddrSpace *getSpaceFromConst(void) const;
|
||||||
|
|
||||||
/// Recover this object from a stream
|
/// 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
|
/// 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
|
/// Does \b this container another given VarnodeData
|
||||||
bool contains(const VarnodeData &op2) const;
|
bool contains(const VarnodeData &op2) const;
|
||||||
|
|
|
@ -16,345 +16,278 @@
|
||||||
#include "prettyprint.hh"
|
#include "prettyprint.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
const char *EmitXml::highlight[] = { "color=\"keyword\"",
|
AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",136);
|
||||||
"color=\"comment\"",
|
AttributeId ATTRIB_CLOSE = AttributeId("close",137);
|
||||||
"color=\"type\"",
|
AttributeId ATTRIB_COLOR = AttributeId("color",138);
|
||||||
"color=\"funcname\"",
|
AttributeId ATTRIB_INDENT = AttributeId("indent",139);
|
||||||
"color=\"var\"",
|
AttributeId ATTRIB_OFF = AttributeId("off",140);
|
||||||
"color=\"const\"",
|
AttributeId ATTRIB_OPEN = AttributeId("open",141);
|
||||||
"color=\"param\"",
|
AttributeId ATTRIB_OPREF = AttributeId("opref",142);
|
||||||
"color=\"global\"",
|
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);
|
||||||
|
|
||||||
/// Inform the emitter that generation of the source code document has begun
|
const string Emit::EMPTY_STRING = "";
|
||||||
/// \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
|
const string EmitMarkup::highlight[] = { "keyword",
|
||||||
/// \param id is the id associated with the document (as returned by beginDocument)
|
"comment",
|
||||||
void EmitXml::endDocument(int4 id) {
|
"type",
|
||||||
*s << "</clang_document>";
|
"funcname",
|
||||||
}
|
"var",
|
||||||
|
"const",
|
||||||
/// Inform the emitter that generation of a function body has begun
|
"param",
|
||||||
/// \return an id associated with the function body
|
"global",
|
||||||
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
|
/// \brief Emit a sequence of space characters as part of source code
|
||||||
///
|
///
|
||||||
/// \param num is the number of space characters to emit
|
/// \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
|
/// \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)
|
if (num <= 10)
|
||||||
print(tenspaces+(10-num));
|
print(spacearray[num]);
|
||||||
else {
|
else {
|
||||||
string spc;
|
string spc;
|
||||||
for(int4 i=0;i<num;++i)
|
for(int4 i=0;i<num;++i)
|
||||||
spc += ' ';
|
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;
|
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 API method matching the token type is called, feeding it content contained in
|
||||||
/// the object.
|
/// the object.
|
||||||
/// \param emit is the low-level emitter to output to
|
/// \param emit is the low-level emitter to output to
|
||||||
void TokenSplit::print(EmitXml *emit) const
|
void TokenSplit::print(Emit *emit) const
|
||||||
|
|
||||||
{
|
{
|
||||||
switch(tagtype) {
|
switch(tagtype) {
|
||||||
|
@ -410,34 +343,34 @@ void TokenSplit::print(EmitXml *emit) const
|
||||||
emit->endFuncProto(count);
|
emit->endFuncProto(count);
|
||||||
break;
|
break;
|
||||||
case vari_t: // tagVariable
|
case vari_t: // tagVariable
|
||||||
emit->tagVariable(tok.c_str(),hl,ptr_second.vn,op);
|
emit->tagVariable(tok,hl,ptr_second.vn,op);
|
||||||
break;
|
break;
|
||||||
case op_t: // tagOp
|
case op_t: // tagOp
|
||||||
emit->tagOp(tok.c_str(),hl,op);
|
emit->tagOp(tok,hl,op);
|
||||||
break;
|
break;
|
||||||
case fnam_t: // tagFuncName
|
case fnam_t: // tagFuncName
|
||||||
emit->tagFuncName(tok.c_str(),hl,ptr_second.fd,op);
|
emit->tagFuncName(tok,hl,ptr_second.fd,op);
|
||||||
break;
|
break;
|
||||||
case type_t: // tagType
|
case type_t: // tagType
|
||||||
emit->tagType(tok.c_str(),hl,ptr_second.ct);
|
emit->tagType(tok,hl,ptr_second.ct);
|
||||||
break;
|
break;
|
||||||
case field_t: // tagField
|
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;
|
break;
|
||||||
case comm_t: // tagComment
|
case comm_t: // tagComment
|
||||||
emit->tagComment(tok.c_str(),hl,ptr_second.spc,off);
|
emit->tagComment(tok,hl,ptr_second.spc,off);
|
||||||
break;
|
break;
|
||||||
case label_t: // tagLabel
|
case label_t: // tagLabel
|
||||||
emit->tagLabel(tok.c_str(),hl,ptr_second.spc,off);
|
emit->tagLabel(tok,hl,ptr_second.spc,off);
|
||||||
break;
|
break;
|
||||||
case synt_t: // print
|
case synt_t: // print
|
||||||
emit->print(tok.c_str(),hl);
|
emit->print(tok,hl);
|
||||||
break;
|
break;
|
||||||
case opar_t: // openParen
|
case opar_t: // openParen
|
||||||
emit->openParen(tok[0],count);
|
emit->openParen(tok,count);
|
||||||
break;
|
break;
|
||||||
case cpar_t: // closeParen
|
case cpar_t: // closeParen
|
||||||
emit->closeParen(tok[0],count);
|
emit->closeParen(tok,count);
|
||||||
break;
|
break;
|
||||||
case oinv_t: // Invisible open
|
case oinv_t: // Invisible open
|
||||||
break;
|
break;
|
||||||
|
@ -550,10 +483,10 @@ void TokenSplit::printDebug(ostream &s) const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EmitPrettyPrint::EmitPrettyPrint(void)
|
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;
|
spaceremain = maxlinesize;
|
||||||
needbreak = false;
|
needbreak = false;
|
||||||
commentmode = false;
|
commentmode = false;
|
||||||
|
@ -614,7 +547,7 @@ void EmitPrettyPrint::overflow(void)
|
||||||
spaceremain = newspaceremain;
|
spaceremain = newspaceremain;
|
||||||
lowlevel->tagLine(maxlinesize-spaceremain);
|
lowlevel->tagLine(maxlinesize-spaceremain);
|
||||||
if (commentmode &&(commentfill.size() != 0)) {
|
if (commentmode &&(commentfill.size() != 0)) {
|
||||||
lowlevel->print(commentfill.c_str(),EmitXml::comment_color);
|
lowlevel->print(commentfill,EmitMarkup::comment_color);
|
||||||
spaceremain -= commentfill.size();
|
spaceremain -= commentfill.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,7 +632,7 @@ void EmitPrettyPrint::print(const TokenSplit &tok)
|
||||||
}
|
}
|
||||||
lowlevel->tagLine(maxlinesize-spaceremain);
|
lowlevel->tagLine(maxlinesize-spaceremain);
|
||||||
if (commentmode &&(commentfill.size() != 0)) {
|
if (commentmode &&(commentfill.size() != 0)) {
|
||||||
lowlevel->print(commentfill.c_str(),EmitXml::comment_color);
|
lowlevel->print(commentfill,EmitMarkup::comment_color);
|
||||||
spaceremain -= commentfill.size();
|
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
|
/// 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
|
/// 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.
|
/// 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
|
/// 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
|
/// 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.
|
/// is \e committed and is sent to the low-level emitter.
|
||||||
|
@ -846,7 +779,7 @@ void EmitPrettyPrint::checkend(void)
|
||||||
{
|
{
|
||||||
if (!needbreak) {
|
if (!needbreak) {
|
||||||
TokenSplit &tok( tokqueue.push() );
|
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();
|
scan();
|
||||||
}
|
}
|
||||||
needbreak = true;
|
needbreak = true;
|
||||||
|
@ -860,7 +793,7 @@ void EmitPrettyPrint::checkbreak(void)
|
||||||
{
|
{
|
||||||
if (!needbreak) {
|
if (!needbreak) {
|
||||||
TokenSplit &tok( tokqueue.push() );
|
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();
|
scan();
|
||||||
}
|
}
|
||||||
needbreak = false;
|
needbreak = false;
|
||||||
|
@ -1021,95 +954,95 @@ void EmitPrettyPrint::endFuncProto(int4 id)
|
||||||
scan();
|
scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitPrettyPrint::tagVariable(const char *ptr,syntax_highlight hl,
|
void EmitPrettyPrint::tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op)
|
||||||
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)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
checkstring();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.tagOp(ptr,hl,op);
|
tok.tagVariable(name,hl,vn,op);
|
||||||
scan();
|
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();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.tagFuncName(ptr,hl,fd,op);
|
tok.tagOp(name,hl,op);
|
||||||
scan();
|
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();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.tagType(ptr,hl,ct);
|
tok.tagFuncName(name,hl,fd,op);
|
||||||
scan();
|
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();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.tagField(ptr,hl,ct,o,op);
|
tok.tagType(name,hl,ct);
|
||||||
scan();
|
scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitPrettyPrint::tagComment(const char *ptr,syntax_highlight hl,
|
void EmitPrettyPrint::tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 o,const PcodeOp *op)
|
||||||
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)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
checkstring();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.print(str,hl);
|
tok.tagField(name,hl,ct,o,op);
|
||||||
scan();
|
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
|
id = openGroup(); // Open paren automatically opens group
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.openParen(o,id);
|
tok.openParen(paren,id);
|
||||||
scan();
|
scan();
|
||||||
needbreak = true;
|
needbreak = true;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitPrettyPrint::closeParen(char c,int4 id)
|
void EmitPrettyPrint::closeParen(const string &paren,int4 id)
|
||||||
|
|
||||||
{
|
{
|
||||||
checkstring();
|
checkstring();
|
||||||
TokenSplit &tok( tokqueue.push() );
|
TokenSplit &tok( tokqueue.push() );
|
||||||
tok.closeParen(c,id);
|
tok.closeParen(paren,id);
|
||||||
scan();
|
scan();
|
||||||
closeGroup(id);
|
closeGroup(id);
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1088,7 @@ void EmitPrettyPrint::stopComment(int4 id)
|
||||||
void EmitPrettyPrint::clear(void)
|
void EmitPrettyPrint::clear(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
EmitXml::clear();
|
Emit::clear();
|
||||||
lowlevel->clear();
|
lowlevel->clear();
|
||||||
indentstack.clear();
|
indentstack.clear();
|
||||||
scanqueue.clear();
|
scanqueue.clear();
|
||||||
|
@ -1212,18 +1145,18 @@ void EmitPrettyPrint::flush(void)
|
||||||
lowlevel->flush();
|
lowlevel->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method toggles the low-level emitter between EmitXml and EmitNoXml depending
|
/// This method toggles the low-level emitter between EmitMarkup and EmitNoMarkup depending
|
||||||
/// on whether XML markup is desired.
|
/// on whether markup is desired.
|
||||||
/// \param val is \b true if XML markup is desired
|
/// \param val is \b true if markup is desired
|
||||||
void EmitPrettyPrint::setXML(bool val)
|
void EmitPrettyPrint::setMarkup(bool val)
|
||||||
|
|
||||||
{
|
{
|
||||||
ostream *t = lowlevel->getOutputStream();
|
ostream *t = lowlevel->getOutputStream();
|
||||||
delete lowlevel;
|
delete lowlevel;
|
||||||
if (val)
|
if (val)
|
||||||
lowlevel = new EmitXml;
|
lowlevel = new EmitMarkup;
|
||||||
else
|
else
|
||||||
lowlevel = new EmitNoXml;
|
lowlevel = new EmitNoMarkup;
|
||||||
lowlevel->setOutputStream(t);
|
lowlevel->setOutputStream(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,30 @@ class Funcdata;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
class PendPrint;
|
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:
|
/// 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.
|
/// 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
|
/// \b Pretty \b printing: Line breaks and additional white space characters are
|
||||||
|
@ -70,23 +89,19 @@ class PendPrint;
|
||||||
/// - tagLine forces a line break
|
/// - tagLine forces a line break
|
||||||
/// - tagLine(indent) forces a line break with an indent override
|
/// - 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
|
/// For an implementation that actually does pretty printing, see EmitPrettyPrint.
|
||||||
/// markup. For an implementation that actually does pretty printing, see EmitPrettyPrint.
|
class Emit {
|
||||||
/// This class can be used as the low-level back-end to EmitPrettyPrint to provide a solution
|
public:
|
||||||
/// that does both pretty printing and XML markup.
|
static const string EMPTY_STRING; ///< An empty string
|
||||||
class EmitXml {
|
|
||||||
static const char *highlight[]; ///< Map from syntax_highlight enumeration to color attribute string
|
|
||||||
protected:
|
protected:
|
||||||
ostream *s; ///< Stream being emitted to
|
|
||||||
int4 indentlevel; ///< Current indent level (in fixed width characters)
|
int4 indentlevel; ///< Current indent level (in fixed width characters)
|
||||||
int4 parenlevel; ///< Current depth of parentheses
|
int4 parenlevel; ///< Current depth of parentheses
|
||||||
int4 indentincrement; ///< Change in indentlevel per level of nesting
|
int4 indentincrement; ///< Change in indentlevel per level of nesting
|
||||||
PendPrint *pendPrint; ///< Pending print callback
|
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
|
void emitPending(void); ///< Emit any pending print commands
|
||||||
public:
|
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
|
/// \brief Possible types of syntax highlighting
|
||||||
enum syntax_highlight {
|
enum syntax_highlight {
|
||||||
keyword_color = 0, ///< Keyword in the high-level language
|
keyword_color = 0, ///< Keyword in the high-level language
|
||||||
|
@ -99,34 +114,202 @@ public:
|
||||||
global_color = 7, ///< Global variable identifiers
|
global_color = 7, ///< Global variable identifiers
|
||||||
no_color = 8 ///< Un-highlighted
|
no_color = 8 ///< Un-highlighted
|
||||||
};
|
};
|
||||||
virtual ~EmitXml(void) {} ///< Destructor
|
virtual ~Emit(void) {} ///< Destructor
|
||||||
virtual int4 beginDocument(void); ///< Begin a whole document of output
|
|
||||||
virtual void endDocument(int4 id); ///< End a whole document of output
|
/// \brief Begin 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
|
/// Inform the emitter that generation of the source code document has begun
|
||||||
virtual int4 beginBlock(const FlowBlock *bl); ///< Begin a control-flow element
|
/// \return an id associated with the document
|
||||||
virtual void endBlock(int4 id); ///< End a control-flow element
|
virtual int4 beginDocument(void)=0;
|
||||||
virtual void tagLine(void); ///< Force a line break
|
|
||||||
virtual void tagLine(int4 indent); ///< Force a line break and indent level
|
/// \brief End a whole document of output
|
||||||
virtual int4 beginReturnType(const Varnode *vn); ///< Begin a return type declaration
|
///
|
||||||
virtual void endReturnType(int4 id); ///< End a return type declaration
|
/// Inform the emitter that generation of the source code document is finished
|
||||||
virtual int4 beginVarDecl(const Symbol *sym); ///< Begin a variable declaration
|
/// \param id is the id associated with the document (as returned by beginDocument)
|
||||||
virtual void endVarDecl(int4 id); ///< End a variable declaration
|
virtual void endDocument(int4 id)=0;
|
||||||
virtual int4 beginStatement(const PcodeOp *op); ///< Begin a source code statement
|
|
||||||
virtual void endStatement(int4 id); ///< End a source code statement
|
/// \brief Begin a whole declaration and body of a function
|
||||||
virtual int4 beginFuncProto(void); ///< Begin a function prototype declaration
|
///
|
||||||
virtual void endFuncProto(int4 id); ///< End a function prototype declaration
|
/// Inform the emitter that generation of a function body has begun
|
||||||
virtual void tagVariable(const char *ptr,syntax_highlight hl,
|
/// \return an id associated with the function body
|
||||||
const Varnode *vn,const PcodeOp *op);
|
virtual int4 beginFunction(const Funcdata *fd)=0;
|
||||||
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);
|
/// \brief End a whole declaration and body of a function
|
||||||
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);
|
/// Inform the emitter that generation of a function body has ended
|
||||||
virtual void tagComment(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
|
/// \param id is the id associated with the function body (as returned by beginFunction)
|
||||||
virtual void tagLabel(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
|
virtual void endFunction(int4 id)=0;
|
||||||
virtual void print(const char *str,syntax_highlight hl=no_color);
|
|
||||||
virtual int4 openParen(char o,int4 id=0); ///< Emit an open parenthesis
|
/// \brief Begin a control-flow element
|
||||||
virtual void closeParen(char c,int4 id); ///< Emit a close parenthesis
|
///
|
||||||
|
/// 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
|
/// \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)
|
/// \param id is the id associated with the group (as returned by openGroup)
|
||||||
virtual void closeGroup(int4 id) {}
|
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 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 void setOutputStream(ostream *t)=0; ///< Set the output stream for the emitter
|
||||||
virtual ostream *getOutputStream(void) const { return s; } ///< Get the current output stream
|
virtual ostream *getOutputStream(void) const=0; ///< Get the current output stream
|
||||||
virtual void spaces(int4 num,int4 bump=0);
|
virtual void spaces(int4 num,int4 bump=0);
|
||||||
|
|
||||||
/// \brief Start a new indent level
|
/// \brief Start a new indent level
|
||||||
|
@ -198,10 +381,10 @@ public:
|
||||||
/// \brief Determine if \b this is an XML markup emitter
|
/// \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
|
/// \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
|
/// \brief (Re)set the default emitting options
|
||||||
virtual void resetDefaults(void);
|
virtual void resetDefaults(void) { resetDefaultsInternal(); }
|
||||||
|
|
||||||
/// \brief Get the current parentheses depth
|
/// \brief Get the current parentheses depth
|
||||||
///
|
///
|
||||||
|
@ -235,22 +418,81 @@ public:
|
||||||
/// \param pend is the given print callback to check
|
/// \param pend is the given print callback to check
|
||||||
/// \return \b true if the specific print callback is pending
|
/// \return \b true if the specific print callback is pending
|
||||||
bool hasPendingPrint(PendPrint *pend) const { return (pendPrint == pend); }
|
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
|
/// \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
|
/// straight to the final output stream. It can be used as the low-level back-end
|
||||||
/// for EmitPrettyPrint.
|
/// for EmitPrettyPrint.
|
||||||
class EmitNoXml : public EmitXml {
|
class EmitNoMarkup : public Emit {
|
||||||
|
ostream *s; ///< The stream to output tokens to
|
||||||
public:
|
public:
|
||||||
EmitNoXml(void) : EmitXml() {} ///< Constructor
|
EmitNoMarkup(void) : Emit() { s = (ostream *)0; } ///< Constructor
|
||||||
virtual int4 beginDocument(void) { return 0; }
|
virtual int4 beginDocument(void) { return 0; }
|
||||||
virtual void endDocument(int4 id) {}
|
virtual void endDocument(int4 id) {}
|
||||||
virtual int4 beginFunction(const Funcdata *fd) { return 0; }
|
virtual int4 beginFunction(const Funcdata *fd) { return 0; }
|
||||||
virtual void endFunction(int4 id) {}
|
virtual void endFunction(int4 id) {}
|
||||||
virtual int4 beginBlock(const FlowBlock *bl) { return 0; }
|
virtual int4 beginBlock(const FlowBlock *bl) { return 0; }
|
||||||
virtual void endBlock(int4 id) {}
|
virtual void endBlock(int4 id) {}
|
||||||
|
virtual void tagLine(void) {
|
||||||
|
*s << endl; for(int4 i=indentlevel;i>0;--i) *s << ' '; }
|
||||||
virtual void tagLine(int4 indent) {
|
virtual void tagLine(int4 indent) {
|
||||||
*s << endl; for(int4 i=indent;i>0;--i) *s << ' '; }
|
*s << endl; for(int4 i=indent;i>0;--i) *s << ' '; }
|
||||||
virtual int4 beginReturnType(const Varnode *vn) { return 0; }
|
virtual int4 beginReturnType(const Varnode *vn) { return 0; }
|
||||||
|
@ -261,30 +503,29 @@ public:
|
||||||
virtual void endStatement(int4 id) {}
|
virtual void endStatement(int4 id) {}
|
||||||
virtual int4 beginFuncProto(void) { return 0; }
|
virtual int4 beginFuncProto(void) { return 0; }
|
||||||
virtual void endFuncProto(int4 id) {}
|
virtual void endFuncProto(int4 id) {}
|
||||||
virtual void tagVariable(const char *ptr,syntax_highlight hl,
|
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op) {
|
||||||
const Varnode *vn,const PcodeOp *op) {
|
*s << name; }
|
||||||
*s << ptr; }
|
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op) {
|
||||||
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op) {
|
*s << name; }
|
||||||
*s << ptr; }
|
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
|
||||||
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
|
*s << name; }
|
||||||
*s << ptr; }
|
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct) {
|
||||||
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct) {
|
*s << name; }
|
||||||
*s << ptr; }
|
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
|
||||||
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
|
*s << name; }
|
||||||
*s << ptr; }
|
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
|
||||||
virtual void tagComment(const char *ptr,syntax_highlight hl,
|
*s << name; }
|
||||||
const AddrSpace *spc,uintb off) {
|
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
|
||||||
*s << ptr; }
|
*s << name; }
|
||||||
virtual void tagLabel(const char *ptr,syntax_highlight hl,
|
virtual void print(const string &data,syntax_highlight hl=no_color) {
|
||||||
const AddrSpace *spc,uintb off) {
|
*s << data; }
|
||||||
*s << ptr; }
|
virtual int4 openParen(const string &paren,int4 id=0) {
|
||||||
virtual void print(const char *str,syntax_highlight hl=no_color) {
|
*s << paren; parenlevel += 1; return id; }
|
||||||
*s << str; }
|
virtual void closeParen(const string &paren,int4 id) {
|
||||||
virtual int4 openParen(char o,int4 id=0) {
|
*s << paren; parenlevel -= 1; }
|
||||||
*s << o; parenlevel += 1; return id; }
|
virtual void setOutputStream(ostream *t) { s = t; }
|
||||||
virtual void closeParen(char c,int4 id) {
|
virtual ostream *getOutputStream(void) const { return s; }
|
||||||
*s << c; parenlevel -= 1; }
|
virtual bool emitsMarkup(void) const { return false; }
|
||||||
virtual bool emitsXml(void) const { return false; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A token/command object in the pretty printing stream
|
/// \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.
|
/// 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
|
/// 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
|
/// 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 {
|
class TokenSplit {
|
||||||
public:
|
public:
|
||||||
/// \brief An enumeration denoting the general class of a token
|
/// \brief An enumeration denoting the general class of a token
|
||||||
|
@ -351,7 +592,7 @@ private:
|
||||||
tag_type tagtype; ///< Type of token
|
tag_type tagtype; ///< Type of token
|
||||||
printclass delimtype; ///< The general class of the token
|
printclass delimtype; ///< The general class of the token
|
||||||
string tok; ///< Characters of token (if any)
|
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
|
// Additional markup elements for token
|
||||||
const PcodeOp *op; ///< Pcode-op associated with \b this token
|
const PcodeOp *op; ///< Pcode-op associated with \b this token
|
||||||
union {
|
union {
|
||||||
|
@ -461,98 +702,95 @@ public:
|
||||||
|
|
||||||
/// \brief Create a variable identifier token
|
/// \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 h indicates how the identifier should be highlighted
|
||||||
/// \param v is the Varnode representing the variable within the syntax tree
|
/// \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)
|
/// \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,
|
void tagVariable(const string &name,EmitMarkup::syntax_highlight h,const Varnode *v,const PcodeOp *o) {
|
||||||
const Varnode *v,const PcodeOp *o) {
|
tok = name; size = tok.size();
|
||||||
tok = ptr; size = tok.size();
|
|
||||||
tagtype=vari_t; delimtype=tokenstring; hl=h; ptr_second.vn=v; op=o; }
|
tagtype=vari_t; delimtype=tokenstring; hl=h; ptr_second.vn=v; op=o; }
|
||||||
|
|
||||||
/// \brief Create an operator token
|
/// \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 h indicates how the token should be highlighted
|
||||||
/// \param o is the PcodeOp object associated with the operation with the syntax tree
|
/// \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) {
|
void tagOp(const string &name,EmitMarkup::syntax_highlight h,const PcodeOp *o) {
|
||||||
tok = ptr; size = tok.size();
|
tok = name; size = tok.size();
|
||||||
tagtype=op_t; delimtype=tokenstring; hl=h; op=o; }
|
tagtype=op_t; delimtype=tokenstring; hl=h; op=o; }
|
||||||
|
|
||||||
/// \brief Create a function identifier token
|
/// \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 h indicates how the identifier should be highlighted
|
||||||
/// \param f is the function
|
/// \param f is the function
|
||||||
/// \param o is the CALL operation associated within the syntax tree or null for a declaration
|
/// \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) {
|
void tagFuncName(const string &name,EmitMarkup::syntax_highlight h,const Funcdata *f,const PcodeOp *o) {
|
||||||
tok = ptr; size = tok.size();
|
tok = name; size = tok.size();
|
||||||
tagtype=fnam_t; delimtype=tokenstring; hl=h; ptr_second.fd=f; op=o; }
|
tagtype=fnam_t; delimtype=tokenstring; hl=h; ptr_second.fd=f; op=o; }
|
||||||
|
|
||||||
/// \brief Create a data-type identifier token
|
/// \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 h indicates how the identifier should be highlighted
|
||||||
/// \param ct is the data-type description object
|
/// \param ct is the data-type description object
|
||||||
void tagType(const char *ptr,EmitXml::syntax_highlight h,const Datatype *ct) {
|
void tagType(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct) {
|
||||||
tok = ptr; size = tok.size();
|
tok = name; size = tok.size();
|
||||||
tagtype=type_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; }
|
tagtype=type_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; }
|
||||||
|
|
||||||
/// \brief Create an identifier for a field within a structured data-type
|
/// \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 h indicates how the identifier should be highlighted
|
||||||
/// \param ct is the data-type associated with the field
|
/// \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 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)
|
/// \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) {
|
void tagField(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct,int4 o,const PcodeOp *inOp) {
|
||||||
tok = ptr; size = tok.size();
|
tok = name; size = tok.size();
|
||||||
tagtype=field_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; off=(uintb)o; op=inOp; }
|
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
|
/// \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 h indicates how the comment should be highlighted
|
||||||
/// \param s is the address space of the address where the comment is attached
|
/// \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
|
/// \param o is the offset of the address where the comment is attached
|
||||||
void tagComment(const char *ptr,EmitXml::syntax_highlight h,
|
void tagComment(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
|
||||||
const AddrSpace *s,uintb o) {
|
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
|
||||||
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
|
|
||||||
tagtype=comm_t; delimtype=tokenstring; hl=h; }
|
tagtype=comm_t; delimtype=tokenstring; hl=h; }
|
||||||
|
|
||||||
/// \brief Create a code label identifier token
|
/// \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 h indicates how the label should be highlighted
|
||||||
/// \param s is the address space of the code address being labeled
|
/// \param s is the address space of the code address being labeled
|
||||||
/// \param o is the offset 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,
|
void tagLabel(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
|
||||||
const AddrSpace *s,uintb o) {
|
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
|
||||||
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
|
|
||||||
tagtype=label_t; delimtype=tokenstring; hl=h; }
|
tagtype=label_t; delimtype=tokenstring; hl=h; }
|
||||||
|
|
||||||
/// \brief Create a token for other (more unusual) syntax in source code
|
/// \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
|
/// \param h indicates how the syntax should be highlighted
|
||||||
void print(const char *str,EmitXml::syntax_highlight h) {
|
void print(const string &data,EmitMarkup::syntax_highlight h) {
|
||||||
tok = str; size=tok.size();
|
tok = data; size=tok.size();
|
||||||
tagtype=synt_t; delimtype=tokenstring; hl=h; }
|
tagtype=synt_t; delimtype=tokenstring; hl=h; }
|
||||||
|
|
||||||
/// \brief Create an open parenthesis
|
/// \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
|
/// \param id is an id to associate with the parenthesis
|
||||||
void openParen(char o,int4 id) {
|
void openParen(const string &paren,int4 id) {
|
||||||
tok = o; size = 1;
|
tok = paren; size = 1;
|
||||||
tagtype=opar_t; delimtype=tokenstring; count=id; }
|
tagtype=opar_t; delimtype=tokenstring; count=id; }
|
||||||
|
|
||||||
/// \brief Create a close parenthesis
|
/// \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)
|
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
|
||||||
void closeParen(char c,int4 id) {
|
void closeParen(const string &paren,int4 id) {
|
||||||
tok = c; size = 1;
|
tok = paren; size = 1;
|
||||||
tagtype=cpar_t; delimtype=tokenstring; count=id; }
|
tagtype=cpar_t; delimtype=tokenstring; count=id; }
|
||||||
|
|
||||||
/// \brief Create a "start a printing group" command
|
/// \brief Create a "start a printing group" command
|
||||||
|
@ -608,7 +846,7 @@ public:
|
||||||
void tagLine(int4 indent) {
|
void tagLine(int4 indent) {
|
||||||
tagtype=line_t; delimtype=tokenbreak; numspaces=999999; indentbump=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 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 getNumSpaces(void) const { return numspaces; } ///< Get the number of characters of whitespace
|
||||||
int4 getSize(void) const { return size; } ///< Get the number of content characters
|
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.
|
/// about formatting issues.
|
||||||
///
|
///
|
||||||
/// This emitter encapsulates a lower-level emitter that does the final emitting to
|
/// This emitter encapsulates a lower-level emitter that does the final emitting to
|
||||||
/// stream and may add XML markup.
|
/// stream and may add markup.
|
||||||
class EmitPrettyPrint : public EmitXml {
|
class EmitPrettyPrint : public Emit {
|
||||||
#ifdef PRETTY_DEBUG
|
#ifdef PRETTY_DEBUG
|
||||||
vector<int4> checkid;
|
vector<int4> checkid;
|
||||||
#endif
|
#endif
|
||||||
EmitXml *lowlevel; ///< The low-level emitter
|
Emit *lowlevel; ///< The low-level emitter
|
||||||
vector<int4> indentstack; ///< Space available for currently active nesting levels
|
vector<int4> indentstack; ///< Space available for currently active nesting levels
|
||||||
int4 spaceremain; ///< Space remaining in current line
|
int4 spaceremain; ///< Space remaining in current line
|
||||||
int4 maxlinesize; ///< Maximum number of characters allowed in a line
|
int4 maxlinesize; ///< Maximum number of characters allowed in a line
|
||||||
|
@ -769,19 +1007,16 @@ public:
|
||||||
virtual void endStatement(int4 id);
|
virtual void endStatement(int4 id);
|
||||||
virtual int4 beginFuncProto(void);
|
virtual int4 beginFuncProto(void);
|
||||||
virtual void endFuncProto(int4 id);
|
virtual void endFuncProto(int4 id);
|
||||||
virtual void tagVariable(const char *ptr,syntax_highlight hl,
|
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op);
|
||||||
const Varnode *vn,const PcodeOp *op);
|
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op);
|
||||||
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op);
|
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
|
||||||
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
|
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct);
|
||||||
virtual void tagType(const char *ptr,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 tagField(const char *ptr,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 tagComment(const char *ptr,syntax_highlight hl,
|
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
|
||||||
const AddrSpace *spc,uintb off);
|
virtual void print(const string &data,syntax_highlight hl=no_color);
|
||||||
virtual void tagLabel(const char *ptr,syntax_highlight hl,
|
virtual int4 openParen(const string &paren,int4 id=0);
|
||||||
const AddrSpace *spc,uintb off);
|
virtual void closeParen(const string &paren,int4 id);
|
||||||
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 int4 openGroup(void);
|
virtual int4 openGroup(void);
|
||||||
virtual void closeGroup(int4 id);
|
virtual void closeGroup(int4 id);
|
||||||
virtual void clear(void);
|
virtual void clear(void);
|
||||||
|
@ -796,9 +1031,9 @@ public:
|
||||||
virtual void setMaxLineSize(int4 val);
|
virtual void setMaxLineSize(int4 val);
|
||||||
virtual int4 getMaxLineSize(void) const { return maxlinesize; }
|
virtual int4 getMaxLineSize(void) const { return maxlinesize; }
|
||||||
virtual void setCommentFill(const string &fill) { commentfill = fill; }
|
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);
|
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
|
/// \brief Helper class for sending cancelable print commands to an ExitXml
|
||||||
|
@ -810,10 +1045,10 @@ public:
|
||||||
class PendPrint {
|
class PendPrint {
|
||||||
public:
|
public:
|
||||||
virtual ~PendPrint(void) {} ///< Destructor
|
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) {
|
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 TypeField *field; ///< The component object describing the field
|
||||||
const Datatype *parent; ///< The parent data-type owning the field
|
const Datatype *parent; ///< The parent data-type owning the field
|
||||||
string fieldname; ///< The name of 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
|
/// \brief The c-language token emitter
|
||||||
|
@ -113,7 +113,33 @@ protected:
|
||||||
static OpToken ptr_expr; ///< Pointer adornment for a type declaration
|
static OpToken ptr_expr; ///< Pointer adornment for a type declaration
|
||||||
static OpToken array_expr; ///< Array 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
|
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
|
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_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_inplace_ops; ///< Set to \b true if we should use '+=' '&=' etc.
|
||||||
bool option_convention; ///< Set to \b true if we should print calling convention
|
bool option_convention; ///< Set to \b true if we should print calling convention
|
||||||
|
@ -314,7 +340,7 @@ class PendingBrace : public PendPrint {
|
||||||
public:
|
public:
|
||||||
PendingBrace(void) { indentId = -1; } ///< Constructor
|
PendingBrace(void) { indentId = -1; } ///< Constructor
|
||||||
int4 getIndentId(void) const { return indentId; } ///< If commands have been issued, returns the new indent level id.
|
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
|
/// \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);
|
pushOp(&function_call,op);
|
||||||
pushAtom(Atom(typePointerRelToken,optoken,EmitXml::funcname_color,op));
|
pushAtom(Atom(typePointerRelToken,optoken,EmitMarkup::funcname_color,op));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "printjava.hh"
|
#include "printjava.hh"
|
||||||
#include "funcdata.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
|
// Constructing this registers the capability
|
||||||
PrintJavaCapability PrintJavaCapability::printJavaCapability;
|
PrintJavaCapability PrintJavaCapability::printJavaCapability;
|
||||||
|
@ -102,13 +102,13 @@ void PrintJava::pushTypeStart(const Datatype *ct,bool noident)
|
||||||
if (ct->getName().size()==0) { // Check for anonymous type
|
if (ct->getName().size()==0) { // Check for anonymous type
|
||||||
// We could support a struct or enum declaration here
|
// We could support a struct or enum declaration here
|
||||||
string nm = genericTypeName(ct);
|
string nm = genericTypeName(ct);
|
||||||
pushAtom(Atom(nm,typetoken,EmitXml::type_color,ct));
|
pushAtom(Atom(nm,typetoken,EmitMarkup::type_color,ct));
|
||||||
}
|
}
|
||||||
else {
|
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)
|
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)
|
void PrintJava::pushTypeEnd(const Datatype *ct)
|
||||||
|
@ -119,8 +119,8 @@ void PrintJava::pushTypeEnd(const Datatype *ct)
|
||||||
void PrintJava::adjustTypeOperators(void)
|
void PrintJava::adjustTypeOperators(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
scope.print = ".";
|
scope.print1 = ".";
|
||||||
shift_right.print = ">>>";
|
shift_right.print1 = ">>>";
|
||||||
TypeOp::selectJavaOperators(glb->inst,true);
|
TypeOp::selectJavaOperators(glb->inst,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ void PrintJava::opCallind(const PcodeOp *op)
|
||||||
}
|
}
|
||||||
else { // A void function
|
else { // A void function
|
||||||
pushVn(op->getIn(0),op,mods);
|
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());
|
refs.push_back(op->getIn(i)->getOffset());
|
||||||
const CPoolRecord *rec = glb->cpool->getRecord(refs);
|
const CPoolRecord *rec = glb->cpool->getRecord(refs);
|
||||||
if (rec == (const CPoolRecord *)0) {
|
if (rec == (const CPoolRecord *)0) {
|
||||||
pushAtom(Atom("UNKNOWNREF",syntax,EmitXml::const_color,op,outvn));
|
pushAtom(Atom("UNKNOWNREF",syntax,EmitMarkup::const_color,op,outvn));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch(rec->getTag()) {
|
switch(rec->getTag()) {
|
||||||
|
@ -316,11 +316,11 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
|
||||||
else {
|
else {
|
||||||
str << "...\"";
|
str << "...\"";
|
||||||
}
|
}
|
||||||
pushAtom(Atom(str.str(),vartoken,EmitXml::const_color,op,outvn));
|
pushAtom(Atom(str.str(),vartoken,EmitMarkup::const_color,op,outvn));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPoolRecord::class_reference:
|
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;
|
break;
|
||||||
case CPoolRecord::instance_of:
|
case CPoolRecord::instance_of:
|
||||||
{
|
{
|
||||||
|
@ -330,7 +330,7 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
|
||||||
}
|
}
|
||||||
pushOp(&instanceof,op);
|
pushOp(&instanceof,op);
|
||||||
pushVn(vn0,op,mods);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case CPoolRecord::primitive: // Should be eliminated
|
case CPoolRecord::primitive: // Should be eliminated
|
||||||
|
@ -341,11 +341,11 @@ void PrintJava::opCpoolRefOp(const PcodeOp *op)
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Datatype *ct = rec->getType();
|
Datatype *ct = rec->getType();
|
||||||
EmitXml::syntax_highlight color = EmitXml::var_color;
|
EmitMarkup::syntax_highlight color = EmitMarkup::var_color;
|
||||||
if (ct->getMetatype() == TYPE_PTR) {
|
if (ct->getMetatype() == TYPE_PTR) {
|
||||||
ct = ((TypePointer *)ct)->getPtrTo();
|
ct = ((TypePointer *)ct)->getPtrTo();
|
||||||
if (ct->getMetatype() == TYPE_CODE)
|
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
|
if (vn0->isConstant()) { // If this is NOT relative to an object reference
|
||||||
pushAtom(Atom(rec->getToken(),vartoken,color,op,outvn));
|
pushAtom(Atom(rec->getToken(),vartoken,color,op,outvn));
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "printlanguage.hh"
|
#include "printlanguage.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
|
const string PrintLanguage::OPEN_PAREN = "(";
|
||||||
|
const string PrintLanguage::CLOSE_PAREN = ")";
|
||||||
|
|
||||||
vector<PrintLanguageCapability *> PrintLanguageCapability::thelist;
|
vector<PrintLanguageCapability *> PrintLanguageCapability::thelist;
|
||||||
|
|
||||||
/// This retrieves the capability with its \b isdefault field set or
|
/// 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());
|
emitOp(revpol.back());
|
||||||
paren = parentheses(tok);
|
paren = parentheses(tok);
|
||||||
if (paren)
|
if (paren)
|
||||||
id = emit->openParen('(');
|
id = emit->openParen(OPEN_PAREN);
|
||||||
else
|
else
|
||||||
id = emit->openGroup();
|
id = emit->openGroup();
|
||||||
}
|
}
|
||||||
|
@ -170,7 +173,7 @@ void PrintLanguage::pushAtom(const Atom &atom)
|
||||||
if (revpol.back().visited == revpol.back().tok->stage) {
|
if (revpol.back().visited == revpol.back().tok->stage) {
|
||||||
emitOp(revpol.back());
|
emitOp(revpol.back());
|
||||||
if (revpol.back().paren)
|
if (revpol.back().paren)
|
||||||
emit->closeParen(')',revpol.back().id);
|
emit->closeParen(CLOSE_PAREN,revpol.back().id);
|
||||||
else
|
else
|
||||||
emit->closeGroup(revpol.back().id);
|
emit->closeGroup(revpol.back().id);
|
||||||
revpol.pop_back();
|
revpol.pop_back();
|
||||||
|
@ -327,32 +330,32 @@ void PrintLanguage::emitOp(const ReversePolish &entry)
|
||||||
case OpToken::binary:
|
case OpToken::binary:
|
||||||
if (entry.visited!=1) return;
|
if (entry.visited!=1) return;
|
||||||
emit->spaces(entry.tok->spacing,entry.tok->bump); // Spacing around operator
|
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);
|
emit->spaces(entry.tok->spacing,entry.tok->bump);
|
||||||
break;
|
break;
|
||||||
case OpToken::unary_prefix:
|
case OpToken::unary_prefix:
|
||||||
if (entry.visited!=0) return;
|
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);
|
emit->spaces(entry.tok->spacing,entry.tok->bump);
|
||||||
break;
|
break;
|
||||||
case OpToken::postsurround:
|
case OpToken::postsurround:
|
||||||
if (entry.visited==0) return;
|
if (entry.visited==0) return;
|
||||||
if (entry.visited==1) { // Front surround token
|
if (entry.visited==1) { // Front surround token
|
||||||
emit->spaces(entry.tok->spacing,entry.tok->bump);
|
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);
|
emit->spaces(0,entry.tok->bump);
|
||||||
}
|
}
|
||||||
else { // Back surround token
|
else { // Back surround token
|
||||||
emit->closeParen(entry.tok->print[1],entry.id2);
|
emit->closeParen(entry.tok->print2,entry.id2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OpToken::presurround:
|
case OpToken::presurround:
|
||||||
if (entry.visited==2) return;
|
if (entry.visited==2) return;
|
||||||
if (entry.visited==0) { // Front surround token
|
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
|
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);
|
emit->spaces(entry.tok->spacing,entry.tok->bump);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -372,24 +375,22 @@ void PrintLanguage::emitAtom(const Atom &atom)
|
||||||
{
|
{
|
||||||
switch(atom.type) {
|
switch(atom.type) {
|
||||||
case syntax:
|
case syntax:
|
||||||
emit->print(atom.name.c_str(),atom.highlight);
|
emit->print(atom.name,atom.highlight);
|
||||||
break;
|
break;
|
||||||
case vartoken:
|
case vartoken:
|
||||||
emit->tagVariable(atom.name.c_str(),atom.highlight,
|
emit->tagVariable(atom.name,atom.highlight,atom.ptr_second.vn,atom.op);
|
||||||
atom.ptr_second.vn,atom.op);
|
|
||||||
break;
|
break;
|
||||||
case functoken:
|
case functoken:
|
||||||
emit->tagFuncName(atom.name.c_str(),atom.highlight,
|
emit->tagFuncName(atom.name,atom.highlight,atom.ptr_second.fd,atom.op);
|
||||||
atom.ptr_second.fd,atom.op);
|
|
||||||
break;
|
break;
|
||||||
case optoken:
|
case optoken:
|
||||||
emit->tagOp(atom.name.c_str(),atom.highlight,atom.op);
|
emit->tagOp(atom.name,atom.highlight,atom.op);
|
||||||
break;
|
break;
|
||||||
case typetoken:
|
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;
|
break;
|
||||||
case fieldtoken:
|
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;
|
break;
|
||||||
case blanktoken:
|
case blanktoken:
|
||||||
break; // Print nothing
|
break; // Print nothing
|
||||||
|
@ -592,7 +593,7 @@ void PrintLanguage::emitLineComment(int4 indent,const Comment *comm)
|
||||||
int4 id = emit->startComment();
|
int4 id = emit->startComment();
|
||||||
// The comment delimeters should not be printed as
|
// The comment delimeters should not be printed as
|
||||||
// comment tags, so that they won't get filled
|
// 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);
|
spc,off);
|
||||||
int4 pos = 0;
|
int4 pos = 0;
|
||||||
while(pos < text.size()) {
|
while(pos < text.size()) {
|
||||||
|
@ -620,24 +621,21 @@ void PrintLanguage::emitLineComment(int4 indent,const Comment *comm)
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
string sub = text.substr(pos-count,count);
|
string sub = text.substr(pos-count,count);
|
||||||
emit->tagComment(sub.c_str(),EmitXml::comment_color,
|
emit->tagComment(sub,EmitMarkup::comment_color,spc,off);
|
||||||
spc,off);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commentend.size() != 0)
|
if (commentend.size() != 0)
|
||||||
emit->tagComment(commentend.c_str(),EmitXml::comment_color,
|
emit->tagComment(commentend,EmitMarkup::comment_color,spc,off);
|
||||||
spc,off);
|
|
||||||
emit->stopComment(id);
|
emit->stopComment(id);
|
||||||
comm->setEmitted(true);
|
comm->setEmitted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tell the emitter whether to emit just the raw tokens or if
|
/// Tell the emitter whether to emit just the raw tokens or if additional mark-up should be provided.
|
||||||
/// output is in XML format with additional mark-up on the raw tokens.
|
/// \param val is \b true for additional mark-up
|
||||||
/// \param val is \b true for XML mark-up
|
void PrintLanguage::setMarkup(bool val)
|
||||||
void PrintLanguage::setXML(bool val)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
((EmitPrettyPrint *)emit)->setXML(val);
|
((EmitPrettyPrint *)emit)->setMarkup(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emitting formal code structuring can be turned off, causing all control-flow
|
/// Emitting formal code structuring can be turned off, causing all control-flow
|
||||||
|
|
|
@ -90,7 +90,8 @@ public:
|
||||||
space, ///< No explicitly printed token
|
space, ///< No explicitly printed token
|
||||||
hiddenfunction ///< Operation that isn't explicitly printed
|
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 stage; ///< Additional elements consumed from the RPN stack when emitting this token
|
||||||
int4 precedence; ///< Precedence level of this token (higher binds more tightly)
|
int4 precedence; ///< Precedence level of this token (higher binds more tightly)
|
||||||
bool associative; ///< True if the operator is associative
|
bool associative; ///< True if the operator is associative
|
||||||
|
@ -134,6 +135,9 @@ public:
|
||||||
/// stack to provide a printing context mechanism for derived classes.
|
/// stack to provide a printing context mechanism for derived classes.
|
||||||
class PrintLanguage {
|
class PrintLanguage {
|
||||||
public:
|
public:
|
||||||
|
static const string OPEN_PAREN; ///< "(" token
|
||||||
|
static const string CLOSE_PAREN; ///< ")" token
|
||||||
|
|
||||||
/// \brief Possible context sensitive modifiers to how tokens get emitted
|
/// \brief Possible context sensitive modifiers to how tokens get emitted
|
||||||
enum modifiers {
|
enum modifiers {
|
||||||
force_hex = 1, ///< Force printing of hex
|
force_hex = 1, ///< Force printing of hex
|
||||||
|
@ -203,7 +207,7 @@ public:
|
||||||
struct Atom {
|
struct Atom {
|
||||||
const string &name; ///< The actual printed characters of the token
|
const string &name; ///< The actual printed characters of the token
|
||||||
tagtype type; ///< The type of Atom
|
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
|
const PcodeOp *op; ///< A p-code operation associated with the token
|
||||||
union {
|
union {
|
||||||
const Varnode *vn; ///< A Varnode associated with the token
|
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
|
int4 offset; ///< The offset (within the parent structure) for a \e field token
|
||||||
|
|
||||||
/// \brief Construct a token with no associated data-flow annotations
|
/// \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; }
|
: name(nm) { type = t; highlight = hl; }
|
||||||
|
|
||||||
/// \brief Construct a token for a data-type name
|
/// \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; }
|
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; }
|
||||||
|
|
||||||
/// \brief Construct a token for a field name
|
/// \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; }
|
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; offset = off; op = o; }
|
||||||
|
|
||||||
/// \brief Construct a token with an associated PcodeOp
|
/// \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; }
|
: name(nm) { type = t; highlight = hl; op = o; }
|
||||||
|
|
||||||
/// \brief Construct a token with an associated PcodeOp and Varnode
|
/// \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; }
|
: name(nm) { type=t; highlight = hl; ptr_second.vn = v; op = o; }
|
||||||
|
|
||||||
/// \brief Construct a token for a function name
|
/// \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; }
|
: name(nm) { type=t; highlight = hl; op = o; ptr_second.fd = f; }
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
|
@ -250,7 +254,7 @@ protected:
|
||||||
Architecture *glb; ///< The Architecture owning the language emitter
|
Architecture *glb; ///< The Architecture owning the language emitter
|
||||||
const Scope *curscope; ///< The current symbol scope
|
const Scope *curscope; ///< The current symbol scope
|
||||||
CastStrategy *castStrategy; ///< The strategy for emitting explicit \e case operations
|
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 mods; ///< Currently active printing modifications
|
||||||
uint4 instr_comment_type; ///< Type of instruction comments to display
|
uint4 instr_comment_type; ///< Type of instruction comments to display
|
||||||
uint4 head_comment_type; ///< Type of header 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
|
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
|
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
|
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
|
bool emitsMarkup(void) const { return emit->emitsMarkup(); } ///< Does the low-level emitter, emit markup
|
||||||
void setXML(bool val); ///< Set whether the low-level emitter, emits XML 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
|
void setFlat(bool val); ///< Set whether nesting code structure should be emitted
|
||||||
|
|
||||||
virtual void initializeFromArchitecture(void)=0; ///< Initialize architecture specific aspects of printer
|
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());
|
ifstream s(specfile.c_str());
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
|
|
||||||
XmlDecode decoder;
|
XmlDecode decoder((const AddrSpaceManager *)0);
|
||||||
try {
|
try {
|
||||||
decoder.ingestStream(s);
|
decoder.ingestStream(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,7 +268,7 @@ void SleighBase::restoreXml(const Element *el)
|
||||||
}
|
}
|
||||||
indexer.restoreXml(*iter);
|
indexer.restoreXml(*iter);
|
||||||
iter++;
|
iter++;
|
||||||
XmlDecode decoder(*iter);
|
XmlDecode decoder(this,*iter);
|
||||||
decodeSpaces(decoder,this);
|
decodeSpaces(decoder,this);
|
||||||
iter++;
|
iter++;
|
||||||
symtab.restoreXml(*iter,this);
|
symtab.restoreXml(*iter,this);
|
||||||
|
|
|
@ -134,7 +134,7 @@ void AddrSpace::truncateSpace(uint4 newsize)
|
||||||
void AddrSpace::encodeAttributes(Encoder &encoder,uintb offset) const
|
void AddrSpace::encodeAttributes(Encoder &encoder,uintb offset) const
|
||||||
|
|
||||||
{
|
{
|
||||||
encoder.writeString(ATTRIB_SPACE,getName());
|
encoder.writeSpace(ATTRIB_SPACE,this);
|
||||||
encoder.writeUnsignedInteger(ATTRIB_OFFSET, offset);
|
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
|
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.writeUnsignedInteger(ATTRIB_OFFSET, offset);
|
||||||
encoder.writeSignedInteger(ATTRIB_SIZE, size);
|
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,
|
static AttributeId *pieceArray[] = { &ATTRIB_PIECE1, &ATTRIB_PIECE2, &ATTRIB_PIECE3, &ATTRIB_PIECE4,
|
||||||
&ATTRIB_PIECE5, &ATTRIB_PIECE6, &ATTRIB_PIECE7, &ATTRIB_PIECE8, &ATTRIB_PIECE9 };
|
&ATTRIB_PIECE5, &ATTRIB_PIECE6, &ATTRIB_PIECE7, &ATTRIB_PIECE8, &ATTRIB_PIECE9 };
|
||||||
JoinRecord *rec = getManager()->findJoin(offset); // Record must already exist
|
JoinRecord *rec = getManager()->findJoin(offset); // Record must already exist
|
||||||
encoder.writeString(ATTRIB_SPACE, getName());
|
encoder.writeSpace(ATTRIB_SPACE, this);
|
||||||
int4 num = rec->numPieces();
|
int4 num = rec->numPieces();
|
||||||
if (num >= 8)
|
if (num >= 8)
|
||||||
throw LowlevelError("Cannot encode more than 8 pieces");
|
throw LowlevelError("Cannot encode more than 8 pieces");
|
||||||
|
@ -657,10 +657,7 @@ void OverlaySpace::decode(Decoder &decoder)
|
||||||
name = decoder.readString(ATTRIB_NAME);
|
name = decoder.readString(ATTRIB_NAME);
|
||||||
index = decoder.readSignedInteger(ATTRIB_INDEX);
|
index = decoder.readSignedInteger(ATTRIB_INDEX);
|
||||||
|
|
||||||
string basename = decoder.readString(ATTRIB_BASE);
|
baseSpace = decoder.readSpace(ATTRIB_BASE);
|
||||||
baseSpace = getManager()->getSpaceByName(basename);
|
|
||||||
if (baseSpace == (AddrSpace *)0)
|
|
||||||
throw LowlevelError("Base space does not exist for overlay space: "+name);
|
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
addressSize = baseSpace->getAddrSize();
|
addressSize = baseSpace->getAddrSize();
|
||||||
wordsize = baseSpace->getWordSize();
|
wordsize = baseSpace->getWordSize();
|
||||||
|
|
|
@ -119,15 +119,14 @@ void StringManager::encode(Encoder &encoder) const
|
||||||
|
|
||||||
/// Parse a \<stringmanage> element, with \<string> children.
|
/// Parse a \<stringmanage> element, with \<string> children.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param m is the manager for looking up AddressSpaces
|
void StringManager::decode(Decoder &decoder)
|
||||||
void StringManager::decode(Decoder &decoder, const AddrSpaceManager *m)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
uint4 elemId = decoder.openElement(ELEM_STRINGMANAGE);
|
uint4 elemId = decoder.openElement(ELEM_STRINGMANAGE);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint4 subId = decoder.openElement();
|
uint4 subId = decoder.openElement();
|
||||||
if (subId != ELEM_STRING) break;
|
if (subId != ELEM_STRING) break;
|
||||||
Address addr = Address::decode(decoder, m);
|
Address addr = Address::decode(decoder);
|
||||||
StringData &stringData(stringMap[addr]);
|
StringData &stringData(stringMap[addr]);
|
||||||
uint4 subId2 = decoder.openElement(ELEM_BYTES);
|
uint4 subId2 = decoder.openElement(ELEM_BYTES);
|
||||||
stringData.isTruncated = decoder.readBool(ATTRIB_TRUNC);
|
stringData.isTruncated = decoder.readBool(ATTRIB_TRUNC);
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
virtual const vector<uint1> &getStringData(const Address &addr,Datatype *charType,bool &isTrunc)=0;
|
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 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 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
|
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.
|
/// Parse any vector lane sizes.
|
||||||
/// \param decoder is the stream decoder
|
/// \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
|
/// \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);
|
uint4 elemId = decoder.openElement(ELEM_REGISTER);
|
||||||
|
@ -303,7 +302,7 @@ bool LanedRegister::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
decoder.rewindAttributes();
|
decoder.rewindAttributes();
|
||||||
VarnodeData storage;
|
VarnodeData storage;
|
||||||
storage.space = (AddrSpace *)0;
|
storage.space = (AddrSpace *)0;
|
||||||
storage.decodeFromAttributes(decoder, manage);
|
storage.decodeFromAttributes(decoder);
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
wholeSize = storage.size;
|
wholeSize = storage.size;
|
||||||
sizeBitMask = 0;
|
sizeBitMask = 0;
|
||||||
|
|
|
@ -111,7 +111,7 @@ private:
|
||||||
public:
|
public:
|
||||||
LanedRegister(void) { wholeSize = 0; sizeBitMask = 0; } ///< Constructor for use with decode
|
LanedRegister(void) { wholeSize = 0; sizeBitMask = 0; } ///< Constructor for use with decode
|
||||||
LanedRegister(int4 sz,uint4 mask) { wholeSize = sz; sizeBitMask = mask; } ///< Constructor
|
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
|
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
|
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
|
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);
|
uint4 elemId = decoder.openElement(ELEM_SPACE_BASE);
|
||||||
decodeBasicAttributes(decoder);
|
decodeBasicAttributes(decoder);
|
||||||
contain = getManager()->getSpaceByName(decoder.readString(ATTRIB_CONTAIN));
|
contain = decoder.readSpace(ATTRIB_CONTAIN);
|
||||||
decoder.closeElement(elemId);
|
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
|
/// A single pcode operation is parsed from an \<op> element and
|
||||||
/// returned to the application via the PcodeEmit::dump method.
|
/// returned to the application via the PcodeEmit::dump method.
|
||||||
/// \param decoder is the stream decoder
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the AddrSpace manager object of the associated processor
|
void PcodeEmit::decodeOp(Decoder &decoder)
|
||||||
void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 opcode;
|
int4 opcode;
|
||||||
|
@ -918,7 +917,7 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
uint4 elemId = decoder.openElement(ELEM_OP);
|
uint4 elemId = decoder.openElement(ELEM_OP);
|
||||||
opcode = decoder.readSignedInteger(ATTRIB_CODE);
|
opcode = decoder.readSignedInteger(ATTRIB_CODE);
|
||||||
Address pc = Address::decode(decoder,manage);
|
Address pc = Address::decode(decoder);
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId == ELEM_VOID) {
|
if (subId == ELEM_VOID) {
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
|
@ -926,7 +925,7 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
outptr = (VarnodeData *)0;
|
outptr = (VarnodeData *)0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
outvar.decode(decoder,manage);
|
outvar.decode(decoder);
|
||||||
outptr = &outvar;
|
outptr = &outvar;
|
||||||
}
|
}
|
||||||
int4 isize = 0;
|
int4 isize = 0;
|
||||||
|
@ -935,13 +934,13 @@ void PcodeEmit::decodeOp(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_SPACEID) {
|
if (subId == ELEM_SPACEID) {
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
invar[isize].space = manage->getConstantSpace();
|
invar[isize].space = decoder.getAddrSpaceManager()->getConstantSpace();
|
||||||
invar[isize].offset = (uintb)(uintp)manage->getSpaceByName( decoder.readString(ATTRIB_NAME) );
|
invar[isize].offset = (uintb)(uintp)decoder.readSpace(ATTRIB_NAME);
|
||||||
invar[isize].size = sizeof(void *);
|
invar[isize].size = sizeof(void *);
|
||||||
decoder.closeElement(subId);
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
invar[isize].decode(decoder,manage);
|
invar[isize].decode(decoder);
|
||||||
isize += 1;
|
isize += 1;
|
||||||
}
|
}
|
||||||
decoder.closeElement(elemId);
|
decoder.closeElement(elemId);
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)=0;
|
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)=0;
|
||||||
|
|
||||||
/// Emit pcode directly from an \<op> element
|
/// Emit pcode directly from an \<op> element
|
||||||
void decodeOp(Decoder &decoder,const AddrSpaceManager *trans);
|
void decodeOp(Decoder &decoder);
|
||||||
|
|
||||||
enum { // Tags for packed pcode format
|
enum { // Tags for packed pcode format
|
||||||
unimpl_tag = 0x20,
|
unimpl_tag = 0x20,
|
||||||
|
|
|
@ -763,7 +763,7 @@ void TypePointer::encode(Encoder &encoder) const
|
||||||
if (wordsize != 1)
|
if (wordsize != 1)
|
||||||
encoder.writeSignedInteger(ATTRIB_WORDSIZE, wordsize);
|
encoder.writeSignedInteger(ATTRIB_WORDSIZE, wordsize);
|
||||||
if (spaceid != (AddrSpace *)0)
|
if (spaceid != (AddrSpace *)0)
|
||||||
encoder.writeString(ATTRIB_SPACE, spaceid->getName());
|
encoder.writeSpace(ATTRIB_SPACE, spaceid);
|
||||||
ptrto->encodeRef(encoder);
|
ptrto->encodeRef(encoder);
|
||||||
encoder.closeElement(ELEM_TYPE);
|
encoder.closeElement(ELEM_TYPE);
|
||||||
}
|
}
|
||||||
|
@ -784,7 +784,7 @@ void TypePointer::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
wordsize = decoder.readUnsignedInteger();
|
wordsize = decoder.readUnsignedInteger();
|
||||||
}
|
}
|
||||||
else if (attrib == ATTRIB_SPACE) {
|
else if (attrib == ATTRIB_SPACE) {
|
||||||
spaceid = typegrp.getArch()->getSpaceByName(decoder.readString());
|
spaceid = decoder.readSpace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptrto = typegrp.decodeType( decoder );
|
ptrto = typegrp.decodeType( decoder );
|
||||||
|
@ -1871,7 +1871,7 @@ void TypePointerRel::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
wordsize = decoder.readUnsignedInteger();
|
wordsize = decoder.readUnsignedInteger();
|
||||||
}
|
}
|
||||||
else if (attrib == ATTRIB_SPACE) {
|
else if (attrib == ATTRIB_SPACE) {
|
||||||
spaceid = typegrp.getArch()->getSpaceByName(decoder.readString());
|
spaceid = decoder.readSpace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptrto = typegrp.decodeType( decoder );
|
ptrto = typegrp.decodeType( decoder );
|
||||||
|
@ -2397,7 +2397,7 @@ void TypeSpacebase::encode(Encoder &encoder) const
|
||||||
}
|
}
|
||||||
encoder.openElement(ELEM_TYPE);
|
encoder.openElement(ELEM_TYPE);
|
||||||
encodeBasic(metatype,encoder);
|
encodeBasic(metatype,encoder);
|
||||||
encoder.writeString(ATTRIB_SPACE, spaceid->getName());
|
encoder.writeSpace(ATTRIB_SPACE, spaceid);
|
||||||
localframe.encode(encoder);
|
localframe.encode(encoder);
|
||||||
encoder.closeElement(ELEM_TYPE);
|
encoder.closeElement(ELEM_TYPE);
|
||||||
}
|
}
|
||||||
|
@ -2410,8 +2410,8 @@ void TypeSpacebase::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
{
|
{
|
||||||
// uint4 elemId = decoder.openElement();
|
// uint4 elemId = decoder.openElement();
|
||||||
decodeBasic(decoder);
|
decodeBasic(decoder);
|
||||||
spaceid = glb->getSpaceByName(decoder.readString(ATTRIB_SPACE));
|
spaceid = decoder.readSpace(ATTRIB_SPACE);
|
||||||
localframe = Address::decode(decoder,typegrp.getArch());
|
localframe = Address::decode(decoder);
|
||||||
// decoder.closeElement(elemId);
|
// 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
|
Datatype *ct = TypeFactory::findById(n,id,sz); // Try internal find
|
||||||
if (ct != (Datatype *)0) return ct;
|
if (ct != (Datatype *)0) return ct;
|
||||||
XmlDecode decoder;
|
XmlDecode decoder(glb);
|
||||||
try {
|
try {
|
||||||
if (!((ArchitectureGhidra *)glb)->getType(n,id,decoder)) // See if ghidra knows about type
|
if (!((ArchitectureGhidra *)glb)->getType(n,id,decoder)) // See if ghidra knows about type
|
||||||
return (Datatype *)0;
|
return (Datatype *)0;
|
||||||
|
|
|
@ -134,7 +134,7 @@ void SegmentOp::decode(Decoder &decoder)
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
if (attribId == 0) break;
|
||||||
if (attribId == ATTRIB_SPACE)
|
if (attribId == ATTRIB_SPACE)
|
||||||
spc = glb->getSpaceByName(decoder.readString());
|
spc = decoder.readSpace();
|
||||||
else if (attribId == ATTRIB_FARPOINTER)
|
else if (attribId == ATTRIB_FARPOINTER)
|
||||||
supportsfarpointer = true;
|
supportsfarpointer = true;
|
||||||
else if (attribId == ATTRIB_USEROP) { // Based on existing sleigh op
|
else if (attribId == ATTRIB_USEROP) { // Based on existing sleigh op
|
||||||
|
@ -157,7 +157,7 @@ void SegmentOp::decode(Decoder &decoder)
|
||||||
int4 sz;
|
int4 sz;
|
||||||
decoder.openElement();
|
decoder.openElement();
|
||||||
if (decoder.peekElement() != 0) {
|
if (decoder.peekElement() != 0) {
|
||||||
Address addr = Address::decode(decoder,glb,sz);
|
Address addr = Address::decode(decoder,sz);
|
||||||
constresolve.space = addr.getSpace();
|
constresolve.space = addr.getSpace();
|
||||||
constresolve.offset = addr.getOffset();
|
constresolve.offset = addr.getOffset();
|
||||||
constresolve.size = sz;
|
constresolve.size = sz;
|
||||||
|
|
|
@ -373,7 +373,7 @@ void ScopeLocal::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
encoder.openElement(ELEM_LOCALDB);
|
encoder.openElement(ELEM_LOCALDB);
|
||||||
encoder.writeString(ATTRIB_MAIN, space->getName());
|
encoder.writeSpace(ATTRIB_MAIN, space);
|
||||||
encoder.writeBool(ATTRIB_LOCK, rangeLocked);
|
encoder.writeBool(ATTRIB_LOCK, rangeLocked);
|
||||||
ScopeInternal::encode(encoder);
|
ScopeInternal::encode(encoder);
|
||||||
encoder.closeElement(ELEM_LOCALDB);
|
encoder.closeElement(ELEM_LOCALDB);
|
||||||
|
@ -392,7 +392,7 @@ void ScopeLocal::decodeWrappingAttributes(Decoder &decoder)
|
||||||
rangeLocked = false;
|
rangeLocked = false;
|
||||||
if (decoder.readBool(ATTRIB_LOCK))
|
if (decoder.readBool(ATTRIB_LOCK))
|
||||||
rangeLocked = true;
|
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
|
/// 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