mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 23:17:03 +08:00
Merge remote-tracking branch 'origin/GP-2157_MarshalAPI'
This commit is contained in:
@@ -51,6 +51,7 @@ model {
|
|||||||
source {
|
source {
|
||||||
srcDir "src/decompile/cpp"
|
srcDir "src/decompile/cpp"
|
||||||
|
|
||||||
|
include "marshal.cc"
|
||||||
include "space.cc"
|
include "space.cc"
|
||||||
include "float.cc"
|
include "float.cc"
|
||||||
include "address.cc"
|
include "address.cc"
|
||||||
@@ -152,6 +153,7 @@ model {
|
|||||||
source {
|
source {
|
||||||
srcDir "src/decompile/cpp"
|
srcDir "src/decompile/cpp"
|
||||||
|
|
||||||
|
include "marshal.cc"
|
||||||
include "space.cc"
|
include "space.cc"
|
||||||
include "float.cc"
|
include "float.cc"
|
||||||
include "address.cc"
|
include "address.cc"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ EXTERNAL_CONSOLEEXT_NAMES=$(subst .cc,,$(notdir $(EXTERNAL_CONSOLEEXT_SOURCE)))
|
|||||||
|
|
||||||
# The following macros partition all the source files, there should be no overlaps
|
# The following macros partition all the source files, there should be no overlaps
|
||||||
# Some core source files used in all projects
|
# Some core source files used in all projects
|
||||||
CORE= xml space float address pcoderaw translate opcodes globalcontext
|
CORE= xml marshal space float address pcoderaw translate opcodes globalcontext
|
||||||
# Additional core files for any projects that decompile
|
# Additional core files for any projects that decompile
|
||||||
DECCORE=capability architecture options graph cover block cast typeop database cpool \
|
DECCORE=capability architecture options graph cover block cast typeop database cpool \
|
||||||
comment stringmanage fspec action loadimage grammar varnode op \
|
comment stringmanage fspec action loadimage grammar varnode op \
|
||||||
|
|||||||
@@ -128,8 +128,6 @@ public:
|
|||||||
virtual int4 apply(Funcdata &data)=0;
|
virtual int4 apply(Funcdata &data)=0;
|
||||||
virtual int4 print(ostream &s,int4 num,int4 depth) const; ///< Print a description of this Action to stream
|
virtual int4 print(ostream &s,int4 num,int4 depth) const; ///< Print a description of this Action to stream
|
||||||
virtual void printState(ostream &s) const; ///< Print status to stream
|
virtual void printState(ostream &s) const; ///< Print status to stream
|
||||||
virtual void saveXml(ostream &s) const {} ///< Save specifics of this action to stream
|
|
||||||
virtual void restoreXml(const Element *el,Funcdata *fd) {} ///< Load specifics of action from XML
|
|
||||||
virtual Action *getSubAction(const string &specify); ///< Retrieve a specific sub-action by name
|
virtual Action *getSubAction(const string &specify); ///< Retrieve a specific sub-action by name
|
||||||
virtual Rule *getSubRule(const string &specify); ///< Retrieve a specific sub-rule by name
|
virtual Rule *getSubRule(const string &specify); ///< Retrieve a specific sub-rule by name
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,17 @@
|
|||||||
#include "address.hh"
|
#include "address.hh"
|
||||||
#include "translate.hh"
|
#include "translate.hh"
|
||||||
|
|
||||||
|
AttributeId ATTRIB_FIRST = AttributeId("first",27);
|
||||||
|
AttributeId ATTRIB_LAST = AttributeId("last",28);
|
||||||
|
AttributeId ATTRIB_UNIQ = AttributeId("uniq",29);
|
||||||
|
|
||||||
|
ElementId ELEM_ADDR = ElementId("addr",11);
|
||||||
|
ElementId ELEM_RANGE = ElementId("range",12);
|
||||||
|
ElementId ELEM_RANGELIST = ElementId("rangelist",13);
|
||||||
|
ElementId ELEM_REGISTER = ElementId("register",14);
|
||||||
|
ElementId ELEM_SEQNUM = ElementId("seqnum",15);
|
||||||
|
ElementId ELEM_VARNODE = ElementId("varnode",16);
|
||||||
|
|
||||||
ostream &operator<<(ostream &s,const SeqNum &sq)
|
ostream &operator<<(ostream &s,const SeqNum &sq)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -44,27 +55,30 @@ SeqNum::SeqNum(Address::mach_extreme ex) : pc(ex)
|
|||||||
uniq = (ex == Address::m_minimal) ? 0 : ~((uintm)0);
|
uniq = (ex == Address::m_minimal) ? 0 : ~((uintm)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeqNum::saveXml(ostream &s) const
|
void SeqNum::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<seqnum";
|
encoder.openElement(ELEM_SEQNUM);
|
||||||
pc.getSpace()->saveXmlAttributes(s,pc.getOffset());
|
pc.getSpace()->encodeAttributes(encoder,pc.getOffset());
|
||||||
a_v_u(s,"uniq",uniq);
|
encoder.writeUnsignedInteger(ATTRIB_UNIQ, uniq);
|
||||||
s << "/>";
|
encoder.closeElement(ELEM_SEQNUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
SeqNum SeqNum::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
SeqNum SeqNum::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintm uniq = ~((uintm)0);
|
uintm uniq = ~((uintm)0);
|
||||||
Address pc = Address::restoreXml(el,manage); // Recover address
|
uint4 elemId = decoder.openElement(ELEM_SEQNUM);
|
||||||
for(int4 i=0;i<el->getNumAttributes();++i)
|
Address pc = Address::decode(decoder,manage); // Recover address
|
||||||
if (el->getAttributeName(i) == "uniq") {
|
for(;;) {
|
||||||
istringstream s2(el->getAttributeValue(i)); // Recover unique (if present)
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
if (attribId == 0) break;
|
||||||
s2 >> uniq;
|
if (attribId == ATTRIB_UNIQ) {
|
||||||
|
uniq = decoder.readUnsignedInteger();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
return SeqNum(pc,uniq);
|
return SeqNum(pc,uniq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,16 +99,6 @@ Address::Address(mach_extreme ex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \deprecated Convert this to the most basic physical address.
|
|
||||||
/// This routine is only present for backward compatibility
|
|
||||||
/// with SLED
|
|
||||||
void Address::toPhysical(void)
|
|
||||||
|
|
||||||
{ AddrSpace *phys = base->getContain();
|
|
||||||
if ((phys != (AddrSpace *)0)&&(base->getType()==IPTR_SPACEBASE))
|
|
||||||
base = phys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return \b true if the range starting at \b this extending the given number of bytes
|
/// Return \b true if the range starting at \b this extending the given number of bytes
|
||||||
/// is contained by the second given range.
|
/// is contained by the second given range.
|
||||||
/// \param sz is the given number of bytes in \b this range
|
/// \param sz is the given number of bytes in \b this range
|
||||||
@@ -187,29 +191,27 @@ void Address::renormalize(int4 size) {
|
|||||||
base->getManager()->renormalizeJoinAddress(*this,size);
|
base->getManager()->renormalizeJoinAddress(*this,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is usually used to build an address from an \b \<addr\>
|
/// This is usually used to decode an address from an \b \<addr\>
|
||||||
/// tag, but it can be used to create an address from any tag
|
/// element, but any element can be used if it has the appropriate attributes
|
||||||
/// with the appropriate attributes
|
|
||||||
/// - \e space indicates the address space of the tag
|
/// - \e space indicates the address space of the tag
|
||||||
/// - \e offset indicates the offset within the space
|
/// - \e offset indicates the offset within the space
|
||||||
///
|
///
|
||||||
/// 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 el is the parsed tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the address space manager for the program
|
/// \param manage is the address space manager for the program
|
||||||
/// \return the resulting Address
|
/// \return the resulting Address
|
||||||
Address Address::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeData var;
|
VarnodeData var;
|
||||||
|
|
||||||
var.restoreXml(el,manage);
|
var.decode(decoder,manage);
|
||||||
return Address(var.space,var.offset);
|
return Address(var.space,var.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is usually used to build an address from an \b \<addr\>
|
/// This is usually used to decode an address from an \b \<addr\>
|
||||||
/// tag, but it can be used to create an address from any tag
|
/// element, but any element can be used if it has the appropriate attributes
|
||||||
/// with the appropriate attributes
|
|
||||||
/// - \e space indicates the address space of the tag
|
/// - \e space indicates the address space of the tag
|
||||||
/// - \e offset indicates the offset within the space
|
/// - \e offset indicates the offset within the space
|
||||||
/// - \e size indicates the size of an address range
|
/// - \e size indicates the size of an address range
|
||||||
@@ -217,20 +219,46 @@ Address Address::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
|||||||
/// or a \e name attribute can be used to recover an address
|
/// or a \e name attribute can be used to recover an address
|
||||||
/// 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 el is the parsed tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the address space manager for the program
|
/// \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::restoreXml(const Element *el,const AddrSpaceManager *manage,int4 &size)
|
Address Address::decode(Decoder &decoder,const AddrSpaceManager *manage,int4 &size)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeData var;
|
VarnodeData var;
|
||||||
|
|
||||||
var.restoreXml(el,manage);
|
var.decode(decoder,manage);
|
||||||
size = var.size;
|
size = var.size;
|
||||||
return Address(var.space,var.offset);
|
return Address(var.space,var.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Range::Range(const RangeProperties &properties,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (properties.isRegister) {
|
||||||
|
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
|
||||||
|
const VarnodeData &point(trans->getRegister(properties.spaceName));
|
||||||
|
spc = point.space;
|
||||||
|
first = point.offset;
|
||||||
|
last = (first-1) + point.size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spc = manage->getSpaceByName(properties.spaceName);
|
||||||
|
if (spc == (AddrSpace *)0)
|
||||||
|
throw LowlevelError("Undefined space: "+properties.spaceName);
|
||||||
|
|
||||||
|
if (spc == (AddrSpace *)0)
|
||||||
|
throw LowlevelError("No address space indicated in range tag");
|
||||||
|
first = properties.first;
|
||||||
|
last = properties.last;
|
||||||
|
if (!properties.seenLast) {
|
||||||
|
last = spc->getHighest();
|
||||||
|
}
|
||||||
|
if (first > spc->getHighest() || last > spc->getHighest() || last < first)
|
||||||
|
throw LowlevelError("Illegal range tag");
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the last address +1, updating the space, or returning
|
/// Get the last address +1, updating the space, or returning
|
||||||
/// the extremal address if necessary
|
/// the extremal address if necessary
|
||||||
/// \param manage is used to fetch the next address space
|
/// \param manage is used to fetch the next address space
|
||||||
@@ -259,48 +287,60 @@ void Range::printBounds(ostream &s) const
|
|||||||
s << hex << first << '-' << last;
|
s << hex << first << '-' << last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write this object to a stream as a \<range> tag.
|
/// Encode \b this to a stream as a \<range> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void Range::saveXml(ostream &s) const
|
void Range::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<range";
|
encoder.openElement(ELEM_RANGE);
|
||||||
a_v(s,"space",spc->getName());
|
encoder.writeString(ATTRIB_SPACE, spc->getName());
|
||||||
a_v_u(s,"first",first);
|
encoder.writeUnsignedInteger(ATTRIB_FIRST, first);
|
||||||
a_v_u(s,"last",last);
|
encoder.writeUnsignedInteger(ATTRIB_LAST, last);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconstruct this object from an XML \<range> element
|
/// Reconstruct this object from a \<range> or \<register> element
|
||||||
/// \param el is the XML element
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the space manage for recovering AddrSpace objects
|
/// \param manage is the space manager for recovering AddrSpace objects
|
||||||
void Range::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void Range::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint4 elemId = decoder.openElement();
|
||||||
|
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
||||||
|
throw XmlError("Expecting <range> or <register> element");
|
||||||
|
decodeFromAttributes(decoder,manage);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reconstruct from attributes that may not be part of a \<range> element.
|
||||||
|
/// \param decoder is the stream decoder
|
||||||
|
/// \param manage is the space manager for recovering AddrSpace objects
|
||||||
|
void Range::decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
spc = (AddrSpace *)0;
|
spc = (AddrSpace *)0;
|
||||||
bool seenLast = false;
|
bool seenLast = false;
|
||||||
first = 0;
|
first = 0;
|
||||||
last = 0;
|
last = 0;
|
||||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
for(;;) {
|
||||||
if (el->getAttributeName(i) == "space") {
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
spc = manage->getSpaceByName(el->getAttributeValue(i));
|
if (attribId == 0) break;
|
||||||
|
if (attribId == ATTRIB_SPACE) {
|
||||||
|
string spcname = decoder.readString();
|
||||||
|
spc = manage->getSpaceByName(spcname);
|
||||||
if (spc == (AddrSpace *)0)
|
if (spc == (AddrSpace *)0)
|
||||||
throw LowlevelError("Undefined space: "+el->getAttributeValue(i));
|
throw LowlevelError("Undefined space: "+spcname);
|
||||||
}
|
}
|
||||||
else if (el->getAttributeName(i) == "first") {
|
else if (attribId == ATTRIB_FIRST) {
|
||||||
istringstream s(el->getAttributeValue(i));
|
first = decoder.readUnsignedInteger();
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> first;
|
|
||||||
}
|
}
|
||||||
else if (el->getAttributeName(i) == "last") {
|
else if (attribId == ATTRIB_LAST) {
|
||||||
istringstream s(el->getAttributeValue(i));
|
last = decoder.readUnsignedInteger();
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> last;
|
|
||||||
seenLast = true;
|
seenLast = true;
|
||||||
}
|
}
|
||||||
else if (el->getAttributeName(i) == "name") {
|
else if (attribId == ATTRIB_NAME) {
|
||||||
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
|
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
|
||||||
const VarnodeData &point(trans->getRegister(el->getAttributeValue(i)));
|
const VarnodeData &point(trans->getRegister(decoder.readString()));
|
||||||
spc = point.space;
|
spc = point.space;
|
||||||
first = point.offset;
|
first = point.offset;
|
||||||
last = (first-1) + point.size;
|
last = (first-1) + point.size;
|
||||||
@@ -316,6 +356,31 @@ void Range::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
|||||||
throw LowlevelError("Illegal range tag");
|
throw LowlevelError("Illegal range tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RangeProperties::decode(Decoder &decoder)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint4 elemId = decoder.openElement();
|
||||||
|
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
||||||
|
throw XmlError("Expecting <range> or <register> element");
|
||||||
|
for(;;) {
|
||||||
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) break;
|
||||||
|
if (attribId == ATTRIB_SPACE)
|
||||||
|
spaceName = decoder.readString();
|
||||||
|
else if (attribId == ATTRIB_FIRST)
|
||||||
|
first = decoder.readUnsignedInteger();
|
||||||
|
else if (attribId == ATTRIB_LAST) {
|
||||||
|
last = decoder.readUnsignedInteger();
|
||||||
|
seenLast = true;
|
||||||
|
}
|
||||||
|
else if (attribId == ATTRIB_NAME) {
|
||||||
|
spaceName = decoder.readString();
|
||||||
|
isRegister = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert a new Range merging as appropriate to maintain the disjoint cover
|
/// Insert a new Range merging as appropriate to maintain the disjoint cover
|
||||||
/// \param spc is the address space containing the new range
|
/// \param spc is the address space containing the new range
|
||||||
/// \param first is the offset of the first byte in the new range
|
/// \param first is the offset of the first byte in the new range
|
||||||
@@ -539,36 +604,33 @@ void RangeList::printBounds(ostream &s) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize this object to an XML \<rangelist> tag
|
/// Encode \b this as a \<rangelist> element
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void RangeList::saveXml(ostream &s) const
|
void RangeList::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
set<Range>::const_iterator iter;
|
set<Range>::const_iterator iter;
|
||||||
|
|
||||||
s << "<rangelist>\n";
|
encoder.openElement(ELEM_RANGELIST);
|
||||||
for(iter=tree.begin();iter!=tree.end();++iter) {
|
for(iter=tree.begin();iter!=tree.end();++iter) {
|
||||||
(*iter).saveXml(s);
|
(*iter).encode(encoder);
|
||||||
}
|
}
|
||||||
s << "</rangelist>\n";
|
encoder.closeElement(ELEM_RANGELIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recover each individual disjoint Range for \b this RangeList as encoded
|
/// Recover each individual disjoint Range for \b this RangeList.
|
||||||
/// in a \<rangelist> tag.
|
/// \param decoder is the stream decoder
|
||||||
/// \param el is the XML element
|
|
||||||
/// \param manage is manager for retrieving address spaces
|
/// \param manage is manager for retrieving address spaces
|
||||||
void RangeList::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void RangeList::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_RANGELIST);
|
||||||
List::const_iterator iter;
|
while(decoder.peekElement() != 0) {
|
||||||
|
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
|
||||||
const Element *subel = *iter;
|
|
||||||
Range range;
|
Range range;
|
||||||
range.restoreXml(subel,manage);
|
range.decode(decoder,manage);
|
||||||
tree.insert(range);
|
tree.insert(range);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UINTB4
|
#ifdef UINTB4
|
||||||
|
|||||||
@@ -30,6 +30,17 @@
|
|||||||
|
|
||||||
class AddrSpaceManager;
|
class AddrSpaceManager;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_FIRST; ///< Marshaling attribute "first"
|
||||||
|
extern AttributeId ATTRIB_LAST; ///< Marshaling attribute "last"
|
||||||
|
extern AttributeId ATTRIB_UNIQ; ///< Marshaling attribute "uniq"
|
||||||
|
|
||||||
|
extern ElementId ELEM_ADDR; ///< Marshaling element \<addr>
|
||||||
|
extern ElementId ELEM_RANGE; ///< Marshaling element \<range>
|
||||||
|
extern ElementId ELEM_RANGELIST; ///< Marshaling element \<rangelist>
|
||||||
|
extern ElementId ELEM_REGISTER; ///< Marshaling element \<register>
|
||||||
|
extern ElementId ELEM_SEQNUM; ///< Marshaling element \<seqnum>
|
||||||
|
extern ElementId ELEM_VARNODE; ///< Marshaling element \<varnode>
|
||||||
|
|
||||||
/// \brief A low-level machine address for labelling bytes and data.
|
/// \brief A low-level machine address for labelling bytes and data.
|
||||||
///
|
///
|
||||||
/// All data that can be manipulated within the processor reverse
|
/// All data that can be manipulated within the processor reverse
|
||||||
@@ -65,7 +76,6 @@ public:
|
|||||||
int4 read(const string &s); ///< Read in the address from a string
|
int4 read(const string &s); ///< Read in the address from a string
|
||||||
AddrSpace *getSpace(void) const; ///< Get the address space
|
AddrSpace *getSpace(void) const; ///< Get the address space
|
||||||
uintb getOffset(void) const; ///< Get the address offset
|
uintb getOffset(void) const; ///< Get the address offset
|
||||||
void toPhysical(void); ///< Convert this to a physical address
|
|
||||||
char getShortcut(void) const; ///< Get the shortcut character for the address space
|
char getShortcut(void) const; ///< Get the shortcut character for the address space
|
||||||
Address &operator=(const Address &op2); ///< Copy an address
|
Address &operator=(const Address &op2); ///< Copy an address
|
||||||
bool operator==(const Address &op2) const; ///< Compare two addresses for equality
|
bool operator==(const Address &op2) const; ///< Compare two addresses for equality
|
||||||
@@ -82,14 +92,14 @@ public:
|
|||||||
bool isConstant(void) const; ///< Is this a \e constant \e value
|
bool isConstant(void) const; ///< Is this a \e constant \e value
|
||||||
void renormalize(int4 size); ///< Make sure there is a backing JoinRecord if \b this is in the \e join space
|
void renormalize(int4 size); ///< Make sure there is a backing JoinRecord if \b this is in the \e join space
|
||||||
bool isJoin(void) const; ///< Is this a \e join \e value
|
bool isJoin(void) const; ///< Is this a \e join \e value
|
||||||
void saveXml(ostream &s) const; ///< Save this to a stream as an XML tag
|
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||||
void saveXml(ostream &s,int4 size) const; ///< Save this and a size to a stream as an XML tag
|
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 restoreXml(const Element *el,const AddrSpaceManager *manage);
|
static Address decode(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
|
|
||||||
/// Restore an address and size from parsed XML
|
/// Restore an address and size from parsed XML
|
||||||
static Address restoreXml(const Element *el,const AddrSpaceManager *manage,int4 &size);
|
static Address decode(Decoder &decoder,const AddrSpaceManager *manage,int4 &size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A class for uniquely labelling and comparing PcodeOps
|
/// \brief A class for uniquely labelling and comparing PcodeOps
|
||||||
@@ -144,16 +154,18 @@ public:
|
|||||||
return (pc < op2.pc);
|
return (pc < op2.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save a SeqNum to a stream as an XML tag
|
/// Encode a SeqNum to a stream
|
||||||
void saveXml(ostream &s) const;
|
void encode(Encoder &encoder) const;
|
||||||
|
|
||||||
/// Restore a SeqNum from parsed XML
|
/// Decode a SeqNum from a stream
|
||||||
static SeqNum restoreXml(const Element *el,const AddrSpaceManager *manage);
|
static SeqNum decode(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
|
|
||||||
/// Write out a SeqNum 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RangeProperties;
|
||||||
|
|
||||||
/// \brief A contiguous range of bytes in some address space
|
/// \brief A contiguous range of bytes in some address space
|
||||||
class Range {
|
class Range {
|
||||||
friend class RangeList;
|
friend class RangeList;
|
||||||
@@ -169,7 +181,8 @@ public:
|
|||||||
/// \param l is the offset of the last byte in the range
|
/// \param l is the offset of the last byte in the range
|
||||||
Range(AddrSpace *s,uintb f,uintb l) {
|
Range(AddrSpace *s,uintb f,uintb l) {
|
||||||
spc = s; first = f; last = l; }
|
spc = s; first = f; last = l; }
|
||||||
Range(void) {} ///< Constructor for use with restoreXml
|
Range(void) {} ///< Constructor for use with decode
|
||||||
|
Range(const RangeProperties &properties,const AddrSpaceManager *manage); ///< Construct range out of basic properties
|
||||||
AddrSpace *getSpace(void) const { return spc; } ///< Get the address space containing \b this Range
|
AddrSpace *getSpace(void) const { return spc; } ///< Get the address space containing \b this Range
|
||||||
uintb getFirst(void) const { return first; } ///< Get the offset of the first byte in \b this Range
|
uintb getFirst(void) const { return first; } ///< Get the offset of the first byte in \b this Range
|
||||||
uintb getLast(void) const { return last; } ///< Get the offset of the last byte in \b this Range
|
uintb getLast(void) const { return last; } ///< Get the offset of the last byte in \b this Range
|
||||||
@@ -188,8 +201,24 @@ public:
|
|||||||
return (spc->getIndex() < op2.spc->getIndex());
|
return (spc->getIndex() < op2.spc->getIndex());
|
||||||
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 saveXml(ostream &s) const; ///< Save \b this Range to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode \b this Range to a stream
|
||||||
void restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore \b this from XML stream
|
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Restore \b this from a stream
|
||||||
|
void decodeFromAttributes(Decoder &decoder,const AddrSpaceManager *manage); ///< Read \b from attributes on another tag
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A partially parsed description of a Range
|
||||||
|
///
|
||||||
|
/// Class that allows \<range> tags to be parsed, when the address space doesn't yet exist
|
||||||
|
class RangeProperties {
|
||||||
|
friend class Range;
|
||||||
|
string spaceName; ///< Name of the address space containing the range
|
||||||
|
uintb first; ///< Offset of first byte in the Range
|
||||||
|
uintb last; ///< Offset of last byte in the Range
|
||||||
|
bool isRegister; ///< Range is specified a register name
|
||||||
|
bool seenLast; ///< End of the range is actively specified
|
||||||
|
public:
|
||||||
|
RangeProperties(void) { first = 0; last = 0; isRegister = false; seenLast = false; }
|
||||||
|
void decode(Decoder &decoder); ///< Restore \b this from an XML stream
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A disjoint set of Ranges, possibly across multiple address spaces
|
/// \brief A disjoint set of Ranges, possibly across multiple address spaces
|
||||||
@@ -217,8 +246,8 @@ public:
|
|||||||
bool inRange(const Address &addr,int4 size) const; ///< Check containment an address range
|
bool inRange(const Address &addr,int4 size) const; ///< Check containment an address range
|
||||||
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 saveXml(ostream &s) const; ///< Write \b this RangeList to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode \b this RangeList to a stream
|
||||||
void restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore \b this RangeList from an XML stream
|
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this RangeList from a \<rangelist> element
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Precalculated masks indexed by size
|
/// Precalculated masks indexed by size
|
||||||
@@ -416,27 +445,27 @@ inline bool Address::isJoin(void) const {
|
|||||||
return (base->getType() == IPTR_JOIN);
|
return (base->getType() == IPTR_JOIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save an \b \<addr\> tag corresponding to this address to a
|
/// Save an \<addr\> element corresponding to this address to a
|
||||||
/// stream. The exact format is determined by the address space,
|
/// stream. The exact format is determined by the address space,
|
||||||
/// but this generally has a \e space and an \e offset attribute.
|
/// but this generally has a \e space and an \e offset attribute.
|
||||||
/// \param s is the stream being written to
|
/// \param encoder is the stream encoder
|
||||||
inline void Address::saveXml(ostream &s) const {
|
inline void Address::encode(Encoder &encoder) const {
|
||||||
s << "<addr";
|
encoder.openElement(ELEM_ADDR);
|
||||||
if (base!=(AddrSpace *)0)
|
if (base!=(AddrSpace *)0)
|
||||||
base->saveXmlAttributes(s,offset);
|
base->encodeAttributes(encoder,offset);
|
||||||
s << "/>";
|
encoder.closeElement(ELEM_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save an \b \<addr\> tag corresponding to this address to a
|
/// Encode an \<addr> element corresponding to this address to a
|
||||||
/// stream. The tag will also include an extra \e size attribute
|
/// stream. The tag will also include an extra \e size attribute
|
||||||
/// so that it can describe an entire memory range.
|
/// so that it can describe an entire memory range.
|
||||||
/// \param s is the stream being written to
|
/// \param encoder is the stream encoder
|
||||||
/// \param size is the number of bytes in the range
|
/// \param size is the number of bytes in the range
|
||||||
inline void Address::saveXml(ostream &s,int4 size) const {
|
inline void Address::encode(Encoder &encoder,int4 size) const {
|
||||||
s << "<addr";
|
encoder.openElement(ELEM_ADDR);
|
||||||
if (base!=(AddrSpace *)0)
|
if (base!=(AddrSpace *)0)
|
||||||
base->saveXmlAttributes(s,offset,size);
|
base->encodeAttributes(encoder,offset,size);
|
||||||
s << "/>";
|
encoder.closeElement(ELEM_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param addr is the Address to test for containment
|
/// \param addr is the Address to test for containment
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -61,6 +61,47 @@ public:
|
|||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_ADJUSTVMA; ///< Marshaling attribute "adjustvma"
|
||||||
|
extern AttributeId ATTRIB_ENABLE; ///< Marshaling attribute "enable"
|
||||||
|
extern AttributeId ATTRIB_GROUP; ///< Marshaling attribute "group"
|
||||||
|
extern AttributeId ATTRIB_GROWTH; ///< Marshaling attribute "growth"
|
||||||
|
extern AttributeId ATTRIB_LOADERSYMBOLS; ///< Marshaling attribute "loadersymbols"
|
||||||
|
extern AttributeId ATTRIB_PARENT; ///< Marshaling attribute "parent"
|
||||||
|
extern AttributeId ATTRIB_REGISTER; ///< Marshaling attribute "register"
|
||||||
|
extern AttributeId ATTRIB_REVERSEJUSTIFY; ///< Marshaling attribute "reversejustify"
|
||||||
|
extern AttributeId ATTRIB_SIGNEXT; ///< Marshaling attribute "signext"
|
||||||
|
extern AttributeId ATTRIB_STYLE; ///< Marshaling attribute "style"
|
||||||
|
|
||||||
|
extern ElementId ELEM_ADDRESS_SHIFT_AMOUNT; ///< Marshaling element \<address_shift_amount>
|
||||||
|
extern ElementId ELEM_AGGRESSIVETRIM; ///< Marshaling element \<aggressivetrim>
|
||||||
|
extern ElementId ELEM_COMPILER_SPEC; ///< Marshaling element \<compiler_spec>
|
||||||
|
extern ElementId ELEM_DATA_SPACE; ///< Marshaling element \<data_space>
|
||||||
|
extern ElementId ELEM_DEFAULT_MEMORY_BLOCKS; ///< Marshaling element \<default_memory_blocks>
|
||||||
|
extern ElementId ELEM_DEFAULT_PROTO; ///< Marshaling element \<default_proto>
|
||||||
|
extern ElementId ELEM_DEFAULT_SYMBOLS; ///< Marshaling element \<default_symbols>
|
||||||
|
extern ElementId ELEM_EVAL_CALLED_PROTOTYPE; ///< Marshaling element \<eval_called_prototype>
|
||||||
|
extern ElementId ELEM_EVAL_CURRENT_PROTOTYPE; ///< Marshaling element \<eval_current_prototype>
|
||||||
|
extern ElementId ELEM_EXPERIMENTAL_RULES; ///< Marshaling element \<experimental_rules>
|
||||||
|
extern ElementId ELEM_FLOWOVERRIDELIST; ///< Marshaling element \<flowoverridelist>
|
||||||
|
extern ElementId ELEM_FUNCPTR; ///< Marshaling element \<funcptr>
|
||||||
|
extern ElementId ELEM_GLOBAL; ///< Marshaling element \<global>
|
||||||
|
extern ElementId ELEM_INCIDENTALCOPY; ///< Marshaling element \<incidentalcopy>
|
||||||
|
extern ElementId ELEM_INFERPTRBOUNDS; ///< Marshaling element \<inferptrbounds>
|
||||||
|
extern ElementId ELEM_MODELALIAS; ///< Marshaling element \<modelalias>
|
||||||
|
extern ElementId ELEM_NOHIGHPTR; ///< Marshaling element \<nohighptr>
|
||||||
|
extern ElementId ELEM_PROCESSOR_SPEC; ///< Marshaling element \<processor_spec>
|
||||||
|
extern ElementId ELEM_PROGRAMCOUNTER; ///< Marshaling element \<programcounter>
|
||||||
|
extern ElementId ELEM_PROPERTIES; ///< Marshaling element \<properties>
|
||||||
|
extern ElementId ELEM_READONLY; ///< Marshaling element \<readonly>
|
||||||
|
extern ElementId ELEM_REGISTER_DATA; ///< Marshaling element \<register_data>
|
||||||
|
extern ElementId ELEM_RULE; ///< Marshaling element \<rule>
|
||||||
|
extern ElementId ELEM_SAVE_STATE; ///< Marshaling element \<save_state>
|
||||||
|
extern ElementId ELEM_SEGMENTED_ADDRESS; ///< Marshaling element \<segmented_address>
|
||||||
|
extern ElementId ELEM_SPACEBASE; ///< Marshaling element \<spacebase>
|
||||||
|
extern ElementId ELEM_SPECEXTENSIONS; ///< Marshaling element \<specextensions>
|
||||||
|
extern ElementId ELEM_STACKPOINTER; ///< Marshaling element \<stackpointer>
|
||||||
|
extern ElementId ELEM_VOLATILE; ///< Marshaling element \<volatile>
|
||||||
|
|
||||||
/// \brief Abstract extension point for building Architecture objects
|
/// \brief Abstract extension point for building Architecture objects
|
||||||
///
|
///
|
||||||
/// Decompilation hinges on initially recognizing the format of code then
|
/// Decompilation hinges on initially recognizing the format of code then
|
||||||
@@ -185,7 +226,7 @@ public:
|
|||||||
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
|
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
|
||||||
void setPrintLanguage(const string &nm); ///< Establish a particular output language
|
void setPrintLanguage(const string &nm); ///< Establish a particular output language
|
||||||
void globalify(void); ///< Mark \e all spaces as global
|
void globalify(void); ///< Mark \e all spaces as global
|
||||||
void restoreFlowOverride(const Element *el); ///< Set flow overrides from XML
|
void decodeFlowOverride(Decoder &decoder); ///< Set flow overrides from XML
|
||||||
virtual ~Architecture(void); ///< Destructor
|
virtual ~Architecture(void); ///< Destructor
|
||||||
|
|
||||||
virtual string getDescription(void) const { return archid; } ///< Get a string describing \b this architecture
|
virtual string getDescription(void) const { return archid; } ///< Get a string describing \b this architecture
|
||||||
@@ -195,8 +236,8 @@ public:
|
|||||||
/// Write the given message to whatever the registered error stream is
|
/// Write the given message to whatever the registered error stream is
|
||||||
/// \param message is the error message
|
/// \param message is the error message
|
||||||
virtual void printMessage(const string &message) const=0;
|
virtual void printMessage(const string &message) const=0;
|
||||||
virtual void saveXml(ostream &s) const; ///< Serialize this architecture to XML
|
virtual void encode(Encoder &encoder) const; ///< Encode \b this architecture to a stream
|
||||||
virtual void restoreXml(DocumentStorage &store); ///< Restore the Architecture state from an XML stream
|
virtual void restoreXml(DocumentStorage &store); ///< Restore the Architecture state from XML documents
|
||||||
virtual void nameFunction(const Address &addr,string &name) const; ///< Pick a default name for a function
|
virtual void nameFunction(const Address &addr,string &name) const; ///< Pick a default name for a function
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
void setDebugStream(ostream *s) { debugstream = s; } ///< Establish the debug console stream
|
void setDebugStream(ostream *s) { debugstream = s; } ///< Establish the debug console stream
|
||||||
@@ -264,25 +305,26 @@ protected:
|
|||||||
void parseCompilerConfig(DocumentStorage &store); ///< Apply compiler specific configuration
|
void parseCompilerConfig(DocumentStorage &store); ///< Apply compiler specific configuration
|
||||||
void parseExtraRules(DocumentStorage &store); ///< Apply any Rule tags
|
void parseExtraRules(DocumentStorage &store); ///< Apply any Rule tags
|
||||||
|
|
||||||
void parseDynamicRule(const Element *el); ///< Apply details of a dynamic Rule object
|
void decodeDynamicRule(Decoder &decoder); ///< Apply details of a dynamic Rule object
|
||||||
ProtoModel *parseProto(const Element *el); ///< Build a proto-type model from an XML tag
|
ProtoModel *decodeProto(Decoder &decoder); ///< Parse a proto-type model from a stream
|
||||||
void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration
|
void decodeProtoEval(Decoder &decoder); ///< Apply prototype evaluation configuration
|
||||||
void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration
|
void decodeDefaultProto(Decoder &decoder); ///< Apply default prototype model configuration
|
||||||
void parseGlobal(const Element *el); ///< Apply global space configuration
|
void decodeGlobal(Decoder &decoder,vector<RangeProperties> &rangeProps); ///< Parse information about global ranges
|
||||||
|
void addToGlobalScope(const RangeProperties &props); ///< Add a memory range to the set of addresses considered \e global
|
||||||
void addOtherSpace(void); ///< Add OTHER space and all of its overlays to the symboltab
|
void addOtherSpace(void); ///< Add OTHER space and all of its overlays to the symboltab
|
||||||
void parseReadOnly(const Element *el); ///< Apply read-only region configuration
|
void decodeReadOnly(Decoder &decoder); ///< Apply read-only region configuration
|
||||||
void parseVolatile(const Element *el); ///< Apply volatile region configuration
|
void decodeVolatile(Decoder &decoder); ///< Apply volatile region configuration
|
||||||
void parseReturnAddress(const Element *el); ///< Apply return address configuration
|
void decodeReturnAddress(Decoder &decoder); ///< Apply return address configuration
|
||||||
void parseIncidentalCopy(const Element *el); ///< Apply incidental copy configuration
|
void decodeIncidentalCopy(Decoder &decoder); ///< Apply incidental copy configuration
|
||||||
void parseLaneSizes(const Element *el); ///< Apply lane size configuration
|
void decodeLaneSizes(Decoder &decoder); ///< Apply lane size configuration
|
||||||
void parseStackPointer(const Element *el); ///< Apply stack pointer configuration
|
void decodeStackPointer(Decoder &decoder); ///< Apply stack pointer configuration
|
||||||
void parseDeadcodeDelay(const Element *el); ///< Apply dead-code delay configuration
|
void decodeDeadcodeDelay(Decoder &decoder); ///< Apply dead-code delay configuration
|
||||||
void parseInferPtrBounds(const Element *el); ///< Apply pointer inference bounds
|
void decodeInferPtrBounds(Decoder &decoder); ///< Apply pointer inference bounds
|
||||||
void parseFuncPtrAlign(const Element *el); ///< Apply function pointer alignment configuration
|
void decodeFuncPtrAlign(Decoder &decoder); ///< Apply function pointer alignment configuration
|
||||||
void parseSpacebase(const Element *el); ///< Create an additional indexed space
|
void decodeSpacebase(Decoder &decoder); ///< Create an additional indexed space
|
||||||
void parseNoHighPtr(const Element *el); ///< Apply memory alias configuration
|
void decodeNoHighPtr(Decoder &decoder); ///< Apply memory alias configuration
|
||||||
void parsePreferSplit(const Element *el); ///< Designate registers to be split
|
void decodePreferSplit(Decoder &decoder); ///< Designate registers to be split
|
||||||
void parseAggressiveTrim(const Element *el); ///< Designate how to trim extension p-code ops
|
void decodeAggressiveTrim(Decoder &decoder); ///< Designate how to trim extension p-code ops
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A resolver for segmented architectures
|
/// \brief A resolver for segmented architectures
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
// Constructing this object registers capability
|
// Constructing this object registers capability
|
||||||
BfdArchitectureCapability BfdArchitectureCapability::bfdArchitectureCapability;
|
BfdArchitectureCapability BfdArchitectureCapability::bfdArchitectureCapability;
|
||||||
|
|
||||||
|
ElementId ELEM_BFD_SAVEFILE = ElementId("bfd_savefile",46);
|
||||||
|
|
||||||
BfdArchitectureCapability::BfdArchitectureCapability(void)
|
BfdArchitectureCapability::BfdArchitectureCapability(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -125,16 +127,15 @@ BfdArchitecture::BfdArchitecture(const string &fname,const string &targ,ostream
|
|||||||
adjustvma = 0;
|
adjustvma = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfdArchitecture::saveXml(ostream &s) const
|
void BfdArchitecture::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{ // prepend extra stuff to specify binary file and spec
|
{ // prepend extra stuff to specify binary file and spec
|
||||||
s << "<bfd_savefile";
|
encoder.openElement(ELEM_BFD_SAVEFILE);
|
||||||
saveXmlHeader(s);
|
encodeHeader(encoder);
|
||||||
a_v_u(s,"adjustvma",adjustvma);
|
encoder.writeUnsignedInteger(ATTRIB_ADJUSTVMA, adjustvma);
|
||||||
s << ">\n";
|
types->encodeCoreTypes(encoder);
|
||||||
types->saveXmlCoreTypes(s);
|
SleighArchitecture::encode(encoder); // Save the rest of the state
|
||||||
SleighArchitecture::saveXml(s); // Save the rest of the state
|
encoder.closeElement(ELEM_BFD_SAVEFILE);
|
||||||
s << "</bfd_savefile>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfdArchitecture::restoreXml(DocumentStorage &store)
|
void BfdArchitecture::restoreXml(DocumentStorage &store)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include "sleigh_arch.hh"
|
#include "sleigh_arch.hh"
|
||||||
#include "loadimage_bfd.hh"
|
#include "loadimage_bfd.hh"
|
||||||
|
|
||||||
|
extern ElementId ELEM_BFD_SAVEFILE; ///< Marshaling element \<bfd_savefile>
|
||||||
|
|
||||||
/// \brief Extension point for building a GNU BFD capable Architecture
|
/// \brief Extension point for building a GNU BFD capable Architecture
|
||||||
class BfdArchitectureCapability : public ArchitectureCapability {
|
class BfdArchitectureCapability : public ArchitectureCapability {
|
||||||
static BfdArchitectureCapability bfdArchitectureCapability; ///< The singleton instance
|
static BfdArchitectureCapability bfdArchitectureCapability; ///< The singleton instance
|
||||||
@@ -40,7 +42,7 @@ class BfdArchitecture : public SleighArchitecture {
|
|||||||
virtual void resolveArchitecture(void);
|
virtual void resolveArchitecture(void);
|
||||||
virtual void postSpecFile(void);
|
virtual void postSpecFile(void);
|
||||||
public:
|
public:
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(DocumentStorage &store);
|
virtual void restoreXml(DocumentStorage &store);
|
||||||
BfdArchitecture(const string &fname,const string &targ,ostream *estream); ///< Constructor
|
BfdArchitecture(const string &fname,const string &targ,ostream *estream); ///< Constructor
|
||||||
virtual ~BfdArchitecture(void) {}
|
virtual ~BfdArchitecture(void) {}
|
||||||
|
|||||||
@@ -17,34 +17,43 @@
|
|||||||
#include "block.hh"
|
#include "block.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
/// The edge is saved assuming we already know what block we are in
|
AttributeId ATTRIB_ALTINDEX = AttributeId("altindex",40);
|
||||||
/// \param s is the output stream
|
AttributeId ATTRIB_DEPTH = AttributeId("depth",41);
|
||||||
void BlockEdge::saveXml(ostream &s) const
|
AttributeId ATTRIB_END = AttributeId("end",42);
|
||||||
|
AttributeId ATTRIB_OPCODE = AttributeId("opcode",43);
|
||||||
|
AttributeId ATTRIB_REV = AttributeId("rev",44);
|
||||||
|
|
||||||
|
ElementId ELEM_BHEAD = ElementId("bhead",47);
|
||||||
|
ElementId ELEM_BLOCK = ElementId("block",48);
|
||||||
|
ElementId ELEM_BLOCKEDGE = ElementId("blockedge",49);
|
||||||
|
ElementId ELEM_EDGE = ElementId("edge",50);
|
||||||
|
|
||||||
|
/// The edge is saved assuming we already know what block we are in.
|
||||||
|
/// \param encoder is the stream encoder
|
||||||
|
void BlockEdge::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<edge";
|
encoder.openElement(ELEM_EDGE);
|
||||||
// We are not saving label currently
|
// We are not saving label currently
|
||||||
a_v_i(s,"end",point->getIndex()); // Reference to other end of edge
|
encoder.writeSignedInteger(ATTRIB_END, point->getIndex()); // Reference to other end of edge
|
||||||
a_v_i(s,"rev",reverse_index); // Position within other blocks edgelist
|
encoder.writeSignedInteger(ATTRIB_REV, reverse_index); // Position within other blocks edgelist
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_EDGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param el is the \<edge> tag
|
/// Parse an \<edge> element
|
||||||
|
/// \param decoder is the stream decoder
|
||||||
/// \param resolver is used to cross-reference the edge's FlowBlock endpoints
|
/// \param resolver is used to cross-reference the edge's FlowBlock endpoints
|
||||||
void BlockEdge::restoreXml(const Element *el,BlockMap &resolver)
|
void BlockEdge::decode(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
uint4 elemId = decoder.openElement(ELEM_EDGE);
|
||||||
label = 0; // Tag does not currently contain info about label
|
label = 0; // Tag does not currently contain info about label
|
||||||
int4 endIndex;
|
int4 endIndex = decoder.readSignedInteger(ATTRIB_END);
|
||||||
istringstream s(el->getAttributeValue("end"));
|
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> endIndex;
|
|
||||||
point = resolver.findLevelBlock(endIndex);
|
point = resolver.findLevelBlock(endIndex);
|
||||||
if (point == (FlowBlock *)0)
|
if (point == (FlowBlock *)0)
|
||||||
throw LowlevelError("Bad serialized edge in block graph");
|
throw LowlevelError("Bad serialized edge in block graph");
|
||||||
istringstream s2(el->getAttributeValue("rev"));
|
reverse_index = decoder.readSignedInteger(ATTRIB_REV);
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
decoder.closeElement(elemId);
|
||||||
s2 >> reverse_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowBlock::FlowBlock(void)
|
FlowBlock::FlowBlock(void)
|
||||||
@@ -68,14 +77,15 @@ void FlowBlock::addInEdge(FlowBlock *b,uint4 lab)
|
|||||||
b->outofthis.push_back(BlockEdge(this,lab,brev));
|
b->outofthis.push_back(BlockEdge(this,lab,brev));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param el is the \<edge> element
|
/// Parse the next \<edge> element in the stream
|
||||||
|
/// \param decoder is the stream decoder
|
||||||
/// \param resolver is used to resolve block references
|
/// \param resolver is used to resolve block references
|
||||||
void FlowBlock::restoreNextInEdge(const Element *el,BlockMap &resolver)
|
void FlowBlock::decodeNextInEdge(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
intothis.emplace_back();
|
intothis.emplace_back();
|
||||||
BlockEdge &inedge(intothis.back());
|
BlockEdge &inedge(intothis.back());
|
||||||
inedge.restoreXml(el,resolver);
|
inedge.decode(decoder,resolver);
|
||||||
while(inedge.point->outofthis.size() <= inedge.reverse_index)
|
while(inedge.point->outofthis.size() <= inedge.reverse_index)
|
||||||
inedge.point->outofthis.emplace_back();
|
inedge.point->outofthis.emplace_back();
|
||||||
BlockEdge &outedge(inedge.point->outofthis[inedge.reverse_index]);
|
BlockEdge &outedge(inedge.point->outofthis[inedge.reverse_index]);
|
||||||
@@ -621,7 +631,7 @@ JumpTable *FlowBlock::getJumptable(void) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Given a string describing a FlowBlock type, return the block_type.
|
/// Given a string describing a FlowBlock type, return the block_type.
|
||||||
/// This is currently only used by the restoreXml() process.
|
/// This is currently only used by the decode() process.
|
||||||
/// TODO: Fill in the remaining names and types
|
/// TODO: Fill in the remaining names and types
|
||||||
/// \param nm is the name string
|
/// \param nm is the name string
|
||||||
/// \return the corresponding block_type
|
/// \return the corresponding block_type
|
||||||
@@ -1286,14 +1296,14 @@ void BlockGraph::finalizePrinting(Funcdata &data) const
|
|||||||
(*iter)->finalizePrinting(data);
|
(*iter)->finalizePrinting(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockGraph::saveXmlBody(ostream &s) const
|
void BlockGraph::encodeBody(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
FlowBlock::saveXmlBody(s);
|
FlowBlock::encodeBody(encoder);
|
||||||
for(int4 i=0;i<list.size();++i) {
|
for(int4 i=0;i<list.size();++i) {
|
||||||
FlowBlock *bl = list[i];
|
FlowBlock *bl = list[i];
|
||||||
s << "<bhead";
|
encoder.openElement(ELEM_BHEAD);
|
||||||
a_v_i(s,"index",bl->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, bl->getIndex());
|
||||||
FlowBlock::block_type bt = bl->getType();
|
FlowBlock::block_type bt = bl->getType();
|
||||||
string nm;
|
string nm;
|
||||||
if (bt == FlowBlock::t_if) {
|
if (bt == FlowBlock::t_if) {
|
||||||
@@ -1307,54 +1317,47 @@ void BlockGraph::saveXmlBody(ostream &s) const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
nm = FlowBlock::typeToName(bt);
|
nm = FlowBlock::typeToName(bt);
|
||||||
a_v(s,"type",nm);
|
encoder.writeString(ATTRIB_TYPE, nm);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_BHEAD);
|
||||||
}
|
}
|
||||||
for(int4 i=0;i<list.size();++i)
|
for(int4 i=0;i<list.size();++i)
|
||||||
list[i]->saveXml(s);
|
list[i]->encode(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockGraph::restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver)
|
void BlockGraph::decodeBody(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockMap newresolver(resolver);
|
BlockMap newresolver(resolver);
|
||||||
FlowBlock::restoreXmlBody(iter,enditer,newresolver);
|
|
||||||
vector<FlowBlock *> tmplist;
|
vector<FlowBlock *> tmplist;
|
||||||
|
|
||||||
while(iter != enditer) {
|
for(;;) {
|
||||||
const Element *el = *iter;
|
uint4 subId = decoder.peekElement();
|
||||||
if (el->getName() != "bhead") break;
|
if (subId != ELEM_BHEAD) break;
|
||||||
++iter;
|
decoder.openElement();
|
||||||
int4 newindex;
|
int4 newindex = decoder.readSignedInteger(ATTRIB_INDEX);
|
||||||
istringstream s(el->getAttributeValue("index"));
|
FlowBlock *bl = newresolver.createBlock(decoder.readString(ATTRIB_TYPE));
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> newindex;
|
|
||||||
const string &nm( el->getAttributeValue("type") );
|
|
||||||
FlowBlock *bl = newresolver.createBlock(nm);
|
|
||||||
bl->index = newindex; // Need to set index here for sort
|
bl->index = newindex; // Need to set index here for sort
|
||||||
tmplist.push_back(bl);
|
tmplist.push_back(bl);
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
newresolver.sortList();
|
newresolver.sortList();
|
||||||
|
|
||||||
for(int4 i=0;i<tmplist.size();++i) {
|
for(int4 i=0;i<tmplist.size();++i) {
|
||||||
if (iter == enditer)
|
|
||||||
throw LowlevelError("Bad BlockGraph xml");
|
|
||||||
FlowBlock *bl = tmplist[i];
|
FlowBlock *bl = tmplist[i];
|
||||||
bl->restoreXml(*iter,newresolver);
|
bl->decode(decoder,newresolver);
|
||||||
addBlock(bl);
|
addBlock(bl);
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is currently just a wrapper around the FlowBlock::restoreXml()
|
/// Parse a \<block> element. This is currently just a wrapper around the
|
||||||
/// that sets of the BlockMap resolver
|
/// FlowBlock::decode() that sets of the BlockMap resolver
|
||||||
/// \param el is the root \<block> tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param m is the address space manager
|
/// \param m is the address space manager
|
||||||
void BlockGraph::restoreXml(const Element *el,const AddrSpaceManager *m)
|
void BlockGraph::decode(Decoder &decoder,const AddrSpaceManager *m)
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockMap resolver(m);
|
BlockMap resolver(m);
|
||||||
FlowBlock::restoreXml(el,resolver);
|
FlowBlock::decode(decoder,resolver);
|
||||||
// Restore goto references here
|
// Restore goto references here
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2353,77 +2356,70 @@ bool BlockBasic::isComplex(void) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void FlowBlock::saveXmlHeader(ostream &s) const
|
void FlowBlock::encodeHeader(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
a_v_i(s,"index",index);
|
encoder.writeSignedInteger(ATTRIB_INDEX, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param el is the XML element to pull attributes from
|
/// \param decoder is the stream decoder to pull attributes from
|
||||||
void FlowBlock::restoreXmlHeader(const Element *el)
|
void FlowBlock::decodeHeader(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
istringstream s(el->getAttributeValue("index"));
|
index = decoder.readSignedInteger(ATTRIB_INDEX);
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write \<edge> tags to stream
|
/// Write \<edge> element to a stream
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void FlowBlock::saveXmlEdges(ostream &s) const
|
void FlowBlock::encodeEdges(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
for(int4 i=0;i<intothis.size();++i) {
|
for(int4 i=0;i<intothis.size();++i) {
|
||||||
intothis[i].saveXml(s);
|
intothis[i].encode(encoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Restore edges from an XML stream
|
/// \brief Restore edges from an encoded stream
|
||||||
///
|
///
|
||||||
/// \param iter is an iterator to the \<edge> tags
|
/// \param decoder is the stream decoder
|
||||||
/// \param enditer marks the end of the list of tags
|
|
||||||
/// \param resolver is used to recover FlowBlock cross-references
|
/// \param resolver is used to recover FlowBlock cross-references
|
||||||
void FlowBlock::restoreXmlEdges(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver)
|
void FlowBlock::decodeEdges(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
while(iter != enditer) {
|
for(;;) {
|
||||||
const Element *el = *iter;
|
uint4 subId = decoder.peekElement();
|
||||||
if (el->getName() != "edge")
|
if (subId != ELEM_EDGE)
|
||||||
return;
|
break;
|
||||||
++iter;
|
decodeNextInEdge(decoder,resolver);
|
||||||
restoreNextInEdge(el,resolver);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize \b this and all its sub-components as an XML \<block> tag.
|
/// Encode \b this and all its sub-components as a \<block> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void FlowBlock::saveXml(ostream &s) const
|
void FlowBlock::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<block";
|
encoder.openElement(ELEM_BLOCK);
|
||||||
saveXmlHeader(s);
|
encodeHeader(encoder);
|
||||||
s << ">\n";
|
encodeBody(encoder);
|
||||||
saveXmlBody(s);
|
encodeEdges(encoder);
|
||||||
saveXmlEdges(s);
|
encoder.closeElement(ELEM_BLOCK);
|
||||||
s << "</block>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recover \b this and all it sub-components from an XML \<block> tag.
|
/// Recover \b this and all it sub-components from a \<block> element.
|
||||||
///
|
///
|
||||||
/// This will construct all the sub-components using \b resolver as a factory.
|
/// This will construct all the sub-components using \b resolver as a factory.
|
||||||
/// \param el is the root XML element
|
/// \param decoder is the stream decoder
|
||||||
/// \param resolver acts as a factory and resolves cross-references
|
/// \param resolver acts as a factory and resolves cross-references
|
||||||
void FlowBlock::restoreXml(const Element *el,BlockMap &resolver)
|
void FlowBlock::decode(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
restoreXmlHeader(el);
|
uint4 elemId = decoder.openElement(ELEM_BLOCK);
|
||||||
const List &list(el->getChildren());
|
decodeHeader(decoder);
|
||||||
List::const_iterator iter;
|
decodeBody(decoder,resolver);
|
||||||
|
decodeEdges(decoder,resolver);
|
||||||
iter = list.begin();
|
decoder.closeElement(elemId);
|
||||||
restoreXmlBody(iter,list.end(),resolver);
|
|
||||||
restoreXmlEdges(iter,list.end(),resolver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If there are two branches, pick the fall-thru branch
|
/// If there are two branches, pick the fall-thru branch
|
||||||
@@ -2560,17 +2556,16 @@ void BlockBasic::setOrder(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockBasic::saveXmlBody(ostream &s) const
|
void BlockBasic::encodeBody(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
cover.saveXml(s);
|
cover.encode(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockBasic::restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver)
|
void BlockBasic::decodeBody(Decoder &decoder,BlockMap &resolver)
|
||||||
|
|
||||||
{
|
{
|
||||||
cover.restoreXml(*iter, resolver.getAddressManager());
|
cover.decode(decoder, resolver.getAddressManager());
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockBasic::printHeader(ostream &s) const
|
void BlockBasic::printHeader(ostream &s) const
|
||||||
@@ -2635,12 +2630,12 @@ void BlockCopy::printTree(ostream &s,int4 level) const
|
|||||||
copy->printTree(s,level);
|
copy->printTree(s,level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockCopy::saveXmlHeader(ostream &s) const
|
void BlockCopy::encodeHeader(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
FlowBlock::saveXmlHeader(s);
|
FlowBlock::encodeHeader(encoder);
|
||||||
int4 altindex = copy->getIndex();
|
int4 altindex = copy->getIndex();
|
||||||
a_v_i(s,"altindex",altindex);
|
encoder.writeSignedInteger(ATTRIB_ALTINDEX, altindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockGoto::markUnstructured(void)
|
void BlockGoto::markUnstructured(void)
|
||||||
@@ -2692,17 +2687,17 @@ FlowBlock *BlockGoto::nextFlowAfter(const FlowBlock *bl) const
|
|||||||
return getGotoTarget()->getFrontLeaf();
|
return getGotoTarget()->getFrontLeaf();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockGoto::saveXmlBody(ostream &s) const
|
void BlockGoto::encodeBody(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockGraph::saveXmlBody(s);
|
BlockGraph::encodeBody(encoder);
|
||||||
s << "<target";
|
encoder.openElement(ELEM_TARGET);
|
||||||
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
||||||
int4 depth = gototarget->calcDepth(leaf);
|
int4 depth = gototarget->calcDepth(leaf);
|
||||||
a_v_i(s,"index",leaf->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, leaf->getIndex());
|
||||||
a_v_i(s,"depth",depth);
|
encoder.writeSignedInteger(ATTRIB_DEPTH, depth);
|
||||||
a_v_u(s,"type",gototype);
|
encoder.writeUnsignedInteger(ATTRIB_TYPE, gototype);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockMultiGoto::scopeBreak(int4 curexit,int4 curloopexit)
|
void BlockMultiGoto::scopeBreak(int4 curexit,int4 curloopexit)
|
||||||
@@ -2725,18 +2720,18 @@ FlowBlock *BlockMultiGoto::nextFlowAfter(const FlowBlock *bl) const
|
|||||||
return (FlowBlock *)0;
|
return (FlowBlock *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockMultiGoto::saveXmlBody(ostream &s) const
|
void BlockMultiGoto::encodeBody(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockGraph::saveXmlBody(s);
|
BlockGraph::encodeBody(encoder);
|
||||||
for(int4 i=0;i<gotoedges.size();++i) {
|
for(int4 i=0;i<gotoedges.size();++i) {
|
||||||
FlowBlock *gototarget = gotoedges[i];
|
FlowBlock *gototarget = gotoedges[i];
|
||||||
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
||||||
int4 depth = gototarget->calcDepth(leaf);
|
int4 depth = gototarget->calcDepth(leaf);
|
||||||
s << "<target";
|
encoder.openElement(ELEM_TARGET);
|
||||||
a_v_i(s,"index",leaf->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, leaf->getIndex());
|
||||||
a_v_i(s,"depth",depth);
|
encoder.writeSignedInteger(ATTRIB_DEPTH, depth);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_TARGET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2846,12 +2841,12 @@ FlowBlock *BlockCondition::nextFlowAfter(const FlowBlock *bl) const
|
|||||||
return (FlowBlock *)0; // Do not know where flow goes
|
return (FlowBlock *)0; // Do not know where flow goes
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockCondition::saveXmlHeader(ostream &s) const
|
void BlockCondition::encodeHeader(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockGraph::saveXmlHeader(s);
|
BlockGraph::encodeHeader(encoder);
|
||||||
string nm(get_opname(opc));
|
string nm(get_opname(opc));
|
||||||
a_v(s,"opcode",nm);
|
encoder.writeString(ATTRIB_OPCODE, nm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockIf::markUnstructured(void)
|
void BlockIf::markUnstructured(void)
|
||||||
@@ -2924,18 +2919,18 @@ FlowBlock *BlockIf::nextFlowAfter(const FlowBlock *bl) const
|
|||||||
return getParent()->nextFlowAfter(this);
|
return getParent()->nextFlowAfter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockIf::saveXmlBody(ostream &s) const
|
void BlockIf::encodeBody(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockGraph::saveXmlBody(s);
|
BlockGraph::encodeBody(encoder);
|
||||||
if (getSize() == 1) { // If this is a if GOTO block
|
if (getSize() == 1) { // If this is a if GOTO block
|
||||||
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
const FlowBlock *leaf = gototarget->getFrontLeaf();
|
||||||
int4 depth = gototarget->calcDepth(leaf);
|
int4 depth = gototarget->calcDepth(leaf);
|
||||||
s << "<target";
|
encoder.openElement(ELEM_TARGET);
|
||||||
a_v_i(s,"index",leaf->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, leaf->getIndex());
|
||||||
a_v_i(s,"depth",depth);
|
encoder.writeSignedInteger(ATTRIB_DEPTH, depth);
|
||||||
a_v_u(s,"type",gototype);
|
encoder.writeUnsignedInteger(ATTRIB_TYPE, gototype);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_TARGET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,17 @@ class BlockSwitch;
|
|||||||
class PrintLanguage;
|
class PrintLanguage;
|
||||||
class BlockMap;
|
class BlockMap;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_ALTINDEX; ///< Marshaling attribute "altindex"
|
||||||
|
extern AttributeId ATTRIB_DEPTH; ///< Marshaling attribute "depth"
|
||||||
|
extern AttributeId ATTRIB_END; ///< Marshaling attribute "end"
|
||||||
|
extern AttributeId ATTRIB_OPCODE; ///< Marshaling attribute "opcode"
|
||||||
|
extern AttributeId ATTRIB_REV; ///< Marshaling attribute "rev"
|
||||||
|
|
||||||
|
extern ElementId ELEM_BHEAD; ///< Marshaling element \<bhead>
|
||||||
|
extern ElementId ELEM_BLOCK; ///< Marshaling element \<block>
|
||||||
|
extern ElementId ELEM_BLOCKEDGE; ///< Marshaling element \<blockedge>
|
||||||
|
extern ElementId ELEM_EDGE; ///< Marshaling element \<edge>
|
||||||
|
|
||||||
/// \brief A control-flow edge between blocks (FlowBlock)
|
/// \brief A control-flow edge between blocks (FlowBlock)
|
||||||
///
|
///
|
||||||
/// The edge is owned by the source block and can have FlowBlock::edge_flags
|
/// The edge is owned by the source block and can have FlowBlock::edge_flags
|
||||||
@@ -45,10 +56,10 @@ struct BlockEdge {
|
|||||||
uint4 label; ///< Label of the edge
|
uint4 label; ///< Label of the edge
|
||||||
FlowBlock *point; ///< Other end of the edge
|
FlowBlock *point; ///< Other end of the edge
|
||||||
int4 reverse_index; ///< Index for edge coming other way
|
int4 reverse_index; ///< Index for edge coming other way
|
||||||
BlockEdge(void) {} ///< Constructor for use with restoreXml
|
BlockEdge(void) {} ///< Constructor for use with decode
|
||||||
BlockEdge(FlowBlock *pt,uint4 lab,int4 rev) { label=lab; point=pt; reverse_index = rev; } ///< Constructor
|
BlockEdge(FlowBlock *pt,uint4 lab,int4 rev) { label=lab; point=pt; reverse_index = rev; } ///< Constructor
|
||||||
void saveXml(ostream &s) const; ///< Save the edge to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode \b this edge to a stream
|
||||||
void restoreXml(const Element *el,BlockMap &resolver); ///< Restore \b this edge from an XML stream
|
void decode(Decoder &decoder,BlockMap &resolver); ///< Restore \b this edge from a stream
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Description of a control-flow block containing PcodeOps
|
/// \brief Description of a control-flow block containing PcodeOps
|
||||||
@@ -119,7 +130,7 @@ private:
|
|||||||
// the result of the condition being false
|
// the result of the condition being false
|
||||||
static void replaceEdgeMap(vector<BlockEdge> &vec); ///< Update block references in edges with copy map
|
static void replaceEdgeMap(vector<BlockEdge> &vec); ///< Update block references in edges with copy map
|
||||||
void addInEdge(FlowBlock *b,uint4 lab); ///< Add an edge coming into \b this
|
void addInEdge(FlowBlock *b,uint4 lab); ///< Add an edge coming into \b this
|
||||||
void restoreNextInEdge(const Element *el,BlockMap &resolver); ///< Restore the next input edge from XML
|
void decodeNextInEdge(Decoder &decoder,BlockMap &resolver); ///< Restore the next input edge from XML
|
||||||
void halfDeleteInEdge(int4 slot); ///< Delete the \e in half of an edge, correcting indices
|
void halfDeleteInEdge(int4 slot); ///< Delete the \e in half of an edge, correcting indices
|
||||||
void halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices
|
void halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices
|
||||||
void removeInEdge(int4 slot); ///< Remove an incoming edge
|
void removeInEdge(int4 slot); ///< Remove an incoming edge
|
||||||
@@ -172,20 +183,19 @@ public:
|
|||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void finalTransform(Funcdata &data) {} ///< Do any structure driven final transforms
|
virtual void finalTransform(Funcdata &data) {} ///< Do any structure driven final transforms
|
||||||
virtual void finalizePrinting(Funcdata &data) const {} ///< Make any final configurations necessary to print the block
|
virtual void finalizePrinting(Funcdata &data) const {} ///< Make any final configurations necessary to print the block
|
||||||
virtual void saveXmlHeader(ostream &s) const; ///< Save basic information as XML attributes
|
virtual void encodeHeader(Encoder &encoder) const; ///< Encode basic information as attributes
|
||||||
virtual void restoreXmlHeader(const Element *el); ///< Restore basic information for XML attributes
|
virtual void decodeHeader(Decoder &decoder); ///< Decode basic information from element attributes
|
||||||
virtual void saveXmlBody(ostream &s) const {} ///< Save detail about components to an XML stream
|
virtual void encodeBody(Encoder &encoder) const {} ///< Encode detail about components to a stream
|
||||||
|
|
||||||
/// \brief Restore details about \b this FlowBlock from an XML stream
|
/// \brief Restore details about \b this FlowBlock from an element stream
|
||||||
///
|
///
|
||||||
/// \param iter is an iterator to XML elements containing component tags etc.
|
/// \param decoder is the stream decoder
|
||||||
/// \param enditer marks the end of the XML tags
|
/// \param resolver is used to recover FlowBlock objects based on elment references
|
||||||
/// \param resolver is used to recover FlowBlock objects based on XML references
|
virtual void decodeBody(Decoder &decoder,BlockMap &resolver) {}
|
||||||
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver) {}
|
void encodeEdges(Encoder &encoder) const; ///< Encode edge information to a stream
|
||||||
void saveXmlEdges(ostream &s) const; ///< Save edge information to an XML stream
|
void decodeEdges(Decoder &decoder,BlockMap &resolver);
|
||||||
void restoreXmlEdges(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
|
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||||
void saveXml(ostream &s) const; ///< Write out \b this to an XML stream
|
void decode(Decoder &decoder,BlockMap &resolver); ///< Decode \b this from a stream
|
||||||
void restoreXml(const Element *el,BlockMap &resolver); ///< Restore \b this from an XML stream
|
|
||||||
const FlowBlock *nextInFlow(void) const; ///< Return next block to be executed in flow
|
const FlowBlock *nextInFlow(void) const; ///< Return next block to be executed in flow
|
||||||
void setVisitCount(int4 i) { visitcount = i; } ///< Set the number of times this block has been visited
|
void setVisitCount(int4 i) { visitcount = i; } ///< Set the number of times this block has been visited
|
||||||
int4 getVisitCount(void) const { return visitcount; } ///< Get the count of visits
|
int4 getVisitCount(void) const { return visitcount; } ///< Get the count of visits
|
||||||
@@ -299,9 +309,9 @@ public:
|
|||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void finalTransform(Funcdata &data);
|
virtual void finalTransform(Funcdata &data);
|
||||||
virtual void finalizePrinting(Funcdata &data) const;
|
virtual void finalizePrinting(Funcdata &data) const;
|
||||||
virtual void saveXmlBody(ostream &s) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
|
virtual void decodeBody(Decoder &decoder,BlockMap &resolver);
|
||||||
void restoreXml(const Element *el,const AddrSpaceManager *m); ///< Restore \b this BlockGraph from an XML stream
|
void decode(Decoder &decoder,const AddrSpaceManager *m); ///< Restore \b this BlockGraph from an XML 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
|
||||||
@@ -383,8 +393,8 @@ public:
|
|||||||
virtual Address getStop(void) const;
|
virtual Address getStop(void) const;
|
||||||
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 saveXmlBody(ostream &s) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
|
virtual void decodeBody(Decoder &decoder,BlockMap &resolver);
|
||||||
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); }
|
||||||
@@ -431,7 +441,7 @@ public:
|
|||||||
virtual bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; }
|
virtual bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; }
|
||||||
virtual FlowBlock *getSplitPoint(void) { return copy->getSplitPoint(); }
|
virtual FlowBlock *getSplitPoint(void) { return copy->getSplitPoint(); }
|
||||||
virtual bool isComplex(void) const { return copy->isComplex(); }
|
virtual bool isComplex(void) const { return copy->isComplex(); }
|
||||||
virtual void saveXmlHeader(ostream &s) const;
|
virtual void encodeHeader(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A block that terminates with an unstructured (goto) branch to another block
|
/// \brief A block that terminates with an unstructured (goto) branch to another block
|
||||||
@@ -458,7 +468,7 @@ public:
|
|||||||
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
|
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
|
||||||
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
|
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
|
||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void saveXmlBody(ostream &s) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A block with multiple edges out, at least one of which is an unstructured (goto) branch.
|
/// \brief A block with multiple edges out, at least one of which is an unstructured (goto) branch.
|
||||||
@@ -486,7 +496,7 @@ public:
|
|||||||
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
|
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
|
||||||
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
|
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
|
||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void saveXmlBody(ostream &s) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A series of blocks that execute in sequence.
|
/// \brief A series of blocks that execute in sequence.
|
||||||
@@ -531,7 +541,7 @@ public:
|
|||||||
virtual PcodeOp *lastOp(void) const;
|
virtual PcodeOp *lastOp(void) const;
|
||||||
virtual bool isComplex(void) const { return getBlock(0)->isComplex(); }
|
virtual bool isComplex(void) const { return getBlock(0)->isComplex(); }
|
||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void saveXmlHeader(ostream &s) const;
|
virtual void encodeHeader(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A basic "if" block
|
/// \brief A basic "if" block
|
||||||
@@ -569,7 +579,7 @@ public:
|
|||||||
virtual const FlowBlock *getExitLeaf(void) const;
|
virtual const FlowBlock *getExitLeaf(void) const;
|
||||||
virtual PcodeOp *lastOp(void) const;
|
virtual PcodeOp *lastOp(void) const;
|
||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
virtual void saveXmlBody(ostream &s) const;
|
virtual void encodeBody(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A loop structure where the condition is checked at the top.
|
/// \brief A loop structure where the condition is checked at the top.
|
||||||
@@ -703,7 +713,7 @@ 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 restore FlowBlock address ranges
|
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
|
||||||
|
|||||||
@@ -16,34 +16,30 @@
|
|||||||
#include "callgraph.hh"
|
#include "callgraph.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
void CallGraphEdge::saveXml(ostream &s) const
|
ElementId ELEM_CALLGRAPH = ElementId("callgraph",51);
|
||||||
|
ElementId ELEM_NODE = ElementId("node",52);
|
||||||
|
|
||||||
|
void CallGraphEdge::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << " <edge>\n";
|
encoder.openElement(ELEM_EDGE);
|
||||||
s << " ";
|
from->getAddr().encode(encoder);
|
||||||
from->getAddr().saveXml(s);
|
to->getAddr().encode(encoder);
|
||||||
s << "\n ";
|
callsiteaddr.encode(encoder);
|
||||||
to->getAddr().saveXml(s);
|
encoder.closeElement(ELEM_EDGE);
|
||||||
s << "\n ";
|
|
||||||
callsiteaddr.saveXml(s);
|
|
||||||
s << "\n </edge>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraphEdge::restoreXml(const Element *el,CallGraph *graph)
|
void CallGraphEdge::decode(Decoder &decoder,CallGraph *graph)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
uint4 elemId = decoder.openElement(ELEM_EDGE);
|
||||||
const AddrSpaceManager *manage = graph->getArch();
|
const AddrSpaceManager *manage = graph->getArch();
|
||||||
Address fromaddr,toaddr,siteaddr;
|
Address fromaddr,toaddr,siteaddr;
|
||||||
|
|
||||||
const List &list(el->getChildren());
|
fromaddr = Address::decode(decoder,manage);
|
||||||
List::const_iterator iter;
|
toaddr = Address::decode(decoder,manage);
|
||||||
|
siteaddr = Address::decode(decoder,manage);
|
||||||
iter = list.begin();
|
decoder.closeElement(elemId);
|
||||||
fromaddr = Address::restoreXml(*iter,manage);
|
|
||||||
++iter;
|
|
||||||
toaddr = Address::restoreXml(*iter,manage);
|
|
||||||
++iter;
|
|
||||||
siteaddr = Address::restoreXml(*iter,manage);
|
|
||||||
|
|
||||||
CallGraphNode *fromnode = graph->findNode(fromaddr);
|
CallGraphNode *fromnode = graph->findNode(fromaddr);
|
||||||
if (fromnode == (CallGraphNode *)0)
|
if (fromnode == (CallGraphNode *)0)
|
||||||
@@ -66,28 +62,29 @@ void CallGraphNode::setFuncdata(Funcdata *f)
|
|||||||
fd = f;
|
fd = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraphNode::saveXml(ostream &s) const
|
void CallGraphNode::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << " <node";
|
encoder.openElement(ELEM_NODE);
|
||||||
if (name.size() != 0)
|
if (name.size() != 0)
|
||||||
a_v(s,"name",name);
|
encoder.writeString(ATTRIB_NAME, name);
|
||||||
s << ">\n ";
|
entryaddr.encode(encoder);
|
||||||
entryaddr.saveXml(s);
|
encoder.closeElement(ELEM_NODE);
|
||||||
s << "\n </node>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraphNode::restoreXml(const Element *el,CallGraph *graph)
|
void CallGraphNode::decode(Decoder &decoder,CallGraph *graph)
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 num = el->getNumAttributes();
|
uint4 elemId = decoder.openElement(ELEM_NODE);
|
||||||
string name;
|
string name;
|
||||||
for(int4 i=0;i<num;++i) {
|
for(;;) {
|
||||||
if (el->getAttributeName(i) == "name")
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
name = el->getAttributeValue(i);
|
if (attribId == 0) break;
|
||||||
|
if (attribId == ATTRIB_NAME)
|
||||||
|
name = decoder.readString();
|
||||||
}
|
}
|
||||||
Address addr = Address::restoreXml(*el->getChildren().begin(),graph->getArch());
|
Address addr = Address::decode(decoder,graph->getArch());
|
||||||
|
decoder.closeElement(elemId);
|
||||||
graph->addNode(addr,name);
|
graph->addNode(addr,name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,41 +428,39 @@ void CallGraph::buildEdges(Funcdata *fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraph::saveXml(ostream &s) const
|
void CallGraph::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
map<Address,CallGraphNode>::const_iterator iter;
|
map<Address,CallGraphNode>::const_iterator iter;
|
||||||
|
|
||||||
s << "<callgraph>\n";
|
encoder.openElement(ELEM_CALLGRAPH);
|
||||||
|
|
||||||
for(iter=graph.begin();iter!=graph.end();++iter)
|
for(iter=graph.begin();iter!=graph.end();++iter)
|
||||||
(*iter).second.saveXml(s);
|
(*iter).second.encode(encoder);
|
||||||
|
|
||||||
// Dump all the "in" edges
|
// Dump all the "in" edges
|
||||||
for(iter=graph.begin();iter!=graph.end();++iter) {
|
for(iter=graph.begin();iter!=graph.end();++iter) {
|
||||||
const CallGraphNode &node( (*iter).second );
|
const CallGraphNode &node( (*iter).second );
|
||||||
|
|
||||||
for(uint4 i=0;i<node.inedge.size();++i)
|
for(uint4 i=0;i<node.inedge.size();++i)
|
||||||
node.inedge[i].saveXml(s);
|
node.inedge[i].encode(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
s << "</callgraph>\n";
|
encoder.closeElement(ELEM_CALLGRAPH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraph::restoreXml(const Element *el)
|
void CallGraph::decoder(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CALLGRAPH);
|
||||||
List::const_iterator iter;
|
for(;;) {
|
||||||
|
uint4 subId = decoder.peekElement();
|
||||||
iter = list.begin();
|
if (subId == 0) break;
|
||||||
while(iter != list.end()) {
|
if (subId == ELEM_EDGE)
|
||||||
const Element *subel = *iter;
|
CallGraphEdge::decode(decoder,this);
|
||||||
++iter;
|
|
||||||
if (subel->getName() == "edge")
|
|
||||||
CallGraphEdge::restoreXml(subel,this);
|
|
||||||
else
|
else
|
||||||
CallGraphNode::restoreXml(subel,this);
|
CallGraphNode::decode(decoder,this);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ class Funcdata;
|
|||||||
class CallGraphNode;
|
class CallGraphNode;
|
||||||
class CallGraph;
|
class CallGraph;
|
||||||
|
|
||||||
|
extern ElementId ELEM_CALLGRAPH; ///< Marshaling element \<callgraph>
|
||||||
|
extern ElementId ELEM_NODE; ///< Marshaling element \<node>
|
||||||
|
|
||||||
class CallGraphEdge {
|
class CallGraphEdge {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
@@ -41,9 +44,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
CallGraphEdge(void) { flags = 0; }
|
CallGraphEdge(void) { flags = 0; }
|
||||||
bool isCycle(void) const { return ((flags&1)!=0); }
|
bool isCycle(void) const { return ((flags&1)!=0); }
|
||||||
void saveXml(ostream &s) const;
|
void encode(Encoder &encoder) const;
|
||||||
const Address &getCallSiteAddr(void) const { return callsiteaddr; }
|
const Address &getCallSiteAddr(void) const { return callsiteaddr; }
|
||||||
static void restoreXml(const Element *el,CallGraph *graph);
|
static void decode(Decoder &decoder,CallGraph *graph);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CallGraphNode {
|
class CallGraphNode {
|
||||||
@@ -77,8 +80,8 @@ public:
|
|||||||
const CallGraphEdge &getOutEdge(int4 i) const { return outedge[i]; }
|
const CallGraphEdge &getOutEdge(int4 i) const { return outedge[i]; }
|
||||||
CallGraphNode *getOutNode(int4 i) const { return outedge[i].to; }
|
CallGraphNode *getOutNode(int4 i) const { return outedge[i].to; }
|
||||||
void setFuncdata(Funcdata *f);
|
void setFuncdata(Funcdata *f);
|
||||||
void saveXml(ostream &s) const;
|
void encode(Encoder &encoder) const;
|
||||||
static void restoreXml(const Element *el,CallGraph *graph);
|
static void decode(Decoder &decoder,CallGraph *graph);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LeafIterator {
|
struct LeafIterator {
|
||||||
@@ -116,8 +119,8 @@ public:
|
|||||||
map<Address,CallGraphNode>::iterator end(void) { return graph.end(); }
|
map<Address,CallGraphNode>::iterator end(void) { return graph.end(); }
|
||||||
void buildAllNodes(void);
|
void buildAllNodes(void);
|
||||||
void buildEdges(Funcdata *fd);
|
void buildEdges(Funcdata *fd);
|
||||||
void saveXml(ostream &s) const;
|
void encode(Encoder &encoder) const;
|
||||||
void restoreXml(const Element *el);
|
void decoder(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
#include "comment.hh"
|
#include "comment.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
|
ElementId ELEM_COMMENT = ElementId("comment",53);
|
||||||
|
ElementId ELEM_COMMENTDB = ElementId("commentdb",54);
|
||||||
|
ElementId ELEM_TEXT = ElementId("text",55);
|
||||||
|
|
||||||
/// \param tp is the set of properties to associate with the comment (or 0 for no properties)
|
/// \param tp is the set of properties to associate with the comment (or 0 for no properties)
|
||||||
/// \param fad is the Address of the function containing the comment
|
/// \param fad is the Address of the function containing the comment
|
||||||
/// \param ad is the Address of the instruction associated with the comment
|
/// \param ad is the Address of the instruction associated with the comment
|
||||||
@@ -26,46 +30,45 @@ Comment::Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const str
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The single comment is saved as a \<comment> tag.
|
/// The single comment is encoded as a \<comment> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void Comment::saveXml(ostream &s) const
|
void Comment::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
string tpname = Comment::decodeCommentType(type);
|
string tpname = Comment::decodeCommentType(type);
|
||||||
s << "<comment";
|
encoder.openElement(ELEM_COMMENT);
|
||||||
a_v(s,"type",tpname);
|
encoder.writeString(ATTRIB_TYPE, tpname);
|
||||||
s << ">\n";
|
encoder.openElement(ELEM_ADDR);
|
||||||
s << " <addr";
|
funcaddr.getSpace()->encodeAttributes(encoder,funcaddr.getOffset());
|
||||||
funcaddr.getSpace()->saveXmlAttributes(s,funcaddr.getOffset());
|
encoder.closeElement(ELEM_ADDR);
|
||||||
s << "/>\n";
|
encoder.openElement(ELEM_ADDR);
|
||||||
s << " <addr";
|
addr.getSpace()->encodeAttributes(encoder,addr.getOffset());
|
||||||
addr.getSpace()->saveXmlAttributes(s,addr.getOffset());
|
encoder.closeElement(ELEM_ADDR);
|
||||||
s << "/>\n";
|
encoder.openElement(ELEM_TEXT);
|
||||||
s << " <text>";
|
encoder.writeString(ATTRIB_CONTENT, text);
|
||||||
xml_escape(s,text.c_str());
|
encoder.closeElement(ELEM_TEXT);
|
||||||
s << " </text>\n";
|
encoder.closeElement(ELEM_COMMENT);
|
||||||
s << "</comment>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The comment is parsed from a \<comment> tag.
|
/// Parse a \<comment> element from the given stream decoder
|
||||||
/// \param el is the \<comment> element
|
/// \param decoder is the given stream decoder
|
||||||
/// \param manage is a manager for resolving address space references
|
/// \param manage is a manager for resolving address space references
|
||||||
void Comment::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void Comment::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
emitted = false;
|
emitted = false;
|
||||||
type = 0;
|
type = 0;
|
||||||
type = Comment::encodeCommentType(el->getAttributeValue("type"));
|
uint4 elemId = decoder.openElement(ELEM_COMMENT);
|
||||||
const List &list(el->getChildren());
|
type = Comment::encodeCommentType(decoder.readString(ATTRIB_TYPE));
|
||||||
List::const_iterator iter;
|
funcaddr = Address::decode(decoder,manage);
|
||||||
|
addr = Address::decode(decoder,manage);
|
||||||
iter = list.begin();
|
uint4 subId = decoder.peekElement();
|
||||||
funcaddr = Address::restoreXml(*iter,manage);
|
if (subId != 0) {
|
||||||
++iter;
|
decoder.openElement();
|
||||||
addr = Address::restoreXml(*iter,manage);
|
text = decoder.readString(ATTRIB_CONTENT);
|
||||||
++iter;
|
decoder.closeElement(subId);
|
||||||
if (iter != list.end())
|
}
|
||||||
text = (*iter)->getContent();
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param name is a string representation of a single comment property
|
/// \param name is a string representation of a single comment property
|
||||||
@@ -235,28 +238,27 @@ CommentSet::const_iterator CommentDatabaseInternal::endComment(const Address &fa
|
|||||||
return commentset.lower_bound(&testcomm);
|
return commentset.lower_bound(&testcomm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentDatabaseInternal::saveXml(ostream &s) const
|
void CommentDatabaseInternal::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
CommentSet::const_iterator iter;
|
CommentSet::const_iterator iter;
|
||||||
|
|
||||||
s << "<commentdb>\n";
|
encoder.openElement(ELEM_COMMENTDB);
|
||||||
for(iter=commentset.begin();iter!=commentset.end();++iter)
|
for(iter=commentset.begin();iter!=commentset.end();++iter)
|
||||||
(*iter)->saveXml(s);
|
(*iter)->encode(encoder);
|
||||||
s << "</commentdb>\n";
|
encoder.closeElement(ELEM_COMMENTDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentDatabaseInternal::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void CommentDatabaseInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_COMMENTDB);
|
||||||
List::const_iterator iter;
|
while(decoder.peekElement() != 0) {
|
||||||
|
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
|
||||||
Comment com;
|
Comment com;
|
||||||
com.restoreXml(*iter,manage);
|
com.decode(decoder,manage);
|
||||||
addComment(com.getType(),com.getFuncAddr(),com.getAddr(),com.getText());
|
addComment(com.getType(),com.getFuncAddr(),com.getAddr(),com.getText());
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Figure out position of given Comment and initialize its key.
|
/// Figure out position of given Comment and initialize its key.
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ class FlowBlock;
|
|||||||
class PcodeOp;
|
class PcodeOp;
|
||||||
class Funcdata;
|
class Funcdata;
|
||||||
|
|
||||||
|
extern ElementId ELEM_COMMENT; ///< Marshaling element \<comment>
|
||||||
|
extern ElementId ELEM_COMMENTDB; ///< Marshaling element \<commentdb>
|
||||||
|
extern ElementId ELEM_TEXT; ///< Marshaling element \<text>
|
||||||
|
|
||||||
/// \brief A comment attached to a specific function and code address
|
/// \brief A comment attached to a specific function and code address
|
||||||
///
|
///
|
||||||
/// Things contains the actual character data of the comment. It is
|
/// Things contains the actual character data of the comment. It is
|
||||||
@@ -53,7 +57,7 @@ public:
|
|||||||
warningheader = 32 ///< The comment is auto-generated and should be in the header
|
warningheader = 32 ///< The comment is auto-generated and should be in the header
|
||||||
};
|
};
|
||||||
Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt); ///< Constructor
|
Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt); ///< Constructor
|
||||||
Comment(void) {} ///< Constructor for use with restoreXml
|
Comment(void) {} ///< Constructor for use with decode
|
||||||
void setEmitted(bool val) const { emitted = val; } ///< Mark that \b this comment has been emitted
|
void setEmitted(bool val) const { emitted = val; } ///< Mark that \b this comment has been emitted
|
||||||
bool isEmitted(void) const { return emitted; } ///< Return \b true if \b this comment is already emitted
|
bool isEmitted(void) const { return emitted; } ///< Return \b true if \b this comment is already emitted
|
||||||
uint4 getType(void) const { return type; } ///< Get the properties associated with the comment
|
uint4 getType(void) const { return type; } ///< Get the properties associated with the comment
|
||||||
@@ -61,8 +65,8 @@ public:
|
|||||||
const Address &getAddr(void) const { return addr; } ///< Get the address to which the instruction is attached
|
const Address &getAddr(void) const { return addr; } ///< Get the address to which the instruction is attached
|
||||||
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 saveXml(ostream &s) const; ///< Save the comment to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode the comment to a stream
|
||||||
void restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore the comment from XML
|
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< 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
|
||||||
};
|
};
|
||||||
@@ -134,17 +138,17 @@ public:
|
|||||||
/// \return the ending iterator
|
/// \return the ending iterator
|
||||||
virtual CommentSet::const_iterator endComment(const Address &fad) const=0;
|
virtual CommentSet::const_iterator endComment(const Address &fad) const=0;
|
||||||
|
|
||||||
/// \brief Save all comments in the container to an XML stream
|
/// \brief Encode all comments in the container to a stream
|
||||||
///
|
///
|
||||||
/// Writes a \<commentdb> tag, with \<comment> sub-tags for each Comment object.
|
/// Writes a \<commentdb> element, with \<comment> children for each Comment object.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
virtual void saveXml(ostream &s) const=0;
|
virtual void encode(Encoder &encoder) const=0;
|
||||||
|
|
||||||
/// \brief Restore all comments from XML
|
/// \brief Restore all comments from a \<commentdb> element
|
||||||
///
|
///
|
||||||
/// \param el is the root \<commentdb> element
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is a manager for resolving address space references
|
/// \param manage is a manager for resolving address space references
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage)=0;
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -166,8 +170,8 @@ public:
|
|||||||
virtual void deleteComment(Comment *com);
|
virtual void deleteComment(Comment *com);
|
||||||
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 saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A class for sorting comments into and within basic blocks
|
/// \brief A class for sorting comments into and within basic blocks
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ CommentDatabaseGhidra::CommentDatabaseGhidra(ArchitectureGhidra *g)
|
|||||||
void CommentDatabaseGhidra::fillCache(const Address &fad) const
|
void CommentDatabaseGhidra::fillCache(const Address &fad) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Document *doc;
|
|
||||||
uint4 commentfilter;
|
uint4 commentfilter;
|
||||||
|
|
||||||
if (cachefilled) return; // Already queried ghidra
|
if (cachefilled) return; // Already queried ghidra
|
||||||
@@ -41,10 +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);
|
||||||
|
|
||||||
doc = ghidra->getComments(fad,commentfilter);
|
XmlDecode decoder;
|
||||||
if (doc != (Document *)0) {
|
if (ghidra->getComments(fad,commentfilter,decoder)) {
|
||||||
cache.restoreXml(doc->getRoot(),ghidra);
|
cache.decode(decoder,ghidra);
|
||||||
delete doc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ public:
|
|||||||
throw LowlevelError("deleteComment unimplemented"); }
|
throw LowlevelError("deleteComment unimplemented"); }
|
||||||
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 saveXml(ostream &s) const {
|
virtual void encode(Encoder &encoder) const {
|
||||||
throw LowlevelError("commentdb::saveXml unimplemented"); }
|
throw LowlevelError("commentdb::encode unimplemented"); }
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *trans) {
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *trans) {
|
||||||
throw LowlevelError("commentdb::restoreXml unimplemented"); }
|
throw LowlevelError("CommentDatabaseGhidra::decode unimplemented"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ void IfcSave::execute(istream &s)
|
|||||||
if (!fs)
|
if (!fs)
|
||||||
throw IfaceExecutionError("Unable to open file: "+savefile);
|
throw IfaceExecutionError("Unable to open file: "+savefile);
|
||||||
|
|
||||||
dcp->conf->saveXml(fs);
|
XmlEncode encoder(fs);
|
||||||
|
dcp->conf->encode(encoder);
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,41 +15,52 @@
|
|||||||
*/
|
*/
|
||||||
#include "cpool.hh"
|
#include "cpool.hh"
|
||||||
|
|
||||||
/// Save the constant pool object description as a \<cpoolrec> tag.
|
AttributeId ATTRIB_A = AttributeId("a",45);
|
||||||
/// \param s is the output stream
|
AttributeId ATTRIB_B = AttributeId("b",46);
|
||||||
void CPoolRecord::saveXml(ostream &s) const
|
AttributeId ATTRIB_LENGTH = AttributeId("length",47);
|
||||||
|
AttributeId ATTRIB_TAG = AttributeId("tag",48);
|
||||||
|
|
||||||
|
ElementId ELEM_CONSTANTPOOL = ElementId("constantpool",56);
|
||||||
|
ElementId ELEM_CPOOLREC = ElementId("cpoolrec",57);
|
||||||
|
ElementId ELEM_REF = ElementId("ref",58);
|
||||||
|
ElementId ELEM_TOKEN = ElementId("token",59);
|
||||||
|
|
||||||
|
/// Encode the constant pool object description as a \<cpoolrec> element.
|
||||||
|
/// \param encoder is the stream encoder
|
||||||
|
void CPoolRecord::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<cpoolrec";
|
encoder.openElement(ELEM_CPOOLREC);
|
||||||
if (tag == pointer_method)
|
if (tag == pointer_method)
|
||||||
a_v(s,"tag","method");
|
encoder.writeString(ATTRIB_TAG, "method");
|
||||||
else if (tag == pointer_field)
|
else if (tag == pointer_field)
|
||||||
a_v(s,"tag","field");
|
encoder.writeString(ATTRIB_TAG, "field");
|
||||||
else if (tag == instance_of)
|
else if (tag == instance_of)
|
||||||
a_v(s,"tag","instanceof");
|
encoder.writeString(ATTRIB_TAG, "instanceof");
|
||||||
else if (tag == array_length)
|
else if (tag == array_length)
|
||||||
a_v(s,"tag","arraylength");
|
encoder.writeString(ATTRIB_TAG, "arraylength");
|
||||||
else if (tag == check_cast)
|
else if (tag == check_cast)
|
||||||
a_v(s,"tag","checkcast");
|
encoder.writeString(ATTRIB_TAG, "checkcast");
|
||||||
else if (tag == string_literal)
|
else if (tag == string_literal)
|
||||||
a_v(s,"tag","string");
|
encoder.writeString(ATTRIB_TAG, "string");
|
||||||
else if (tag == class_reference)
|
else if (tag == class_reference)
|
||||||
a_v(s,"tag","classref");
|
encoder.writeString(ATTRIB_TAG, "classref");
|
||||||
else
|
else
|
||||||
a_v(s,"tag","primitive");
|
encoder.writeString(ATTRIB_TAG, "primitive");
|
||||||
if (isConstructor())
|
if (isConstructor())
|
||||||
a_v_b(s,"constructor",true);
|
encoder.writeBool(ATTRIB_CONSTRUCTOR, true);
|
||||||
if (isDestructor())
|
if (isDestructor())
|
||||||
a_v_b(s,"destructor",true);
|
encoder.writeBool(ATTRIB_DESTRUCTOR, true);
|
||||||
s << ">\n";
|
|
||||||
if (tag == primitive) {
|
if (tag == primitive) {
|
||||||
s << " <value>0x";
|
encoder.openElement(ELEM_VALUE);
|
||||||
s << hex << value;
|
encoder.writeUnsignedInteger(ATTRIB_CONTENT, value);
|
||||||
s << "</value>\n";
|
encoder.closeElement(ELEM_VALUE);
|
||||||
}
|
}
|
||||||
if (byteData != (uint1 *)0) {
|
if (byteData != (uint1 *)0) {
|
||||||
s << " <data length=\"" << dec << byteDataLen << "\">\n";
|
encoder.openElement(ELEM_DATA);
|
||||||
|
encoder.writeSignedInteger(ATTRIB_LENGTH, byteDataLen);
|
||||||
int4 wrap = 0;
|
int4 wrap = 0;
|
||||||
|
ostringstream s;
|
||||||
for(int4 i=0;i<byteDataLen;++i) {
|
for(int4 i=0;i<byteDataLen;++i) {
|
||||||
s << setfill('0') << setw(2) << hex << byteData[i] << ' ';
|
s << setfill('0') << setw(2) << hex << byteData[i] << ' ';
|
||||||
wrap += 1;
|
wrap += 1;
|
||||||
@@ -58,31 +69,33 @@ void CPoolRecord::saveXml(ostream &s) const
|
|||||||
wrap = 0;
|
wrap = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << " </data>\n";
|
encoder.writeString(ATTRIB_CONTENT, s.str());
|
||||||
|
encoder.closeElement(ELEM_DATA);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
s << " <token>";
|
encoder.openElement(ELEM_TOKEN);
|
||||||
xml_escape(s,token.c_str());
|
encoder.writeString(ATTRIB_CONTENT, token);
|
||||||
s << " </token>\n";
|
encoder.closeElement(ELEM_TOKEN);
|
||||||
}
|
}
|
||||||
type->saveXml(s);
|
type->encode(encoder);
|
||||||
s << "</cpoolrec>\n";
|
encoder.closeElement(ELEM_CPOOLREC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize \b this CPoolRecord instance from a \<cpoolrec> tag.
|
/// Initialize \b this CPoolRecord instance from a \<cpoolrec> element.
|
||||||
/// \param el is the \<cpoolrec> element
|
/// \param decoder is the stream decoder
|
||||||
/// \param typegrp is the TypeFactory used to resolve data-types
|
/// \param typegrp is the TypeFactory used to resolve data-types
|
||||||
void CPoolRecord::restoreXml(const Element *el,TypeFactory &typegrp)
|
void CPoolRecord::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
|
|
||||||
{
|
{
|
||||||
tag = primitive; // Default tag
|
tag = primitive; // Default tag
|
||||||
value = 0;
|
value = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
int4 num = el->getNumAttributes();
|
uint4 elemId = decoder.openElement(ELEM_CPOOLREC);
|
||||||
for(int4 i=0;i<num;++i) {
|
for(;;) {
|
||||||
const string &attr(el->getAttributeName(i));
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attr == "tag") {
|
if (attribId == 0) break;
|
||||||
const string &tagstring(el->getAttributeValue(i));
|
if (attribId == ATTRIB_TAG) {
|
||||||
|
string tagstring = decoder.readString();
|
||||||
if (tagstring == "method")
|
if (tagstring == "method")
|
||||||
tag = pointer_method;
|
tag = pointer_method;
|
||||||
else if (tagstring == "field")
|
else if (tagstring == "field")
|
||||||
@@ -98,36 +111,27 @@ void CPoolRecord::restoreXml(const Element *el,TypeFactory &typegrp)
|
|||||||
else if (tagstring == "classref")
|
else if (tagstring == "classref")
|
||||||
tag = class_reference;
|
tag = class_reference;
|
||||||
}
|
}
|
||||||
else if (attr == "constructor") {
|
else if (attribId == ATTRIB_CONSTRUCTOR) {
|
||||||
if (xml_readbool(el->getAttributeValue(i)))
|
if (decoder.readBool())
|
||||||
flags |= CPoolRecord::is_constructor;
|
flags |= CPoolRecord::is_constructor;
|
||||||
}
|
}
|
||||||
else if (attr == "destructor") {
|
else if (attribId == ATTRIB_DESTRUCTOR) {
|
||||||
if (xml_readbool(el->getAttributeValue(i)))
|
if (decoder.readBool())
|
||||||
flags |= CPoolRecord::is_destructor;
|
flags |= CPoolRecord::is_destructor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const List &list(el->getChildren());
|
uint4 subId;
|
||||||
List::const_iterator iter;
|
|
||||||
|
|
||||||
iter = list.begin();
|
|
||||||
const Element *subel;
|
|
||||||
if (tag == primitive) { // First tag must be value
|
if (tag == primitive) { // First tag must be value
|
||||||
subel = *iter;
|
subId = decoder.openElement(ELEM_VALUE);
|
||||||
istringstream s1(subel->getContent());
|
value = decoder.readUnsignedInteger(ATTRIB_CONTENT);
|
||||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
decoder.closeElement(subId);
|
||||||
s1 >> value;
|
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
subel = *iter;
|
subId = decoder.openElement();
|
||||||
++iter;
|
if (subId == ELEM_TOKEN)
|
||||||
if (subel->getName() == "token")
|
token = decoder.readString(ATTRIB_CONTENT);
|
||||||
token = subel->getContent();
|
|
||||||
else {
|
else {
|
||||||
istringstream s2(subel->getAttributeValue("length"));
|
byteDataLen = decoder.readSignedInteger(ATTRIB_LENGTH);
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
istringstream s3(decoder.readString(ATTRIB_CONTENT));
|
||||||
s2 >> byteDataLen;
|
|
||||||
istringstream s3(subel->getContent());
|
|
||||||
byteData = new uint1[byteDataLen];
|
byteData = new uint1[byteDataLen];
|
||||||
for(int4 i=0;i<byteDataLen;++i) {
|
for(int4 i=0;i<byteDataLen;++i) {
|
||||||
uint4 val;
|
uint4 val;
|
||||||
@@ -135,16 +139,17 @@ void CPoolRecord::restoreXml(const Element *el,TypeFactory &typegrp)
|
|||||||
byteData[i] = (uint1)val;
|
byteData[i] = (uint1)val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(subId);
|
||||||
if (tag == string_literal && (byteData == (uint1 *)0))
|
if (tag == string_literal && (byteData == (uint1 *)0))
|
||||||
throw LowlevelError("Bad constant pool record: missing <data>");
|
throw LowlevelError("Bad constant pool record: missing <data>");
|
||||||
subel = *iter;
|
|
||||||
if (flags != 0) {
|
if (flags != 0) {
|
||||||
bool isConstructor = ((flags & is_constructor)!=0);
|
bool isConstructor = ((flags & is_constructor)!=0);
|
||||||
bool isDestructor = ((flags & is_destructor)!=0);
|
bool isDestructor = ((flags & is_destructor)!=0);
|
||||||
type = typegrp.restoreXmlTypeWithCodeFlags(subel,isConstructor,isDestructor);
|
type = typegrp.decodeTypeWithCodeFlags(decoder,isConstructor,isDestructor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
type = typegrp.restoreXmlType(subel);
|
type = typegrp.decodeType(decoder);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPool::putRecord(const vector<uintb> &refs,uint4 tag,const string &tok,Datatype *ct)
|
void ConstantPool::putRecord(const vector<uintb> &refs,uint4 tag,const string &tok,Datatype *ct)
|
||||||
@@ -156,36 +161,34 @@ void ConstantPool::putRecord(const vector<uintb> &refs,uint4 tag,const string &t
|
|||||||
newrec->type = ct;
|
newrec->type = ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CPoolRecord *ConstantPool::restoreXmlRecord(const vector<uintb> &refs,const Element *el,TypeFactory &typegrp)
|
const CPoolRecord *ConstantPool::decodeRecord(const vector<uintb> &refs,Decoder &decoder,TypeFactory &typegrp)
|
||||||
|
|
||||||
{
|
{
|
||||||
CPoolRecord *newrec = createRecord(refs);
|
CPoolRecord *newrec = createRecord(refs);
|
||||||
newrec->restoreXml(el,typegrp);
|
newrec->decode(decoder,typegrp);
|
||||||
return newrec;
|
return newrec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The reference is output as a \<ref> tag.
|
/// The reference is encoded as a \<ref> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void ConstantPoolInternal::CheapSorter::saveXml(ostream &s) const
|
void ConstantPoolInternal::CheapSorter::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<ref";
|
encoder.openElement(ELEM_REF);
|
||||||
a_v_u(s,"a",a);
|
encoder.writeUnsignedInteger(ATTRIB_A, a);
|
||||||
a_v_u(s,"b",b);
|
encoder.writeUnsignedInteger(ATTRIB_B, b);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restore \b this \e reference from a \<ref> XML tag
|
/// Restore \b this \e reference from a \<ref> element
|
||||||
/// \param el is the XML element
|
/// \param decoder is the stream decoder
|
||||||
void ConstantPoolInternal::CheapSorter::restoreXml(const Element *el)
|
void ConstantPoolInternal::CheapSorter::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
istringstream s1(el->getAttributeValue("a"));
|
uint4 elemId = decoder.openElement(ELEM_REF);
|
||||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
a = decoder.readUnsignedInteger(ATTRIB_A);
|
||||||
s1 >> a;
|
b = decoder.readUnsignedInteger(ATTRIB_B);
|
||||||
istringstream s2(el->getAttributeValue("b"));
|
decoder.closeElement(elemId);
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s2 >> b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CPoolRecord *ConstantPoolInternal::createRecord(const vector<uintb> &refs)
|
CPoolRecord *ConstantPoolInternal::createRecord(const vector<uintb> &refs)
|
||||||
@@ -210,32 +213,29 @@ const CPoolRecord *ConstantPoolInternal::getRecord(const vector<uintb> &refs) co
|
|||||||
return &(*iter).second;
|
return &(*iter).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolInternal::saveXml(ostream &s) const
|
void ConstantPoolInternal::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
map<CheapSorter,CPoolRecord>::const_iterator iter;
|
map<CheapSorter,CPoolRecord>::const_iterator iter;
|
||||||
s << "<constantpool>\n";
|
encoder.openElement(ELEM_CONSTANTPOOL);
|
||||||
for(iter=cpoolMap.begin();iter!=cpoolMap.end();++iter) {
|
for(iter=cpoolMap.begin();iter!=cpoolMap.end();++iter) {
|
||||||
(*iter).first.saveXml(s);
|
(*iter).first.encode(encoder);
|
||||||
(*iter).second.saveXml(s);
|
(*iter).second.encode(encoder);
|
||||||
}
|
}
|
||||||
s << "</constantpool>\n";
|
encoder.closeElement(ELEM_CONSTANTPOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolInternal::restoreXml(const Element *el,TypeFactory &typegrp)
|
void ConstantPoolInternal::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CONSTANTPOOL);
|
||||||
List::const_iterator iter;
|
while(decoder.peekElement() != 0) {
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
|
||||||
const Element *subel = *iter;
|
|
||||||
CheapSorter sorter;
|
CheapSorter sorter;
|
||||||
sorter.restoreXml(subel);
|
sorter.decode(decoder);
|
||||||
vector<uintb> refs;
|
vector<uintb> refs;
|
||||||
sorter.apply(refs);
|
sorter.apply(refs);
|
||||||
++iter;
|
|
||||||
subel = *iter;
|
|
||||||
CPoolRecord *newrec = createRecord(refs);
|
CPoolRecord *newrec = createRecord(refs);
|
||||||
newrec->restoreXml(subel,typegrp);
|
newrec->decode(decoder,typegrp);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,16 @@
|
|||||||
|
|
||||||
#include "type.hh"
|
#include "type.hh"
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_A; ///< Marshaling attribute "a"
|
||||||
|
extern AttributeId ATTRIB_B; ///< Marshaling attribute "b"
|
||||||
|
extern AttributeId ATTRIB_LENGTH; ///< Marshaling attribute "length"
|
||||||
|
extern AttributeId ATTRIB_TAG; ///< Marshaling attribute "tag"
|
||||||
|
|
||||||
|
extern ElementId ELEM_CONSTANTPOOL; ///< Marshaling element \<constantpool>
|
||||||
|
extern ElementId ELEM_CPOOLREC; ///< Marshaling element \<cpoolrec>
|
||||||
|
extern ElementId ELEM_REF; ///< Marshaling element \<ref>
|
||||||
|
extern ElementId ELEM_TOKEN; ///< Marshaling element \<token>
|
||||||
|
|
||||||
/// \brief A description of a byte-code object referenced by a constant
|
/// \brief A description of a byte-code object referenced by a constant
|
||||||
///
|
///
|
||||||
/// Byte-code languages can make use of objects that the \e system knows about
|
/// Byte-code languages can make use of objects that the \e system knows about
|
||||||
@@ -78,8 +88,8 @@ public:
|
|||||||
uintb getValue(void) const { return value; } ///< Get the constant value associated with \b this
|
uintb getValue(void) const { return value; } ///< Get the constant value associated with \b this
|
||||||
bool isConstructor(void) const { return ((flags & is_constructor)!=0); } ///< Is object a constructor method
|
bool isConstructor(void) const { return ((flags & is_constructor)!=0); } ///< Is object a constructor method
|
||||||
bool isDestructor(void) const { return ((flags & is_destructor)!=0); } ///< Is object a destructor method
|
bool isDestructor(void) const { return ((flags & is_destructor)!=0); } ///< Is object a destructor method
|
||||||
void saveXml(ostream &s) const; ///< Save object to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||||
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore object from XML stream
|
void decode(Decoder &decoder,TypeFactory &typegrp); ///< Decode \b this from a stream
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An interface to the pool of \b constant objects for byte-code languages
|
/// \brief An interface to the pool of \b constant objects for byte-code languages
|
||||||
@@ -116,33 +126,33 @@ public:
|
|||||||
/// \param ct is the data-type associated with the object
|
/// \param ct is the data-type associated with the object
|
||||||
void putRecord(const vector<uintb> &refs,uint4 tag,const string &tok,Datatype *ct);
|
void putRecord(const vector<uintb> &refs,uint4 tag,const string &tok,Datatype *ct);
|
||||||
|
|
||||||
/// \brief Restore a CPoolRecord given a \e reference and an XML stream
|
/// \brief Restore a CPoolRecord given a \e reference and a stream decoder
|
||||||
///
|
///
|
||||||
/// A \<cpoolrec> element initializes the new record which is immediately associated
|
/// A \<cpoolrec> element initializes the new record which is immediately associated
|
||||||
/// with the \e reference.
|
/// with the \e reference.
|
||||||
/// \param refs is the \e reference (made up of 1 or more identifying integers)
|
/// \param refs is the \e reference (made up of 1 or more identifying integers)
|
||||||
/// \param el is the XML element
|
/// \param decoder is the given stream decoder
|
||||||
/// \param typegrp is the TypeFactory used to resolve data-type references in XML
|
/// \param typegrp is the TypeFactory used to resolve data-type references in XML
|
||||||
/// \return the newly allocated and initialized CPoolRecord
|
/// \return the newly allocated and initialized CPoolRecord
|
||||||
const CPoolRecord *restoreXmlRecord(const vector<uintb> &refs,const Element *el,TypeFactory &typegrp);
|
const CPoolRecord *decodeRecord(const vector<uintb> &refs,Decoder &decoder,TypeFactory &typegrp);
|
||||||
|
|
||||||
virtual bool empty(void) const=0; ///< Is the container empty of records
|
virtual bool empty(void) const=0; ///< Is the container empty of records
|
||||||
virtual void clear(void)=0; ///< Release any (local) resources
|
virtual void clear(void)=0; ///< Release any (local) resources
|
||||||
|
|
||||||
/// \brief Save all records in this container to an XML stream
|
/// \brief Encode all records in this container to a stream
|
||||||
///
|
///
|
||||||
/// (If supported) An \<constantpool> element is written containing \<cpoolrec>
|
/// (If supported) A \<constantpool> element is written containing \<cpoolrec>
|
||||||
/// child elements for each CPoolRecord in the container.
|
/// child elements for each CPoolRecord in the container.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
virtual void saveXml(ostream &s) const=0;
|
virtual void encode(Encoder &encoder) const=0;
|
||||||
|
|
||||||
/// \brief Restore constant pool records from an XML stream
|
/// \brief Restore constant pool records from the given stream decoder
|
||||||
///
|
///
|
||||||
/// (If supported) The container is populated with CPooLRecords initialized
|
/// (If supported) The container is populated with CPoolRecords initialized
|
||||||
/// from a \<constantpool> XML tag.
|
/// from a \<constantpool> element.
|
||||||
/// \param el is the XML element
|
/// \param decoder is the given stream decoder
|
||||||
/// \param typegrp is the TypeFactory used to resolve data-type references in the XML
|
/// \param typegrp is the TypeFactory used to resolve data-type references in the XML
|
||||||
virtual void restoreXml(const Element *el,TypeFactory &typegrp)=0;
|
virtual void decode(Decoder &decoder,TypeFactory &typegrp)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An implementation of the ConstantPool interface storing records internally in RAM
|
/// \brief An implementation of the ConstantPool interface storing records internally in RAM
|
||||||
@@ -182,8 +192,8 @@ class ConstantPoolInternal : public ConstantPool {
|
|||||||
/// \param refs is the provided container of integers
|
/// \param refs is the provided container of integers
|
||||||
void apply(vector<uintb> &refs) const { refs.push_back(a); refs.push_back(b); }
|
void apply(vector<uintb> &refs) const { refs.push_back(a); refs.push_back(b); }
|
||||||
|
|
||||||
void saveXml(ostream &s) const; ///< Serialize the \e reference to an XML element
|
void encode(Encoder &encoder) const; ///< Encode the \e reference to a stream
|
||||||
void restoreXml(const Element *el); ///< Deserialize the \e reference from an XML element
|
void decode(Decoder &decoder); ///< Decode the \e reference from a stream
|
||||||
};
|
};
|
||||||
map<CheapSorter,CPoolRecord> cpoolMap; ///< A map from \e reference to constant pool record
|
map<CheapSorter,CPoolRecord> cpoolMap; ///< A map from \e reference to constant pool record
|
||||||
virtual CPoolRecord *createRecord(const vector<uintb> &refs);
|
virtual CPoolRecord *createRecord(const vector<uintb> &refs);
|
||||||
@@ -191,8 +201,8 @@ public:
|
|||||||
virtual const CPoolRecord *getRecord(const vector<uintb> &refs) const;
|
virtual const CPoolRecord *getRecord(const vector<uintb> &refs) const;
|
||||||
virtual bool empty(void) const { return cpoolMap.empty(); }
|
virtual bool empty(void) const { return cpoolMap.empty(); }
|
||||||
virtual void clear(void) { cpoolMap.clear(); }
|
virtual void clear(void) { cpoolMap.clear(); }
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
|
virtual void decode(Decoder &decoder,TypeFactory &typegrp);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ 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) {
|
||||||
Document *doc;
|
XmlDecode decoder;
|
||||||
|
bool success;
|
||||||
try {
|
try {
|
||||||
doc = ghidra->getCPoolRef(refs);
|
success = ghidra->getCPoolRef(refs,decoder);
|
||||||
}
|
}
|
||||||
catch(JavaError &err) {
|
catch(JavaError &err) {
|
||||||
throw LowlevelError("Error fetching constant pool record: " + err.explain);
|
throw LowlevelError("Error fetching constant pool record: " + err.explain);
|
||||||
@@ -42,24 +43,23 @@ const CPoolRecord *ConstantPoolGhidra::getRecord(const vector<uintb> &refs) cons
|
|||||||
catch(XmlError &err) {
|
catch(XmlError &err) {
|
||||||
throw LowlevelError("Error in constant pool record xml: "+err.explain);
|
throw LowlevelError("Error in constant pool record xml: "+err.explain);
|
||||||
}
|
}
|
||||||
if (doc == (Document *)0) {
|
if (!success) {
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << "Could not retrieve constant pool record for reference: 0x" << refs[0];
|
s << "Could not retrieve constant pool record for reference: 0x" << refs[0];
|
||||||
throw LowlevelError(s.str());
|
throw LowlevelError(s.str());
|
||||||
}
|
}
|
||||||
rec = cache.restoreXmlRecord(refs,doc->getRoot(),*ghidra->types);
|
rec = cache.decodeRecord(refs,decoder,*ghidra->types);
|
||||||
delete doc;
|
|
||||||
}
|
}
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolGhidra::saveXml(ostream &s) const
|
void ConstantPoolGhidra::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
throw LowlevelError("Cannot access constant pool with this method");
|
throw LowlevelError("Cannot access constant pool with this method");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolGhidra::restoreXml(const Element *el,TypeFactory &typegrp)
|
void ConstantPoolGhidra::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||||
|
|
||||||
{
|
{
|
||||||
throw LowlevelError("Cannot access constant pool with this method");
|
throw LowlevelError("Cannot access constant pool with this method");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
///
|
///
|
||||||
/// The actual CPoolRecord objects are cached locally, but new queries are placed
|
/// The actual CPoolRecord objects are cached locally, but new queries are placed
|
||||||
/// with the Ghidra client hosting the program currently being decompiled. The
|
/// with the Ghidra client hosting the program currently being decompiled. The
|
||||||
/// queries and response records are sent via XML. The saveXml() and restoreXml()
|
/// queries and response records are sent via XML. The encode() and decode()
|
||||||
/// methods are disabled. The clear() method only releases the local cache,
|
/// methods are disabled. The clear() method only releases the local cache,
|
||||||
/// no records on the Ghidra client are affected.
|
/// no records on the Ghidra client are affected.
|
||||||
class ConstantPoolGhidra : public ConstantPool {
|
class ConstantPoolGhidra : public ConstantPool {
|
||||||
@@ -37,8 +37,8 @@ public:
|
|||||||
virtual const CPoolRecord *getRecord(const vector<uintb> &refs) const;
|
virtual const CPoolRecord *getRecord(const vector<uintb> &refs) const;
|
||||||
virtual bool empty(void) const { return false; }
|
virtual bool empty(void) const { return false; }
|
||||||
virtual void clear(void) { cache.clear(); }
|
virtual void clear(void) { cache.clear(); }
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
|
virtual void decode(Decoder &decoder,TypeFactory &typegrp);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,28 @@ class Database;
|
|||||||
class Symbol;
|
class Symbol;
|
||||||
class PrintLanguage;
|
class PrintLanguage;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_CAT; ///< Marshaling attribute "cat"
|
||||||
|
extern AttributeId ATTRIB_FIELD; ///< Marshaling attribute "field"
|
||||||
|
extern AttributeId ATTRIB_MERGE; ///< Marshaling attribute "merge"
|
||||||
|
extern AttributeId ATTRIB_SCOPEIDBYNAME; ///< Marshaling attribute "scopeidbyname"
|
||||||
|
extern AttributeId ATTRIB_VOLATILE; ///< Marshaling attribute "volatile"
|
||||||
|
|
||||||
|
extern ElementId ELEM_COLLISION; ///< Marshaling element \<collision>
|
||||||
|
extern ElementId ELEM_DB; ///< Marshaling element \<db>
|
||||||
|
extern ElementId ELEM_EQUATESYMBOL; ///< Marshaling element \<equatesymbol>
|
||||||
|
extern ElementId ELEM_EXTERNREFSYMBOL; ///< Marshaling element \<externrefsymbol>
|
||||||
|
extern ElementId ELEM_FACETSYMBOL; ///< Marshaling element \<facetsymbol>
|
||||||
|
extern ElementId ELEM_FUNCTIONSHELL; ///< Marshaling element \<functionshell>
|
||||||
|
extern ElementId ELEM_HASH; ///< Marshaling element \<hash>
|
||||||
|
extern ElementId ELEM_HOLE; ///< Marshaling element \<hole>
|
||||||
|
extern ElementId ELEM_LABELSYM; ///< Marshaling element \<labelsym>
|
||||||
|
extern ElementId ELEM_MAPSYM; ///< Marshaling element \<mapsym>
|
||||||
|
extern ElementId ELEM_PARENT; ///< Marshaling element \<parent>
|
||||||
|
extern ElementId ELEM_PROPERTY_CHANGEPOINT; ///< Marshaling element \<property_changepoint>
|
||||||
|
extern ElementId ELEM_RANGEEQUALSSYMBOLS; ///< Marshaling element \<rangeequalssymbols>
|
||||||
|
extern ElementId ELEM_SCOPE; ///< Marshaling element \<scope>
|
||||||
|
extern ElementId ELEM_SYMBOLLIST; ///< Marshaling element \<symbollist>
|
||||||
|
|
||||||
/// \brief A storage location for a particular Symbol
|
/// \brief A storage location for a particular Symbol
|
||||||
///
|
///
|
||||||
/// Where a Symbol is stored, as a byte address and a size, is of particular importance
|
/// Where a Symbol is stored, as a byte address and a size, is of particular importance
|
||||||
@@ -134,8 +156,8 @@ public:
|
|||||||
bool updateType(Varnode *vn) const; ///< Update a Varnode data-type from \b this
|
bool updateType(Varnode *vn) const; ///< Update a Varnode data-type from \b this
|
||||||
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 saveXml(ostream &s) const; ///< Save \b this to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode \b this to a stream
|
||||||
List::const_iterator restoreXml(List::const_iterator iter,const AddrSpaceManager *manage); ///< Restore \b this from an XML stream
|
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this from a stream
|
||||||
};
|
};
|
||||||
typedef rangemap<SymbolEntry> EntryMap; ///< A rangemap of SymbolEntry
|
typedef rangemap<SymbolEntry> EntryMap; ///< A rangemap of SymbolEntry
|
||||||
|
|
||||||
@@ -192,7 +214,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Symbol(Scope *sc,const string &nm,Datatype *ct); ///< Construct given a name and data-type
|
Symbol(Scope *sc,const string &nm,Datatype *ct); ///< Construct given a name and data-type
|
||||||
Symbol(Scope *sc); ///< Construct for use with restoreXml()
|
Symbol(Scope *sc); ///< Construct for use with decode()
|
||||||
const string &getName(void) const { return name; } ///< Get the local name of the symbol
|
const string &getName(void) const { return name; } ///< Get the local name of the symbol
|
||||||
Datatype *getType(void) const { return type; } ///< Get the data-type
|
Datatype *getType(void) const { return type; } ///< Get the data-type
|
||||||
uint8 getId(void) const { return symbolId; } ///< Get a unique id for the symbol
|
uint8 getId(void) const { return symbolId; } ///< Get a unique id for the symbol
|
||||||
@@ -219,12 +241,12 @@ public:
|
|||||||
SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol
|
SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol
|
||||||
int4 getMapEntryPosition(const SymbolEntry *entry) const; ///< Position of given SymbolEntry within \b this multi-entry Symbol
|
int4 getMapEntryPosition(const SymbolEntry *entry) const; ///< Position of given SymbolEntry within \b this multi-entry Symbol
|
||||||
int4 getResolutionDepth(const Scope *useScope) const; ///< Get number of scope names needed to resolve \b this symbol
|
int4 getResolutionDepth(const Scope *useScope) const; ///< Get number of scope names needed to resolve \b this symbol
|
||||||
void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes
|
void encodeHeader(Encoder &encoder) const; ///< Encode basic Symbol properties as attributes
|
||||||
void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML
|
void decodeHeader(Decoder &decoder); ///< Decode basic Symbol properties from a \<symbol> element
|
||||||
void saveXmlBody(ostream &s) const; ///< Save details of the Symbol to XML
|
void encodeBody(Encoder &encoder) const; ///< Encode details of the Symbol to a stream
|
||||||
void restoreXmlBody(List::const_iterator iter); ///< Restore details of the Symbol from XML
|
void decodeBody(Decoder &decoder); ///< Decode details of the Symbol from a \<symbol> element
|
||||||
virtual void saveXml(ostream &s) const; ///< Save \b this Symbol to an XML stream
|
virtual void encode(Encoder &encoder) const; ///< Encode \b this Symbol to a stream
|
||||||
virtual void restoreXml(const Element *el); ///< Restore \b this Symbol from an XML stream
|
virtual void decode(Decoder &decoder); ///< Decode \b this Symbol from a stream
|
||||||
virtual int4 getBytesConsumed(void) const; ///< Get number of bytes consumed within the address->symbol map
|
virtual int4 getBytesConsumed(void) const; ///< Get number of bytes consumed within the address->symbol map
|
||||||
static uint8 ID_BASE; ///< Base of internal ID's
|
static uint8 ID_BASE; ///< Base of internal ID's
|
||||||
};
|
};
|
||||||
@@ -259,10 +281,10 @@ class FunctionSymbol : public Symbol {
|
|||||||
void buildType(void); ///< Build the data-type associated with \b this Symbol
|
void buildType(void); ///< Build the data-type associated with \b this Symbol
|
||||||
public:
|
public:
|
||||||
FunctionSymbol(Scope *sc,const string &nm,int4 size); ///< Construct given the name
|
FunctionSymbol(Scope *sc,const string &nm,int4 size); ///< Construct given the name
|
||||||
FunctionSymbol(Scope *sc,int4 size); ///< Constructor for use with restoreXml
|
FunctionSymbol(Scope *sc,int4 size); ///< Constructor for use with decode
|
||||||
Funcdata *getFunction(void); ///< Get the underlying Funcdata object
|
Funcdata *getFunction(void); ///< Get the underlying Funcdata object
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual int4 getBytesConsumed(void) const { return consumeSize; }
|
virtual int4 getBytesConsumed(void) const { return consumeSize; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -275,21 +297,21 @@ class EquateSymbol : public Symbol {
|
|||||||
uintb value; ///< Value of the constant being equated
|
uintb value; ///< Value of the constant being equated
|
||||||
public:
|
public:
|
||||||
EquateSymbol(Scope *sc,const string &nm,uint4 format,uintb val); ///< Constructor
|
EquateSymbol(Scope *sc,const string &nm,uint4 format,uintb val); ///< Constructor
|
||||||
EquateSymbol(Scope *sc) : Symbol(sc) { value = 0; category = equate; } ///< Constructor for use with restoreXml
|
EquateSymbol(Scope *sc) : Symbol(sc) { value = 0; category = equate; } ///< Constructor for use with decode
|
||||||
uintb getValue(void) const { return value; } ///< Get the constant value
|
uintb getValue(void) const { return value; } ///< Get the constant value
|
||||||
bool isValueClose(uintb op2Value,int4 size) const; ///< Is the given value similar to \b this equate
|
bool isValueClose(uintb op2Value,int4 size) const; ///< Is the given value similar to \b this equate
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnionFacetSymbol : public Symbol {
|
class UnionFacetSymbol : public Symbol {
|
||||||
int4 fieldNum; ///< Particular field to associate with Symbol access
|
int4 fieldNum; ///< Particular field to associate with Symbol access
|
||||||
public:
|
public:
|
||||||
UnionFacetSymbol(Scope *sc,const string &nm,Datatype *unionDt,int4 fldNum); ///< Constructor from components
|
UnionFacetSymbol(Scope *sc,const string &nm,Datatype *unionDt,int4 fldNum); ///< Constructor from components
|
||||||
UnionFacetSymbol(Scope *sc) : Symbol(sc) { fieldNum = -1; category = union_facet; } ///< Constructor for restoreXml
|
UnionFacetSymbol(Scope *sc) : Symbol(sc) { fieldNum = -1; category = union_facet; } ///< Constructor for decode
|
||||||
int4 getFieldNumber(void) const { return fieldNum; } ///< Get the particular field associate with \b this
|
int4 getFieldNumber(void) const { return fieldNum; } ///< Get the particular field associate with \b this
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A Symbol that labels code internal to a function
|
/// \brief A Symbol that labels code internal to a function
|
||||||
@@ -297,9 +319,9 @@ class LabSymbol : public Symbol {
|
|||||||
void buildType(void); ///< Build placeholder data-type
|
void buildType(void); ///< Build placeholder data-type
|
||||||
public:
|
public:
|
||||||
LabSymbol(Scope *sc,const string &nm); ///< Construct given name
|
LabSymbol(Scope *sc,const string &nm); ///< Construct given name
|
||||||
LabSymbol(Scope *sc); ///< Constructor for use with restoreXml
|
LabSymbol(Scope *sc); ///< Constructor for use with decode
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A function Symbol referring to an external location
|
/// \brief A function Symbol referring to an external location
|
||||||
@@ -314,10 +336,10 @@ class ExternRefSymbol : public Symbol {
|
|||||||
virtual ~ExternRefSymbol(void) {}
|
virtual ~ExternRefSymbol(void) {}
|
||||||
public:
|
public:
|
||||||
ExternRefSymbol(Scope *sc,const Address &ref,const string &nm); ///< Construct given a \e placeholder address
|
ExternRefSymbol(Scope *sc,const Address &ref,const string &nm); ///< Construct given a \e placeholder address
|
||||||
ExternRefSymbol(Scope *sc) : Symbol(sc) {} ///< For use with restoreXml
|
ExternRefSymbol(Scope *sc) : Symbol(sc) {} ///< For use with decode
|
||||||
const Address &getRefAddr(void) const { return refaddr; } ///< Return the \e placeholder address
|
const Address &getRefAddr(void) const { return refaddr; } ///< Return the \e placeholder address
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Comparator for sorting Symbol objects by name
|
/// \brief Comparator for sorting Symbol objects by name
|
||||||
@@ -391,6 +413,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Exception thrown when a function is added more than once to the database
|
||||||
|
///
|
||||||
|
/// Stores off the address of the function, so a handler can recover from the exception
|
||||||
|
/// and pick up the original symbol.
|
||||||
|
struct DuplicateFunctionError : public RecovError {
|
||||||
|
Address address; ///< Address of function causing the error
|
||||||
|
string functionName; ///< Name of the function
|
||||||
|
DuplicateFunctionError(const Address &addr,const string &nm) : RecovError("Duplicate Function") {
|
||||||
|
address = addr; functionName = nm; } ///< Constructor
|
||||||
|
};
|
||||||
|
|
||||||
typedef map<uint8,Scope *> ScopeMap; ///< A map from id to Scope
|
typedef map<uint8,Scope *> ScopeMap; ///< A map from id to Scope
|
||||||
|
|
||||||
/// \brief A collection of Symbol objects within a single (namespace or functional) scope
|
/// \brief A collection of Symbol objects within a single (namespace or functional) scope
|
||||||
@@ -661,8 +694,9 @@ public:
|
|||||||
/// \return return a unique version of the name
|
/// \return return a unique version of the name
|
||||||
virtual string makeNameUnique(const string &nm) const=0;
|
virtual string makeNameUnique(const string &nm) const=0;
|
||||||
|
|
||||||
virtual void saveXml(ostream &s) const=0; ///< Write out \b this as a \<scope> XML tag
|
virtual void encode(Encoder &encoder) const=0; ///< Encode \b this as a \<scope> element
|
||||||
virtual void restoreXml(const Element *el)=0; ///< Restore \b this Scope from a \<scope> XML tag
|
virtual void decode(Decoder &decoder)=0; ///< Decode \b this Scope from a \<scope> element
|
||||||
|
virtual void decodeWrappingAttributes(Decoder &decoder) {} ///< Restore attributes for \b this Scope from wrapping element
|
||||||
virtual void printEntries(ostream &s) const=0; ///< Dump a description of all SymbolEntry objects to a stream
|
virtual void printEntries(ostream &s) const=0; ///< Dump a description of all SymbolEntry objects to a stream
|
||||||
|
|
||||||
/// \brief Get the number of Symbols in the given category
|
/// \brief Get the number of Symbols in the given category
|
||||||
@@ -709,8 +743,8 @@ public:
|
|||||||
Scope *discoverScope(const Address &addr,int4 sz,const Address &usepoint); ///< Find the owning Scope of a given memory range
|
Scope *discoverScope(const Address &addr,int4 sz,const Address &usepoint); ///< Find the owning Scope of a given memory range
|
||||||
ScopeMap::const_iterator childrenBegin() const { return children.begin(); } ///< Beginning iterator of child scopes
|
ScopeMap::const_iterator childrenBegin() const { return children.begin(); } ///< Beginning iterator of child scopes
|
||||||
ScopeMap::const_iterator childrenEnd() const { return children.end(); } ///< Ending iterator of child scopes
|
ScopeMap::const_iterator childrenEnd() const { return children.end(); } ///< Ending iterator of child scopes
|
||||||
void saveXmlRecursive(ostream &s,bool onlyGlobal) const; ///< Save all contained scopes as an XML stream
|
void encodeRecursive(Encoder &encoder,bool onlyGlobal) const; ///< Encode all contained scopes to a stream
|
||||||
void overrideSizeLockType(Symbol *sym,Datatype *ct); ///< Change the data-type of a Symbol that is \e sizelocked
|
void overrideSizeLockType(Symbol *sym,Datatype *ct); ///< Change the data-type of a Symbol that is \e sizelocked
|
||||||
void resetSizeLockType(Symbol *sym); ///< Clear a Symbol's \e size-locked data-type
|
void resetSizeLockType(Symbol *sym); ///< Clear a Symbol's \e size-locked data-type
|
||||||
void setThisPointer(Symbol *sym,bool val) { sym->setThisPointer(val); } ///< Toggle the given Symbol as the "this" pointer
|
void setThisPointer(Symbol *sym,bool val) { sym->setThisPointer(val); } ///< Toggle the given Symbol as the "this" pointer
|
||||||
bool isSubScope(const Scope *scp) const; ///< Is this a sub-scope of the given Scope
|
bool isSubScope(const Scope *scp) const; ///< Is this a sub-scope of the given Scope
|
||||||
@@ -722,7 +756,7 @@ public:
|
|||||||
Symbol *addSymbol(const string &nm,Datatype *ct); ///< Add a new Symbol \e without mapping it to an address
|
Symbol *addSymbol(const string &nm,Datatype *ct); ///< Add a new Symbol \e without mapping it to an address
|
||||||
SymbolEntry *addMapPoint(Symbol *sym,const Address &addr,
|
SymbolEntry *addMapPoint(Symbol *sym,const Address &addr,
|
||||||
const Address &usepoint); ///< Map a Symbol to a specific address
|
const Address &usepoint); ///< Map a Symbol to a specific address
|
||||||
Symbol *addMapSym(const Element *el); ///< Add a mapped Symbol from a \<mapsym> XML tag
|
Symbol *addMapSym(Decoder &decoder); ///< Parse a mapped Symbol from a \<mapsym> element
|
||||||
FunctionSymbol *addFunction(const Address &addr,const string &nm);
|
FunctionSymbol *addFunction(const Address &addr,const string &nm);
|
||||||
ExternRefSymbol *addExternalRef(const Address &addr,const Address &refaddr,const string &nm);
|
ExternRefSymbol *addExternalRef(const Address &addr,const Address &refaddr,const string &nm);
|
||||||
LabSymbol *addCodeLabel(const Address &addr,const string &nm);
|
LabSymbol *addCodeLabel(const Address &addr,const string &nm);
|
||||||
@@ -740,8 +774,8 @@ public:
|
|||||||
/// a set of Symbol objects (the set owns the Symbol objects). It also implements
|
/// a set of Symbol objects (the set owns the Symbol objects). It also implements
|
||||||
/// a \b maptable, which is a list of rangemaps that own the SymbolEntry objects.
|
/// a \b maptable, which is a list of rangemaps that own the SymbolEntry objects.
|
||||||
class ScopeInternal : public Scope {
|
class ScopeInternal : public Scope {
|
||||||
void processHole(const Element *el);
|
void decodeHole(Decoder &decoder);
|
||||||
void processCollision(const Element *el);
|
void decodeCollision(Decoder &decoder);
|
||||||
void insertNameTree(Symbol *sym);
|
void insertNameTree(Symbol *sym);
|
||||||
SymbolNameTree::const_iterator findFirstByName(const string &nm) const;
|
SymbolNameTree::const_iterator findFirstByName(const string &nm) const;
|
||||||
protected:
|
protected:
|
||||||
@@ -799,8 +833,8 @@ public:
|
|||||||
Datatype *ct,int4 &index,uint4 flags) const;
|
Datatype *ct,int4 &index,uint4 flags) const;
|
||||||
virtual string buildUndefinedName(void) const;
|
virtual string buildUndefinedName(void) const;
|
||||||
virtual string makeNameUnique(const string &nm) const;
|
virtual string makeNameUnique(const string &nm) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void printEntries(ostream &s) const;
|
virtual void printEntries(ostream &s) const;
|
||||||
virtual int4 getCategorySize(int4 cat) const;
|
virtual int4 getCategorySize(int4 cat) const;
|
||||||
virtual Symbol *getCategorySymbol(int4 cat,int4 ind) const;
|
virtual Symbol *getCategorySymbol(int4 cat,int4 ind) const;
|
||||||
@@ -867,7 +901,7 @@ class Database {
|
|||||||
void clearResolve(Scope *scope); ///< Clear the \e ownership ranges associated with the given Scope
|
void clearResolve(Scope *scope); ///< Clear the \e ownership ranges associated with the given Scope
|
||||||
void clearReferences(Scope *scope); ///< Clear any map references to the given Scope and its children
|
void clearReferences(Scope *scope); ///< Clear any map references to the given Scope and its children
|
||||||
void fillResolve(Scope *scope); ///< Add the \e ownership ranges of the given Scope to the map
|
void fillResolve(Scope *scope); ///< Add the \e ownership ranges of the given Scope to the map
|
||||||
Scope *parseParentTag(const Element *el); ///< Figure out parent scope given \<parent> tag.
|
Scope *parseParentTag(Decoder &decoder); ///< Figure out parent scope given \<parent> tag.
|
||||||
public:
|
public:
|
||||||
Database(Architecture *g,bool idByName); ///< Constructor
|
Database(Architecture *g,bool idByName); ///< Constructor
|
||||||
~Database(void); ///< Destructor
|
~Database(void); ///< Destructor
|
||||||
@@ -891,9 +925,9 @@ public:
|
|||||||
void setPropertyRange(uint4 flags,const Range &range); ///< Set boolean properties over a given memory range
|
void setPropertyRange(uint4 flags,const Range &range); ///< Set boolean properties over a given memory range
|
||||||
void setProperties(const partmap<Address,uint4> &newflags) { flagbase = newflags; } ///< Replace the property map
|
void setProperties(const partmap<Address,uint4> &newflags) { flagbase = newflags; } ///< Replace the property map
|
||||||
const partmap<Address,uint4> &getProperties(void) const { return flagbase; } ///< Get the entire property map
|
const partmap<Address,uint4> &getProperties(void) const { return flagbase; } ///< Get the entire property map
|
||||||
void saveXml(ostream &s) const; ///< Save the whole Database to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode the whole Database to a stream
|
||||||
void restoreXml(const Element *el); ///< Recover the whole database from XML
|
void decode(Decoder &decoder); ///< Decode the whole database from a stream
|
||||||
void restoreXmlScope(const Element *el,Scope *newScope); ///< Register and fill out a single Scope from an XML \<scope> tag
|
void decodeScope(Decoder &decoder,Scope *newScope); ///< Register and fill out a single Scope from an XML \<scope> tag
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \param sc is the scope containing the new symbol
|
/// \param sc is the scope containing the new symbol
|
||||||
|
|||||||
@@ -52,120 +52,103 @@ 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
|
||||||
|
|
||||||
Document *doc = ghidra->getNamespacePath(id);
|
XmlDecode decoder;
|
||||||
if (doc == (Document *)0)
|
if (!ghidra->getNamespacePath(id,decoder))
|
||||||
throw LowlevelError("Could not get namespace info");
|
throw LowlevelError("Could not get namespace info");
|
||||||
|
|
||||||
Scope *curscope = symboltab->getGlobalScope(); // Get pointer to ourselves (which is not const)
|
Scope *curscope = symboltab->getGlobalScope(); // Get pointer to ourselves (which is not const)
|
||||||
try {
|
uint4 elemId = decoder.openElement();
|
||||||
const List &list(doc->getRoot()->getChildren());
|
uint4 subId = decoder.openElement();
|
||||||
List::const_iterator iter = list.begin();
|
decoder.closeElementSkipping(subId); // Skip element describing the root scope
|
||||||
++iter; // Skip element describing the root scope
|
for(;;) {
|
||||||
while(iter != list.end()) {
|
subId = decoder.openElement();
|
||||||
const Element *el = *iter;
|
if (subId == 0) break;
|
||||||
++iter;
|
uint8 scopeId = decoder.readUnsignedInteger(ATTRIB_ID);
|
||||||
uint8 scopeId;
|
curscope = symboltab->findCreateScope(scopeId, decoder.readString(ATTRIB_CONTENT), curscope);
|
||||||
istringstream s(el->getAttributeValue("id"));
|
decoder.closeElement(subId);
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> scopeId;
|
|
||||||
curscope = symboltab->findCreateScope(scopeId, el->getContent(), curscope);
|
|
||||||
}
|
|
||||||
delete doc;
|
|
||||||
}
|
|
||||||
catch(LowlevelError &err) {
|
|
||||||
delete doc;
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
return curscope;
|
return curscope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client can respond to a query negatively by sending a
|
/// The Ghidra client can respond to a query negatively by sending a
|
||||||
/// \<hole> tag, which describes the (largest) range of addresses containing
|
/// \<hole> element, which describes the (largest) range of addresses containing
|
||||||
/// the query address that do not have any Symbol mapped to them. This object
|
/// the query address that do not have any Symbol mapped to them. This object
|
||||||
/// stores this information in the \b holes map, which it consults to avoid
|
/// stores this information in the \b holes map, which it consults to avoid
|
||||||
/// sending queries for the same unmapped address repeatedly. The tag may
|
/// sending queries for the same unmapped address repeatedly. The tag may
|
||||||
/// also contain boolean property information about the memory range, which
|
/// also contain boolean property information about the memory range, which
|
||||||
/// also gets stored.
|
/// also gets stored.
|
||||||
/// \param el is the \<hole> element
|
/// \param decoder is the stream decoder
|
||||||
void ScopeGhidra::processHole(const Element *el) const
|
void ScopeGhidra::decodeHole(Decoder &decoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Range range;
|
uint4 elemId = decoder.openElement(ELEM_HOLE);
|
||||||
range.restoreXml(el,ghidra);
|
|
||||||
holes.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
|
||||||
uint4 flags = 0;
|
uint4 flags = 0;
|
||||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
Range range;
|
||||||
if ((el->getAttributeName(i)=="readonly")&&
|
range.decodeFromAttributes(decoder,ghidra);
|
||||||
xml_readbool(el->getAttributeValue(i)))
|
decoder.rewindAttributes();
|
||||||
|
for(;;) {
|
||||||
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) break;
|
||||||
|
if (attribId==ATTRIB_READONLY && decoder.readBool())
|
||||||
flags |= Varnode::readonly;
|
flags |= Varnode::readonly;
|
||||||
else if ((el->getAttributeName(i)=="volatile")&&
|
else if (attribId==ATTRIB_VOLATILE && decoder.readBool())
|
||||||
xml_readbool(el->getAttributeValue(i)))
|
|
||||||
flags |= Varnode::volatil;
|
flags |= Varnode::volatil;
|
||||||
}
|
}
|
||||||
|
holes.insertRange(range.getSpace(),range.getFirst(),range.getLast());
|
||||||
|
decoder.closeElement(elemId);
|
||||||
if (flags != 0) {
|
if (flags != 0) {
|
||||||
ghidra->symboltab->setPropertyRange(flags,range);
|
ghidra->symboltab->setPropertyRange(flags,range);
|
||||||
cacheDirty = true;
|
cacheDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the global object described by the XML document
|
/// Build the global object described by the stream element
|
||||||
/// and put it in the cache. The XML can either be a
|
/// and put it in the cache. The element can either be a \<hole>, describing the absence
|
||||||
/// \<hole> tag, describing the absence of symbols at the queried
|
/// of symbols at the queried address, or one of the symbol elements.
|
||||||
/// address, or one of the symbol tags
|
/// \param decoder is the stream decoder
|
||||||
/// \param doc is the XML document
|
|
||||||
/// \return the newly constructed Symbol or NULL if there was a hole
|
/// \return the newly constructed Symbol or NULL if there was a hole
|
||||||
Symbol *ScopeGhidra::dump2Cache(Document *doc) const
|
Symbol *ScopeGhidra::dump2Cache(Decoder &decoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
const Element *el = doc->getRoot();
|
|
||||||
Symbol *sym = (Symbol *)0;
|
Symbol *sym = (Symbol *)0;
|
||||||
|
|
||||||
if (el->getName() == "hole") {
|
uint4 elemId = decoder.peekElement();
|
||||||
processHole(el);
|
if (elemId == ELEM_HOLE) {
|
||||||
|
decodeHole(decoder);
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
List::const_iterator iter = el->getChildren().begin();
|
decoder.openElement();
|
||||||
uint8 scopeId;
|
uint8 scopeId = decoder.readUnsignedInteger(ATTRIB_ID);
|
||||||
{
|
|
||||||
istringstream s(el->getAttributeValue("id"));
|
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> scopeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope *scope = reresolveScope(scopeId);
|
Scope *scope = reresolveScope(scopeId);
|
||||||
el = *iter;
|
|
||||||
try {
|
try {
|
||||||
sym = scope->addMapSym(el);
|
sym = scope->addMapSym(decoder);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
catch(RecovError &err) {
|
catch(DuplicateFunctionError &err) {
|
||||||
// Duplicate name error (when trying to create the new function's scope)
|
// Duplicate name error (when trying to create the new function's scope)
|
||||||
// Check for function object where the full size is not stored in the cache
|
// Check for function object where the full size is not stored in the cache
|
||||||
// Entries for functions always start at the entry address
|
// Entries for functions always start at the entry address
|
||||||
// of the function in order to deal with non-contiguous functions
|
// of the function in order to deal with non-contiguous functions
|
||||||
// But ghidra will still return the function for queries at addresses in the
|
// But ghidra will still return the function for queries at addresses in the
|
||||||
// interior of the function
|
// interior of the function
|
||||||
const Element *symel = *el->getChildren().begin();
|
if (!err.address.isInvalid()) { // Make sure the address was parsed
|
||||||
if (symel->getName() == "function") { // Make sure new record is for a function
|
|
||||||
const Element *baseAddrEl = *symel->getChildren().begin();
|
|
||||||
Address baseaddr = Address::restoreXml( baseAddrEl, glb ); // Decode address from record
|
|
||||||
vector<Symbol *> symList;
|
vector<Symbol *> symList;
|
||||||
scope->queryByName(symel->getAttributeValue("name"),symList); // Lookup symbols with duplicate name
|
scope->queryByName(err.functionName,symList); // Lookup symbols with duplicate name
|
||||||
for(int4 i=0;i<symList.size();++i) {
|
for(int4 i=0;i<symList.size();++i) {
|
||||||
FunctionSymbol *funcSym = dynamic_cast<FunctionSymbol *>(symList[i]);
|
FunctionSymbol *funcSym = dynamic_cast<FunctionSymbol *>(symList[i]);
|
||||||
if (funcSym != (FunctionSymbol *)0) { // If duplicate symbol is for function
|
if (funcSym != (FunctionSymbol *)0) { // If duplicate symbol is for function
|
||||||
if (funcSym->getFunction()->getAddress() == baseaddr) { // and the address matches
|
if (funcSym->getFunction()->getAddress() == err.address) { // and the address matches
|
||||||
sym = funcSym; // use the old symbol
|
sym = funcSym; // use the old symbol
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sym == (Symbol *)0) {
|
if (sym == (Symbol *)0)
|
||||||
ostringstream s;
|
throw LowlevelError("DuplicateFunctionError, but could not recover original symbol");
|
||||||
s << err.explain << ": entry didn't cache";
|
|
||||||
throw LowlevelError(s.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (sym != (Symbol *)0) {
|
if (sym != (Symbol *)0) {
|
||||||
SymbolEntry *entry = sym->getFirstWholeMap();
|
SymbolEntry *entry = sym->getFirstWholeMap();
|
||||||
@@ -208,7 +191,6 @@ Symbol *ScopeGhidra::dump2Cache(Document *doc) const
|
|||||||
Symbol *ScopeGhidra::removeQuery(const Address &addr) const
|
Symbol *ScopeGhidra::removeQuery(const Address &addr) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Document *doc;
|
|
||||||
Symbol *sym = (Symbol *)0;
|
Symbol *sym = (Symbol *)0;
|
||||||
|
|
||||||
// Don't send up queries on constants or uniques
|
// Don't send up queries on constants or uniques
|
||||||
@@ -230,10 +212,9 @@ 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;
|
||||||
doc = ghidra->getMappedSymbolsXML(addr); // Query GHIDRA about this address
|
XmlDecode decoder;
|
||||||
if (doc != (Document *)0) {
|
if (ghidra->getMappedSymbolsXML(addr,decoder)) { // Query GHIDRA about this address
|
||||||
sym = dump2Cache(doc); // Add it to the cache
|
sym = dump2Cache(decoder); // Add it to the cache
|
||||||
delete doc;
|
|
||||||
}
|
}
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@@ -368,14 +349,12 @@ Funcdata *ScopeGhidra::resolveExternalRefFunction(ExternRefSymbol *sym) const
|
|||||||
if (resFd == (Funcdata *)0) {
|
if (resFd == (Funcdata *)0) {
|
||||||
// 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
|
||||||
Document *doc;
|
|
||||||
SymbolEntry *entry = sym->getFirstWholeMap();
|
SymbolEntry *entry = sym->getFirstWholeMap();
|
||||||
doc = ghidra->getExternalRefXML(entry->getAddr());
|
XmlDecode decoder;
|
||||||
if (doc != (Document *)0) {
|
if (ghidra->getExternalRefXML(entry->getAddr(),decoder)) {
|
||||||
FunctionSymbol *funcSym;
|
FunctionSymbol *funcSym;
|
||||||
// Make sure referenced function is cached
|
// Make sure referenced function is cached
|
||||||
funcSym = dynamic_cast<FunctionSymbol *>(dump2Cache(doc));
|
funcSym = dynamic_cast<FunctionSymbol *>(dump2Cache(decoder));
|
||||||
delete doc;
|
|
||||||
if (funcSym != (FunctionSymbol *)0)
|
if (funcSym != (FunctionSymbol *)0)
|
||||||
resFd = funcSym->getFunction();
|
resFd = funcSym->getFunction();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ class ScopeGhidra : public Scope {
|
|||||||
vector<int4> spacerange; ///< List of address spaces that are in the global range
|
vector<int4> spacerange; ///< List of address spaces that are in the global range
|
||||||
partmap<Address,uint4> flagbaseDefault; ///< Default boolean properties on memory
|
partmap<Address,uint4> flagbaseDefault; ///< Default boolean properties on memory
|
||||||
mutable bool cacheDirty; ///< Is flagbaseDefault different from cache
|
mutable bool cacheDirty; ///< Is flagbaseDefault different from cache
|
||||||
Symbol *dump2Cache(Document *doc) const; ///< Parse a response into the cache
|
Symbol *dump2Cache(Decoder &decoder) const; ///< Parse a response into the cache
|
||||||
Symbol *removeQuery(const Address &addr) const; ///< Process a query that missed the cache
|
Symbol *removeQuery(const Address &addr) const; ///< Process a query that missed the cache
|
||||||
void processHole(const Element *el) const; ///< Process a response describing a hole
|
void decodeHole(Decoder &decoder) const; ///< Process a \<hole> response element
|
||||||
Scope *reresolveScope(uint8 id) const; ///< Find the Scope that will contain a result Symbol
|
Scope *reresolveScope(uint8 id) const; ///< Find the Scope that will contain a result Symbol
|
||||||
virtual void addRange(AddrSpace *spc,uintb first,uintb last);
|
virtual void addRange(AddrSpace *spc,uintb first,uintb last);
|
||||||
virtual void removeRange(AddrSpace *spc,uintb first,uintb last) {
|
virtual void removeRange(AddrSpace *spc,uintb first,uintb last) {
|
||||||
@@ -107,8 +107,8 @@ public:
|
|||||||
virtual void renameSymbol(Symbol *sym,const string &newname) { throw LowlevelError("renameSymbol unimplemented"); }
|
virtual void renameSymbol(Symbol *sym,const string &newname) { throw LowlevelError("renameSymbol unimplemented"); }
|
||||||
virtual void retypeSymbol(Symbol *sym,Datatype *ct) { throw LowlevelError("retypeSymbol unimplemented"); }
|
virtual void retypeSymbol(Symbol *sym,Datatype *ct) { throw LowlevelError("retypeSymbol unimplemented"); }
|
||||||
virtual string makeNameUnique(const string &nm) const { throw LowlevelError("makeNameUnique unimplemented"); }
|
virtual string makeNameUnique(const string &nm) const { throw LowlevelError("makeNameUnique unimplemented"); }
|
||||||
virtual void saveXml(ostream &s) const { throw LowlevelError("saveXml unimplemented"); }
|
virtual void encode(Encoder &encoder) const { throw LowlevelError("encode unimplemented"); }
|
||||||
virtual void restoreXml(const Element *el) { throw LowlevelError("restoreXml unimplemented"); }
|
virtual void decode(Decoder &decoder) { throw LowlevelError("decode unimplemented"); }
|
||||||
virtual void printEntries(ostream &s) const { throw LowlevelError("printEntries unimplemented"); }
|
virtual void printEntries(ostream &s) const { throw LowlevelError("printEntries unimplemented"); }
|
||||||
virtual int4 getCategorySize(int4 cat) const { throw LowlevelError("getCategorySize unimplemented"); }
|
virtual int4 getCategorySize(int4 cat) const { throw LowlevelError("getCategorySize unimplemented"); }
|
||||||
virtual Symbol *getCategorySymbol(int4 cat,int4 ind) const { throw LowlevelError("getCategorySymbol unimplemented"); }
|
virtual Symbol *getCategorySymbol(int4 cat,int4 ind) const { throw LowlevelError("getCategorySymbol unimplemented"); }
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,38 @@
|
|||||||
|
|
||||||
class JoinRecord;
|
class JoinRecord;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_CUSTOM; ///< Marshaling attribute "custom"
|
||||||
|
extern AttributeId ATTRIB_DOTDOTDOT; ///< Marshaling attribute "dotdotdot"
|
||||||
|
extern AttributeId ATTRIB_EXTENSION; ///< Marshaling attribute "extension"
|
||||||
|
extern AttributeId ATTRIB_HASTHIS; ///< Marshaling attribute "hasthis"
|
||||||
|
extern AttributeId ATTRIB_INLINE; ///< Marshaling attribute "inline"
|
||||||
|
extern AttributeId ATTRIB_KILLEDBYCALL; ///< Marshaling attribute "killedbycall"
|
||||||
|
extern AttributeId ATTRIB_MAXSIZE; ///< Marshaling attribute "maxsize"
|
||||||
|
extern AttributeId ATTRIB_MINSIZE; ///< Marshaling attribute "minsize"
|
||||||
|
extern AttributeId ATTRIB_MODELLOCK; ///< Marshaling attribute "modellock"
|
||||||
|
extern AttributeId ATTRIB_NORETURN; ///< Marshaling attribute "noreturn"
|
||||||
|
extern AttributeId ATTRIB_POINTERMAX; ///< Marshaling attribute "pointermax"
|
||||||
|
extern AttributeId ATTRIB_SEPARATEFLOAT; ///< Marshaling attribute "separatefloat"
|
||||||
|
extern AttributeId ATTRIB_STACKSHIFT; ///< Marshaling attribute "stackshift"
|
||||||
|
extern AttributeId ATTRIB_STRATEGY; ///< Marshaling attribute "strategy"
|
||||||
|
extern AttributeId ATTRIB_THISBEFORERETPOINTER; ///< Marshaling attribute "thisbeforeretpointer"
|
||||||
|
extern AttributeId ATTRIB_VOIDLOCK; ///< Marshaling attribute "voidlock"
|
||||||
|
|
||||||
|
extern ElementId ELEM_GROUP; ///< Marshaling element \<group>
|
||||||
|
extern ElementId ELEM_INTERNALLIST; ///< Marshaling element \<internallist>
|
||||||
|
extern ElementId ELEM_KILLEDBYCALL; ///< Marshaling element \<killedbycall>
|
||||||
|
extern ElementId ELEM_LIKELYTRASH; ///< Marshaling element \<likelytrash>
|
||||||
|
extern ElementId ELEM_LOCALRANGE; ///< Marshaling element \<localrange>
|
||||||
|
extern ElementId ELEM_MODEL; ///< Marshaling element \<model>
|
||||||
|
extern ElementId ELEM_PARAM; ///< Marshaling element \<param>
|
||||||
|
extern ElementId ELEM_PARAMRANGE; ///< Marshaling element \<paramrange>
|
||||||
|
extern ElementId ELEM_PENTRY; ///< Marshaling element \<pentry>
|
||||||
|
extern ElementId ELEM_PROTOTYPE; ///< Marshaling element \<prototype>
|
||||||
|
extern ElementId ELEM_RESOLVEPROTOTYPE; ///< Marshaling element \<resolveprototype>
|
||||||
|
extern ElementId ELEM_RETPARAM; ///< Marshaling element \<retparam>
|
||||||
|
extern ElementId ELEM_RETURNSYM; ///< Marshaling element \<returnsym>
|
||||||
|
extern ElementId ELEM_UNAFFECTED; ///< Marshaling element \<unaffected>
|
||||||
|
|
||||||
/// \brief Exception thrown when a prototype can't be modeled properly
|
/// \brief Exception thrown when a prototype can't be modeled properly
|
||||||
struct ParamUnassignedError : public LowlevelError {
|
struct ParamUnassignedError : public LowlevelError {
|
||||||
ParamUnassignedError(const string &s) : LowlevelError(s) {} ///< Constructor
|
ParamUnassignedError(const string &s) : LowlevelError(s) {} ///< Constructor
|
||||||
@@ -85,7 +117,7 @@ private:
|
|||||||
/// \brief Is the logical value left-justified within its container
|
/// \brief Is the logical value left-justified within its container
|
||||||
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
|
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
|
||||||
public:
|
public:
|
||||||
ParamEntry(int4 grp) { group=grp; } ///< Constructor for use with restoreXml
|
ParamEntry(int4 grp) { group=grp; } ///< Constructor for use with decode
|
||||||
int4 getGroup(void) const { return group; } ///< Get the group id \b this belongs to
|
int4 getGroup(void) const { return group; } ///< Get the group id \b this belongs to
|
||||||
int4 getGroupSize(void) const { return groupsize; } ///< Get the number of groups occupied by \b this
|
int4 getGroupSize(void) const { return groupsize; } ///< Get the number of groups occupied by \b this
|
||||||
int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes.
|
int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes.
|
||||||
@@ -102,13 +134,13 @@ public:
|
|||||||
bool intersects(const Address &addr,int4 sz) const; ///< Does \b this intersect the given range in some way
|
bool intersects(const Address &addr,int4 sz) const; ///< Does \b this intersect the given range in some way
|
||||||
int4 justifiedContain(const Address &addr,int4 sz) const; ///< Calculate endian aware containment
|
int4 justifiedContain(const Address &addr,int4 sz) const; ///< Calculate endian aware containment
|
||||||
bool getContainer(const Address &addr,int4 sz,VarnodeData &res) const;
|
bool getContainer(const Address &addr,int4 sz,VarnodeData &res) const;
|
||||||
bool contains(const ParamEntry &op2) const; ///< Does \this contain the given entry (as a subpiece)
|
bool contains(const ParamEntry &op2) const; ///< Does \b this contain the given entry (as a subpiece)
|
||||||
OpCode assumedExtension(const Address &addr,int4 sz,VarnodeData &res) const;
|
OpCode assumedExtension(const Address &addr,int4 sz,VarnodeData &res) const;
|
||||||
int4 getSlot(const Address &addr,int4 skip) const;
|
int4 getSlot(const Address &addr,int4 skip) const;
|
||||||
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 restoreXml(const Element *el,const AddrSpaceManager *manage,bool normalstack,bool grouped,list<ParamEntry> &curList);
|
void decode(Decoder &decoder,const AddrSpaceManager *manage,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
|
||||||
@@ -302,11 +334,11 @@ public:
|
|||||||
class FspecSpace : public AddrSpace {
|
class FspecSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind); ///< Constructor
|
FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind); ///< Constructor
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset) const;
|
virtual void encodeAttributes(Encoder &encoder,uintb offset) const;
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
|
virtual void encodeAttributes(Encoder &encoder,uintb offset,int4 size) const;
|
||||||
virtual void printRaw(ostream &s,uintb offset) const;
|
virtual void printRaw(ostream &s,uintb offset) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
static const string NAME; ///< Reserved name for the fspec space
|
static const string NAME; ///< Reserved name for the fspec space
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -342,7 +374,7 @@ private:
|
|||||||
VarnodeData range; ///< The memory range affected
|
VarnodeData range; ///< The memory range affected
|
||||||
uint4 type; ///< The type of effect
|
uint4 type; ///< The type of effect
|
||||||
public:
|
public:
|
||||||
EffectRecord(void) {} ///< Constructor for use with restoreXml()
|
EffectRecord(void) {} ///< Constructor for use with decode()
|
||||||
EffectRecord(const EffectRecord &op2) { range = op2.range; type = op2.type; } ///< Copy constructor
|
EffectRecord(const EffectRecord &op2) { range = op2.range; type = op2.type; } ///< Copy constructor
|
||||||
EffectRecord(const Address &addr,int4 size); ///< Construct a memory range with an unknown effect
|
EffectRecord(const Address &addr,int4 size); ///< Construct a memory range with an unknown effect
|
||||||
EffectRecord(const ParamEntry &entry,uint4 t); ///< Construct an effect on a parameter storage location
|
EffectRecord(const ParamEntry &entry,uint4 t); ///< Construct an effect on a parameter storage location
|
||||||
@@ -352,8 +384,8 @@ public:
|
|||||||
int4 getSize(void) const { return range.size; } ///< Get the size of the affected range
|
int4 getSize(void) const { return range.size; } ///< Get the size of the affected range
|
||||||
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 saveXml(ostream &s) const; ///< Save the record to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode the record to a stream
|
||||||
void restoreXml(uint4 grouptype,const Element *el,const AddrSpaceManager *manage); ///< Restore the record from an XML stream
|
void decode(uint4 grouptype,Decoder &decoder,const AddrSpaceManager *manage); ///< Decode the record from a stream
|
||||||
static bool compareByAddress(const EffectRecord &op1,const EffectRecord &op2);
|
static bool compareByAddress(const EffectRecord &op1,const EffectRecord &op2);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -496,13 +528,13 @@ public:
|
|||||||
/// \return the maximum number of passes across all parameters in \b this model
|
/// \return the maximum number of passes across all parameters in \b this model
|
||||||
virtual int4 getMaxDelay(void) const=0;
|
virtual int4 getMaxDelay(void) const=0;
|
||||||
|
|
||||||
/// \brief Restore the model from an XML stream
|
/// \brief Restore the model from an \<input> or \<output> element in the stream
|
||||||
///
|
///
|
||||||
/// \param el is the root \<input> or \<output> element
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is used to resolve references to address spaces
|
/// \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 restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)=0;
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,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
|
||||||
};
|
};
|
||||||
@@ -539,12 +571,12 @@ 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(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
|
void parsePentry(Decoder &decoder,const AddrSpaceManager *manage,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(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,
|
void parseGroup(Decoder &decoder,const AddrSpaceManager *manage,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 restoreXml()
|
ParamListStandard(void) {} ///< Construct for use with decode()
|
||||||
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
||||||
virtual ~ParamListStandard(void);
|
virtual ~ParamListStandard(void);
|
||||||
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
||||||
@@ -562,7 +594,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 restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -593,7 +625,7 @@ public:
|
|||||||
/// conventions. The assignMap() method may make less sense in this scenario.
|
/// conventions. The assignMap() method may make less sense in this scenario.
|
||||||
class ParamListRegister : public ParamListStandard {
|
class ParamListRegister : public ParamListStandard {
|
||||||
public:
|
public:
|
||||||
ParamListRegister(void) : ParamListStandard() {} ///< Constructor for use with restoreXml()
|
ParamListRegister(void) : ParamListStandard() {} ///< Constructor for use with decode()
|
||||||
ParamListRegister(const ParamListRegister &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
ParamListRegister(const ParamListRegister &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
||||||
virtual uint4 getType(void) const { return p_register; }
|
virtual uint4 getType(void) const { return p_register; }
|
||||||
virtual void fillinMap(ParamActive *active) const;
|
virtual void fillinMap(ParamActive *active) const;
|
||||||
@@ -610,11 +642,11 @@ public:
|
|||||||
/// to inform the input model.
|
/// to inform the input model.
|
||||||
class ParamListStandardOut : public ParamListRegisterOut {
|
class ParamListStandardOut : public ParamListRegisterOut {
|
||||||
public:
|
public:
|
||||||
ParamListStandardOut(void) : ParamListRegisterOut() {} ///< Constructor for use with restoreXml()
|
ParamListStandardOut(void) : ParamListRegisterOut() {} ///< Constructor for use with decode()
|
||||||
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 restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -628,7 +660,7 @@ public:
|
|||||||
/// need to be invoked.
|
/// need to be invoked.
|
||||||
class ParamListMerged : public ParamListStandard {
|
class ParamListMerged : public ParamListStandard {
|
||||||
public:
|
public:
|
||||||
ParamListMerged(void) : ParamListStandard() {} ///< Constructor for use with restoreXml
|
ParamListMerged(void) : ParamListStandard() {} ///< Constructor for use with decode
|
||||||
ParamListMerged(const ParamListMerged &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
ParamListMerged(const ParamListMerged &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
||||||
void foldIn(const ParamListStandard &op2); ///< Add another model to the union
|
void foldIn(const ParamListStandard &op2); ///< Add another model to the union
|
||||||
void finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
|
void finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
|
||||||
@@ -686,7 +718,7 @@ public:
|
|||||||
enum {
|
enum {
|
||||||
extrapop_unknown = 0x8000 ///< Reserved extrapop value meaning the function's \e extrapop is unknown
|
extrapop_unknown = 0x8000 ///< Reserved extrapop value meaning the function's \e extrapop is unknown
|
||||||
};
|
};
|
||||||
ProtoModel(Architecture *g); ///< Constructor for use with restoreXml()
|
ProtoModel(Architecture *g); ///< Constructor for use with decode()
|
||||||
ProtoModel(const string &nm,const ProtoModel &op2); ///< Copy constructor changing the name
|
ProtoModel(const string &nm,const ProtoModel &op2); ///< Copy constructor changing the name
|
||||||
virtual ~ProtoModel(void); ///< Destructor
|
virtual ~ProtoModel(void); ///< Destructor
|
||||||
const string &getName(void) const { return name; } ///< Get the name of the prototype model
|
const string &getName(void) const { return name; } ///< Get the name of the prototype model
|
||||||
@@ -909,7 +941,7 @@ public:
|
|||||||
int4 getMaxOutputDelay(void) const { return output->getMaxDelay(); }
|
int4 getMaxOutputDelay(void) const { return output->getMaxDelay(); }
|
||||||
|
|
||||||
virtual bool isMerged(void) const { return false; } ///< Is \b this a merged prototype model
|
virtual bool isMerged(void) const { return false; } ///< Is \b this a merged prototype model
|
||||||
virtual void restoreXml(const Element *el); ///< Restore \b this model from an XML stream
|
virtual void decode(Decoder &decoder); ///< Restore \b this model from a stream
|
||||||
static uint4 lookupEffect(const vector<EffectRecord> &efflist,const Address &addr,int4 size);
|
static uint4 lookupEffect(const vector<EffectRecord> &efflist,const Address &addr,int4 size);
|
||||||
static int4 lookupRecord(const vector<EffectRecord> &efflist,int4 listSize,const Address &addr,int4 size);
|
static int4 lookupRecord(const vector<EffectRecord> &efflist,int4 listSize,const Address &addr,int4 size);
|
||||||
};
|
};
|
||||||
@@ -969,7 +1001,7 @@ public:
|
|||||||
void foldIn(ProtoModel *model); ///< Fold-in an additional prototype model
|
void foldIn(ProtoModel *model); ///< Fold-in an additional prototype model
|
||||||
ProtoModel *selectModel(ParamActive *active) const; ///< Select the best model given a set of trials
|
ProtoModel *selectModel(ParamActive *active) const; ///< Select the best model given a set of trials
|
||||||
virtual bool isMerged(void) const { return true; }
|
virtual bool isMerged(void) const { return true; }
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Symbol;
|
class Symbol;
|
||||||
@@ -1116,18 +1148,19 @@ public:
|
|||||||
virtual ProtoParameter *getOutput(void)=0; ///< Get the return-value description
|
virtual ProtoParameter *getOutput(void)=0; ///< Get the return-value description
|
||||||
virtual ProtoStore *clone(void) const=0; ///< Clone the entire collection of parameter descriptions
|
virtual ProtoStore *clone(void) const=0; ///< Clone the entire collection of parameter descriptions
|
||||||
|
|
||||||
/// \brief Save any parameters that are not backed by symbols to an XML stream
|
/// \brief Encode any parameters that are not backed by symbols to a stream
|
||||||
///
|
///
|
||||||
/// Symbols are stored elsewhere, so symbol backed parameters are not serialized.
|
/// Symbols are stored elsewhere, so symbol backed parameters are not serialized.
|
||||||
/// If there are any internal parameters an \<internallist> tag is emitted.
|
/// If there are any internal parameters an \<internallist> element is emitted.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
virtual void saveXml(ostream &s) const=0;
|
virtual void encode(Encoder &encoder) const=0;
|
||||||
|
|
||||||
/// \brief Restore any internal parameter descriptions from an XML stream
|
/// \brief Restore any internal parameter descriptions from a stream
|
||||||
///
|
///
|
||||||
/// \param el is a root \<internallist> element containing \<param> and \<retparam> sub-tags.
|
/// Parse an \<internallist> element containing \<param> and \<retparam> child elements.
|
||||||
|
/// \param decoder is the stream decoder
|
||||||
/// \param model is prototype model for determining storage for unassigned parameters
|
/// \param model is prototype model for determining storage for unassigned parameters
|
||||||
virtual void restoreXml(const Element *el,ProtoModel *model)=0;
|
virtual void decode(Decoder &decoder,ProtoModel *model)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A parameter with a formal backing Symbol
|
/// \brief A parameter with a formal backing Symbol
|
||||||
@@ -1183,8 +1216,8 @@ public:
|
|||||||
virtual void clearOutput(void);
|
virtual void clearOutput(void);
|
||||||
virtual ProtoParameter *getOutput(void);
|
virtual ProtoParameter *getOutput(void);
|
||||||
virtual ProtoStore *clone(void) const;
|
virtual ProtoStore *clone(void) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,ProtoModel *model);
|
virtual void decode(Decoder &decoder,ProtoModel *model);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A collection of parameter descriptions without backing symbols
|
/// \brief A collection of parameter descriptions without backing symbols
|
||||||
@@ -1207,8 +1240,8 @@ public:
|
|||||||
virtual void clearOutput(void);
|
virtual void clearOutput(void);
|
||||||
virtual ProtoParameter *getOutput(void);
|
virtual ProtoParameter *getOutput(void);
|
||||||
virtual ProtoStore *clone(void) const;
|
virtual ProtoStore *clone(void) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,ProtoModel *model);
|
virtual void decode(Decoder &decoder,ProtoModel *model);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Raw components of a function prototype (obtained from parsing source code)
|
/// \brief Raw components of a function prototype (obtained from parsing source code)
|
||||||
@@ -1258,10 +1291,10 @@ class FuncProto {
|
|||||||
int4 injectid; ///< (If non-negative) id of p-code snippet that should replace this function
|
int4 injectid; ///< (If non-negative) id of p-code snippet that should replace this function
|
||||||
int4 returnBytesConsumed; ///< Number of bytes of return value that are consumed by callers (0 = all bytes)
|
int4 returnBytesConsumed; ///< Number of bytes of return value that are consumed by callers (0 = all bytes)
|
||||||
void updateThisPointer(void); ///< Make sure any "this" parameter is properly marked
|
void updateThisPointer(void); ///< Make sure any "this" parameter is properly marked
|
||||||
void saveEffectXml(ostream &s) const; ///< Save any overriding EffectRecords to XML stream
|
void encodeEffect(Encoder &encoder) const; ///< Encode any overriding EffectRecords to stream
|
||||||
void saveLikelyTrashXml(ostream &s) const; ///< Save any overriding likelytrash registers to XML stream
|
void encodeLikelyTrash(Encoder &encoder) const; ///< Encode any overriding likelytrash registers to stream
|
||||||
void restoreEffectXml(void); ///< Merge in any EffectRecord overrides
|
void decodeEffect(void); ///< Merge in any EffectRecord overrides
|
||||||
void restoreLikelyTrashXml(void); ///< Merge in any \e likelytrash overrides
|
void decodeLikelyTrash(void); ///< Merge in any \e likelytrash overrides
|
||||||
protected:
|
protected:
|
||||||
void paramShift(int4 paramshift); ///< Add parameters to the front of the input parameter list
|
void paramShift(int4 paramshift); ///< Add parameters to the front of the input parameter list
|
||||||
bool isParamshiftApplied(void) const { return ((flags¶mshift_applied)!=0); } ///< Has a parameter shift been applied
|
bool isParamshiftApplied(void) const { return ((flags¶mshift_applied)!=0); } ///< Has a parameter shift been applied
|
||||||
@@ -1502,8 +1535,8 @@ public:
|
|||||||
/// \return the active set of flags for \b this prototype
|
/// \return the active set of flags for \b this prototype
|
||||||
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
|
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
|
||||||
|
|
||||||
void saveXml(ostream &s) const;
|
void encode(Encoder &encoder) const;
|
||||||
void restoreXml(const Element *el,Architecture *glb);
|
void decode(Decoder &decoder,Architecture *glb);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Funcdata;
|
class Funcdata;
|
||||||
|
|||||||
@@ -14,7 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
//#include <fstream>
|
|
||||||
|
AttributeId ATTRIB_NOCODE = AttributeId("nocode",70);
|
||||||
|
|
||||||
|
ElementId ELEM_AST = ElementId("ast",89);
|
||||||
|
ElementId ELEM_FUNCTION = ElementId("function",90);
|
||||||
|
ElementId ELEM_HIGHLIST = ElementId("highlist",91);
|
||||||
|
ElementId ELEM_JUMPTABLELIST = ElementId("jumptablelist",92);
|
||||||
|
ElementId ELEM_VARNODES = ElementId("varnodes",93);
|
||||||
|
|
||||||
/// \param nm is the (base) name of the function
|
/// \param nm is the (base) name of the function
|
||||||
/// \param scope is Symbol scope associated with the function
|
/// \param scope is Symbol scope associated with the function
|
||||||
@@ -42,7 +49,7 @@ Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,FunctionSym
|
|||||||
size = sz;
|
size = sz;
|
||||||
AddrSpace *stackid = glb->getStackSpace();
|
AddrSpace *stackid = glb->getStackSpace();
|
||||||
if (nm.size()==0)
|
if (nm.size()==0)
|
||||||
localmap = (ScopeLocal *)0; // Filled in by restoreXml
|
localmap = (ScopeLocal *)0; // Filled in by decode
|
||||||
else {
|
else {
|
||||||
uint8 id;
|
uint8 id;
|
||||||
if (sym != (FunctionSymbol *)0)
|
if (sym != (FunctionSymbol *)0)
|
||||||
@@ -542,66 +549,65 @@ void Funcdata::printLocalRange(ostream &s) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This parses a \<jumptablelist> tag and builds a JumpTable object for
|
/// Parse a \<jumptablelist> element and build a JumpTable object for
|
||||||
/// each \<jumptable> sub-tag.
|
/// each \<jumptable> child element.
|
||||||
/// \param el is the root \<jumptablelist> tag
|
/// \param decoder is the stream decoder
|
||||||
void Funcdata::restoreXmlJumpTable(const Element *el)
|
void Funcdata::decodeJumpTable(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list( el->getChildren() );
|
uint4 elemId = decoder.openElement(ELEM_JUMPTABLELIST);
|
||||||
List::const_iterator iter;
|
while(decoder.peekElement() != 0) {
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
|
||||||
JumpTable *jt = new JumpTable(glb);
|
JumpTable *jt = new JumpTable(glb);
|
||||||
jt->restoreXml(*iter);
|
jt->decode(decoder);
|
||||||
jumpvec.push_back(jt);
|
jumpvec.push_back(jt);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A \<jumptablelist> tag is written with \<jumptable> sub-tags describing
|
/// A \<jumptablelist> element is written with \<jumptable> children describing
|
||||||
/// each jump-table associated with the control-flow of \b this function.
|
/// each jump-table associated with the control-flow of \b this function.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void Funcdata::saveXmlJumpTable(ostream &s) const
|
void Funcdata::encodeJumpTable(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (jumpvec.empty()) return;
|
if (jumpvec.empty()) return;
|
||||||
vector<JumpTable *>::const_iterator iter;
|
vector<JumpTable *>::const_iterator iter;
|
||||||
|
|
||||||
s << "<jumptablelist>\n";
|
encoder.openElement(ELEM_JUMPTABLELIST);
|
||||||
for(iter=jumpvec.begin();iter!=jumpvec.end();++iter)
|
for(iter=jumpvec.begin();iter!=jumpvec.end();++iter)
|
||||||
(*iter)->saveXml(s);
|
(*iter)->encode(encoder);
|
||||||
s << "</jumptablelist>\n";
|
encoder.closeElement(ELEM_JUMPTABLELIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Save XML descriptions for a set of Varnodes to stream
|
/// \brief Encode descriptions for a set of Varnodes to a stream
|
||||||
///
|
///
|
||||||
/// This is an internal function for the function's save to XML system.
|
/// This is an internal function for the function's marshaling system.
|
||||||
/// Individual XML tags are written in sequence for Varnodes in a given set.
|
/// Individual elements are written in sequence for Varnodes in a given set.
|
||||||
/// The set is bounded by iterators using the 'loc' ordering.
|
/// The set is bounded by iterators using the 'loc' ordering.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
/// \param iter is the beginning of the set
|
/// \param iter is the beginning of the set
|
||||||
/// \param enditer is the end of the set
|
/// \param enditer is the end of the set
|
||||||
void Funcdata::saveVarnodeXml(ostream &s,VarnodeLocSet::const_iterator iter,VarnodeLocSet::const_iterator enditer)
|
void Funcdata::encodeVarnode(Encoder &encoder,VarnodeLocSet::const_iterator iter,VarnodeLocSet::const_iterator enditer)
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *vn;
|
Varnode *vn;
|
||||||
while(iter!=enditer) {
|
while(iter!=enditer) {
|
||||||
vn = *iter++;
|
vn = *iter++;
|
||||||
vn->saveXml(s);
|
vn->encode(encoder);
|
||||||
s << '\n';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This produces a single \<highlist> tag, with a \<high> sub-tag for each
|
/// This produces a single \<highlist> element, with a \<high> child for each
|
||||||
/// high-level variable (HighVariable) currently associated with \b this function.
|
/// high-level variable (HighVariable) currently associated with \b this function.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void Funcdata::saveXmlHigh(ostream &s) const
|
void Funcdata::encodeHigh(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *vn;
|
Varnode *vn;
|
||||||
HighVariable *high;
|
HighVariable *high;
|
||||||
|
|
||||||
if (!isHighOn()) return;
|
if (!isHighOn()) return;
|
||||||
s << "<highlist>";
|
encoder.openElement(ELEM_HIGHLIST);
|
||||||
VarnodeLocSet::const_iterator iter;
|
VarnodeLocSet::const_iterator iter;
|
||||||
for(iter=beginLoc();iter!=endLoc();++iter) {
|
for(iter=beginLoc();iter!=endLoc();++iter) {
|
||||||
vn = *iter;
|
vn = *iter;
|
||||||
@@ -609,104 +615,98 @@ void Funcdata::saveXmlHigh(ostream &s) const
|
|||||||
high = vn->getHigh();
|
high = vn->getHigh();
|
||||||
if (high->isMark()) continue;
|
if (high->isMark()) continue;
|
||||||
high->setMark();
|
high->setMark();
|
||||||
high->saveXml(s);
|
high->encode(encoder);
|
||||||
}
|
}
|
||||||
for(iter=beginLoc();iter!=endLoc();++iter) {
|
for(iter=beginLoc();iter!=endLoc();++iter) {
|
||||||
vn = *iter;
|
vn = *iter;
|
||||||
if (!vn->isAnnotation())
|
if (!vn->isAnnotation())
|
||||||
vn->getHigh()->clearMark();
|
vn->getHigh()->clearMark();
|
||||||
}
|
}
|
||||||
|
encoder.closeElement(ELEM_HIGHLIST);
|
||||||
s << "</highlist>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single \<ast> tag is produced with children describing Varnodes, PcodeOps, and
|
/// A single \<ast> element is produced with children describing Varnodes, PcodeOps, and
|
||||||
/// basic blocks making up \b this function's current syntax tree.
|
/// basic blocks making up \b this function's current syntax tree.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void Funcdata::saveXmlTree(ostream &s) const
|
void Funcdata::encodeTree(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<ast>\n";
|
encoder.openElement(ELEM_AST);
|
||||||
s << "<varnodes>\n";
|
encoder.openElement(ELEM_VARNODES);
|
||||||
for(int4 i=0;i<glb->numSpaces();++i) {
|
for(int4 i=0;i<glb->numSpaces();++i) {
|
||||||
AddrSpace *base = glb->getSpace(i);
|
AddrSpace *base = glb->getSpace(i);
|
||||||
if (base == (AddrSpace *)0 || base->getType()==IPTR_IOP) continue;
|
if (base == (AddrSpace *)0 || base->getType()==IPTR_IOP) continue;
|
||||||
VarnodeLocSet::const_iterator iter = vbank.beginLoc(base);
|
VarnodeLocSet::const_iterator iter = vbank.beginLoc(base);
|
||||||
VarnodeLocSet::const_iterator enditer = vbank.endLoc(base);
|
VarnodeLocSet::const_iterator enditer = vbank.endLoc(base);
|
||||||
saveVarnodeXml(s,iter,enditer);
|
encodeVarnode(encoder,iter,enditer);
|
||||||
}
|
}
|
||||||
s << "</varnodes>\n";
|
encoder.closeElement(ELEM_VARNODES);
|
||||||
|
|
||||||
list<PcodeOp *>::iterator oiter,endoiter;
|
list<PcodeOp *>::iterator oiter,endoiter;
|
||||||
PcodeOp *op;
|
PcodeOp *op;
|
||||||
BlockBasic *bs;
|
BlockBasic *bs;
|
||||||
for(int4 i=0;i<bblocks.getSize();++i) {
|
for(int4 i=0;i<bblocks.getSize();++i) {
|
||||||
bs = (BlockBasic *)bblocks.getBlock(i);
|
bs = (BlockBasic *)bblocks.getBlock(i);
|
||||||
s << "<block";
|
encoder.openElement(ELEM_BLOCK);
|
||||||
a_v_i(s,"index",bs->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, bs->getIndex());
|
||||||
s << ">\n";
|
bs->encodeBody(encoder);
|
||||||
bs->saveXmlBody(s);
|
|
||||||
oiter = bs->beginOp();
|
oiter = bs->beginOp();
|
||||||
endoiter = bs->endOp();
|
endoiter = bs->endOp();
|
||||||
while(oiter != endoiter) {
|
while(oiter != endoiter) {
|
||||||
op = *oiter++;
|
op = *oiter++;
|
||||||
op->saveXml(s);
|
op->encode(encoder);
|
||||||
s << '\n';
|
|
||||||
}
|
}
|
||||||
s << "</block>\n";
|
encoder.closeElement(ELEM_BLOCK);
|
||||||
}
|
}
|
||||||
for(int4 i=0;i<bblocks.getSize();++i) {
|
for(int4 i=0;i<bblocks.getSize();++i) {
|
||||||
bs = (BlockBasic *)bblocks.getBlock(i);
|
bs = (BlockBasic *)bblocks.getBlock(i);
|
||||||
if (bs->sizeIn() == 0) continue;
|
if (bs->sizeIn() == 0) continue;
|
||||||
s << "<blockedge";
|
encoder.openElement(ELEM_BLOCKEDGE);
|
||||||
a_v_i(s,"index",bs->getIndex());
|
encoder.writeSignedInteger(ATTRIB_INDEX, bs->getIndex());
|
||||||
s << ">\n";
|
bs->encodeEdges(encoder);
|
||||||
bs->saveXmlEdges(s);
|
encoder.closeElement(ELEM_BLOCKEDGE);
|
||||||
s << "</blockedge>\n";
|
|
||||||
}
|
}
|
||||||
s << "</ast>\n";
|
encoder.closeElement(ELEM_AST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An XML description of \b this function is written to the stream,
|
/// A description of \b this function is written to the stream,
|
||||||
/// including name, address, prototype, symbol, jump-table, and override information.
|
/// including name, address, prototype, symbol, jump-table, and override information.
|
||||||
/// If indicated by the caller, a description of the entire PcodeOp and Varnode
|
/// If indicated by the caller, a description of the entire PcodeOp and Varnode
|
||||||
/// tree is also emitted.
|
/// tree is also emitted.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
/// \param id is the unique id associated with the function symbol
|
/// \param id is the unique id associated with the function symbol
|
||||||
/// \param savetree is \b true if the p-code tree should be emitted
|
/// \param savetree is \b true if the p-code tree should be emitted
|
||||||
void Funcdata::saveXml(ostream &s,uint8 id,bool savetree) const
|
void Funcdata::encode(Encoder &encoder,uint8 id,bool savetree) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<function";
|
encoder.openElement(ELEM_FUNCTION);
|
||||||
if (id != 0)
|
if (id != 0)
|
||||||
a_v_u(s, "id", id);
|
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||||
a_v(s,"name",name);
|
encoder.writeString(ATTRIB_NAME, name);
|
||||||
a_v_i(s,"size",size);
|
encoder.writeSignedInteger(ATTRIB_SIZE, size);
|
||||||
if (hasNoCode())
|
if (hasNoCode())
|
||||||
a_v_b(s,"nocode",true);
|
encoder.writeBool(ATTRIB_NOCODE, true);
|
||||||
s << ">\n";
|
baseaddr.encode(encoder);
|
||||||
baseaddr.saveXml(s);
|
|
||||||
s << '\n';
|
|
||||||
|
|
||||||
if (!hasNoCode()) {
|
if (!hasNoCode()) {
|
||||||
localmap->saveXmlRecursive(s,false); // Save scope and all subscopes
|
localmap->encodeRecursive(encoder,false); // Save scope and all subscopes
|
||||||
}
|
}
|
||||||
|
|
||||||
if (savetree) {
|
if (savetree) {
|
||||||
saveXmlTree(s);
|
encodeTree(encoder);
|
||||||
saveXmlHigh(s);
|
encodeHigh(encoder);
|
||||||
}
|
}
|
||||||
saveXmlJumpTable(s);
|
encodeJumpTable(encoder);
|
||||||
funcp.saveXml(s); // Must be saved after database
|
funcp.encode(encoder); // Must be saved after database
|
||||||
localoverride.saveXml(s,glb);
|
localoverride.encode(encoder,glb);
|
||||||
s << "</function>\n";
|
encoder.closeElement(ELEM_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// From an XML \<function> tag, recover the name, address, prototype, symbol,
|
/// Parse a \<function> element, recovering the name, address, prototype, symbol,
|
||||||
/// jump-table, and override information for \b this function.
|
/// jump-table, and override information for \b this function.
|
||||||
/// \param el is the root \<function> tag
|
/// \param decoder is the stream decoder
|
||||||
/// \return the symbol id associated with the function
|
/// \return the symbol id associated with the function
|
||||||
uint8 Funcdata::restoreXml(const Element *el)
|
uint8 Funcdata::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
// clear(); // Shouldn't be needed
|
// clear(); // Shouldn't be needed
|
||||||
@@ -714,22 +714,20 @@ uint8 Funcdata::restoreXml(const Element *el)
|
|||||||
size = -1;
|
size = -1;
|
||||||
uint8 id = 0;
|
uint8 id = 0;
|
||||||
AddrSpace *stackid = glb->getStackSpace();
|
AddrSpace *stackid = glb->getStackSpace();
|
||||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
uint4 elemId = decoder.openElement(ELEM_FUNCTION);
|
||||||
const string &attrName(el->getAttributeName(i));
|
for(;;) {
|
||||||
if (attrName == "name")
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
name = el->getAttributeValue(i);
|
if (attribId == 0) break;
|
||||||
else if (attrName == "size") {
|
if (attribId == ATTRIB_NAME)
|
||||||
istringstream s( el->getAttributeValue(i));
|
name = decoder.readString();
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
else if (attribId == ATTRIB_SIZE) {
|
||||||
s >> size;
|
size = decoder.readSignedInteger();
|
||||||
}
|
}
|
||||||
else if (attrName == "id") {
|
else if (attribId == ATTRIB_ID) {
|
||||||
istringstream s( el->getAttributeValue(i));
|
id = decoder.readUnsignedInteger();
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> id;
|
|
||||||
}
|
}
|
||||||
else if (attrName == "nocode") {
|
else if (attribId == ATTRIB_NOCODE) {
|
||||||
if (xml_readbool(el->getAttributeValue(i)))
|
if (decoder.readBool())
|
||||||
flags |= no_code;
|
flags |= no_code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,27 +735,20 @@ uint8 Funcdata::restoreXml(const Element *el)
|
|||||||
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");
|
||||||
const List &list( el->getChildren() );
|
baseaddr = Address::decode( decoder, glb );
|
||||||
List::const_iterator iter = list.begin();
|
for(;;) {
|
||||||
baseaddr = Address::restoreXml( *iter, glb );
|
uint4 subId = decoder.peekElement();
|
||||||
++iter;
|
if (subId == 0) break;
|
||||||
for(;iter!=list.end();++iter) {
|
if (subId == ELEM_LOCALDB) {
|
||||||
if ((*iter)->getName() == "localdb") {
|
|
||||||
if (localmap != (ScopeLocal *)0)
|
if (localmap != (ScopeLocal *)0)
|
||||||
throw LowlevelError("Pre-existing local scope when restoring: "+name);
|
throw LowlevelError("Pre-existing local scope when restoring: "+name);
|
||||||
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
||||||
glb->symboltab->restoreXmlScope(*iter,newMap); // May delete newMap and throw
|
glb->symboltab->decodeScope(decoder,newMap); // May delete newMap and throw
|
||||||
localmap = newMap;
|
localmap = newMap;
|
||||||
}
|
}
|
||||||
// else if ((*iter)->getName() == "scope") {
|
else if (subId == ELEM_OVERRIDE)
|
||||||
// const Element *scopeel = *iter;
|
localoverride.decode(decoder,glb);
|
||||||
// ScopeInternal *subscope = new ScopeInternal("",glb);
|
else if (subId == ELEM_PROTOTYPE) {
|
||||||
// subscope->restrictScope(this);
|
|
||||||
// glb->symboltab->restore_nonglobal_xml(scopeel,subscope);
|
|
||||||
// }
|
|
||||||
else if ((*iter)->getName() == "override")
|
|
||||||
localoverride.restoreXml(*iter,glb);
|
|
||||||
else if ((*iter)->getName() == "prototype") {
|
|
||||||
if (localmap == (ScopeLocal *)0) {
|
if (localmap == (ScopeLocal *)0) {
|
||||||
// If we haven't seen a <localdb> tag yet, assume we have a default local scope
|
// If we haven't seen a <localdb> tag yet, assume we have a default local scope
|
||||||
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
||||||
@@ -766,11 +757,12 @@ uint8 Funcdata::restoreXml(const Element *el)
|
|||||||
localmap = newMap;
|
localmap = newMap;
|
||||||
}
|
}
|
||||||
funcp.setScope(localmap,baseaddr+ -1); // localmap built earlier
|
funcp.setScope(localmap,baseaddr+ -1); // localmap built earlier
|
||||||
funcp.restoreXml(*iter,glb);
|
funcp.decode(decoder,glb);
|
||||||
}
|
}
|
||||||
else if ((*iter)->getName() == "jumptablelist")
|
else if (subId == ELEM_JUMPTABLELIST)
|
||||||
restoreXmlJumpTable(*iter);
|
decodeJumpTable(decoder);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
if (localmap == (ScopeLocal *)0) { // Seen neither <localdb> or <prototype>
|
if (localmap == (ScopeLocal *)0) { // Seen neither <localdb> or <prototype>
|
||||||
// This is a function shell, so we provide default locals
|
// This is a function shell, so we provide default locals
|
||||||
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
ScopeLocal *newMap = new ScopeLocal(id,stackid,this,glb);
|
||||||
|
|||||||
@@ -28,6 +28,14 @@
|
|||||||
|
|
||||||
class FlowInfo;
|
class FlowInfo;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_NOCODE; ///< Marshaling attribute "nocode"
|
||||||
|
|
||||||
|
extern ElementId ELEM_AST; ///< Marshaling element \<ast>
|
||||||
|
extern ElementId ELEM_FUNCTION; ///< Marshaling element \<function>
|
||||||
|
extern ElementId ELEM_HIGHLIST; ///< Marshaling element \<highlist>
|
||||||
|
extern ElementId ELEM_JUMPTABLELIST; ///< Marshaling element \<jumptablelist>
|
||||||
|
extern ElementId ELEM_VARNODES; ///< Marshaling element \<varnodes>
|
||||||
|
|
||||||
/// \brief Container for data structures associated with a single function
|
/// \brief Container for data structures associated with a single function
|
||||||
///
|
///
|
||||||
/// This class holds the primary data structures for decompiling a function. In particular it holds
|
/// This class holds the primary data structures for decompiling a function. In particular it holds
|
||||||
@@ -120,7 +128,7 @@ class Funcdata {
|
|||||||
void nodeSplitRawDuplicate(BlockBasic *b,BlockBasic *bprime);
|
void nodeSplitRawDuplicate(BlockBasic *b,BlockBasic *bprime);
|
||||||
void nodeSplitInputPatch(BlockBasic *b,BlockBasic *bprime,int4 inedge);
|
void nodeSplitInputPatch(BlockBasic *b,BlockBasic *bprime,int4 inedge);
|
||||||
static bool descendantsOutside(Varnode *vn);
|
static bool descendantsOutside(Varnode *vn);
|
||||||
static void saveVarnodeXml(ostream &s,VarnodeLocSet::const_iterator iter,VarnodeLocSet::const_iterator enditer);
|
static void encodeVarnode(Encoder &encoder,VarnodeLocSet::const_iterator iter,VarnodeLocSet::const_iterator enditer);
|
||||||
static bool checkIndirectUse(Varnode *vn);
|
static bool checkIndirectUse(Varnode *vn);
|
||||||
static PcodeOp *findPrimaryBranch(PcodeOpTree::const_iterator iter,PcodeOpTree::const_iterator enditer,
|
static PcodeOp *findPrimaryBranch(PcodeOpTree::const_iterator iter,PcodeOpTree::const_iterator enditer,
|
||||||
bool findbranch,bool findcall,bool findreturn);
|
bool findbranch,bool findcall,bool findreturn);
|
||||||
@@ -177,12 +185,12 @@ public:
|
|||||||
void printVarnodeTree(ostream &s) const; ///< Print a description of all Varnodes to a stream
|
void printVarnodeTree(ostream &s) const; ///< Print a description of all Varnodes to a stream
|
||||||
void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream
|
void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream
|
||||||
void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes
|
void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes
|
||||||
void saveXml(ostream &s,uint8 id,bool savetree) const; ///< Emit an XML description of \b this function to stream
|
void encode(Encoder &encoder,uint8 id,bool savetree) const; ///< Encode a description of \b this function to stream
|
||||||
uint8 restoreXml(const Element *el); ///< Restore the state of \b this function from an XML description
|
uint8 decode(Decoder &decoder); ///< Restore the state of \b this function from an XML description
|
||||||
void saveXmlJumpTable(ostream &s) const; ///< Emit an XML description of jump-tables to stream
|
void encodeJumpTable(Encoder &encoder) const; ///< Encode a description of jump-tables to stream
|
||||||
void restoreXmlJumpTable(const Element *el); ///< Restore jump-tables from an XML description
|
void decodeJumpTable(Decoder &decoder); ///< Decode jump-tables from a stream
|
||||||
void saveXmlTree(ostream &s) const; ///< Save an XML description of the p-code tree to stream
|
void encodeTree(Encoder &encoder) const; ///< Encode a description of the p-code tree to stream
|
||||||
void saveXmlHigh(ostream &s) const; ///< Save an XML description of all HighVariables to stream
|
void encodeHigh(Encoder &encoder) const; ///< Encode a description of all HighVariables to stream
|
||||||
|
|
||||||
Override &getOverride(void) { return localoverride; } ///< Get the Override object for \b this function
|
Override &getOverride(void) { return localoverride; } ///< Get the Override object for \b this function
|
||||||
|
|
||||||
|
|||||||
@@ -139,22 +139,23 @@ void ArchitectureGhidra::readStringStream(istream &s,string &res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The method expects to see protocol markers indicating a string from the client,
|
/// The method expects to see protocol markers indicating a string from the client,
|
||||||
/// otherwise it throws and exception. The string is read in and then parsed as XML.
|
/// otherwise it throws and exception. The string is read into the given stream decoder.
|
||||||
/// \param s is the input stream from the client.
|
/// \param s is the input stream from the client.
|
||||||
/// \return the XML document
|
/// \param decoder is the given stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::readXMLStream(istream &s)
|
/// \return \b true if a response was received
|
||||||
|
bool ArchitectureGhidra::readStream(istream &s,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 type = readToAnyBurst(s);
|
int4 type = readToAnyBurst(s);
|
||||||
if (type==14) {
|
if (type==14) {
|
||||||
Document *doc = xml_tree(s);
|
decoder.ingestStream(s);
|
||||||
type = readToAnyBurst(s);
|
type = readToAnyBurst(s);
|
||||||
if (type!=15)
|
if (type!=15)
|
||||||
throw JavaError("alignment","Expecting XML string end");
|
throw JavaError("alignment","Expecting XML string end");
|
||||||
return doc;
|
return true;
|
||||||
}
|
}
|
||||||
if ((type&1)==1)
|
if ((type&1)==1)
|
||||||
return (Document *)0;
|
return false;
|
||||||
throw JavaError("alignment","Expecting string or end of query response");
|
throw JavaError("alignment","Expecting string or end of query response");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,17 +232,19 @@ void ArchitectureGhidra::readResponseEnd(istream &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read up to the beginning of a query response, check for an
|
/// Read up to the beginning of a query response, check for an
|
||||||
/// exception record, otherwise read in a string as an XML document.
|
/// exception record, otherwise pass back an element for decoding.
|
||||||
/// \param s is the input stream from the client
|
/// \param s is the input stream from the client
|
||||||
/// \return the XML document
|
/// \param decoder is the stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::readXMLAll(istream &s)
|
/// \return \b true if we received a valid response
|
||||||
|
bool ArchitectureGhidra::readAll(istream &s,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
readToResponse(s);
|
readToResponse(s);
|
||||||
Document *doc = readXMLStream(s);
|
if (readStream(s,decoder)) {
|
||||||
if (doc != (Document *)0)
|
|
||||||
readResponseEnd(s);
|
readResponseEnd(s);
|
||||||
return doc;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read up to the beginning of a query response, check for an
|
/// Read up to the beginning of a query response, check for an
|
||||||
@@ -339,8 +342,10 @@ 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) {
|
||||||
types->restoreXmlCoreTypes(el);
|
XmlDecode decoder(el);
|
||||||
|
types->decodeCoreTypes(decoder);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// Put in the core types
|
// Put in the core types
|
||||||
types->setCoreType("void",1,TYPE_VOID,false);
|
types->setCoreType("void",1,TYPE_VOID,false);
|
||||||
@@ -398,11 +403,12 @@ void ArchitectureGhidra::resolveArchitecture(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ask the Ghidra client if it knows about a specific processor register.
|
/// Ask the Ghidra client if it knows about a specific processor register.
|
||||||
/// The client responds with a \<addr> XML element describing the storage
|
/// The client responds with a \<addr> element describing the storage
|
||||||
/// location of the register.
|
/// location of the register.
|
||||||
/// \param regname is the name to query for
|
/// \param regname is the name to query for
|
||||||
/// \return the storage address as XML or NULL if the register is unknown
|
/// \param decoder is the stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getRegister(const string ®name)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getRegister(const string ®name,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
@@ -411,7 +417,7 @@ Document *ArchitectureGhidra::getRegister(const string ®name)
|
|||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a storage location and size, ask the Ghidra client if it knows of
|
/// Given a storage location and size, ask the Ghidra client if it knows of
|
||||||
@@ -426,7 +432,8 @@ string ArchitectureGhidra::getRegisterName(const VarnodeData &vndata)
|
|||||||
writeStringStream(sout,"getRegisterName");
|
writeStringStream(sout,"getRegisterName");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
Address addr(vndata.space,vndata.offset);
|
Address addr(vndata.space,vndata.offset);
|
||||||
addr.saveXml(sout,vndata.size);
|
encoder.clear();
|
||||||
|
addr.encode(encoder,vndata.size);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
@@ -438,24 +445,26 @@ string ArchitectureGhidra::getRegisterName(const VarnodeData &vndata)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client will return a description of registers that have
|
/// The Ghidra client will pass back a description of registers that have
|
||||||
/// known values at the given address. The response is generally a
|
/// known values at the given address. The response is generally a
|
||||||
/// \<tracked_pointset> which contains \<set> children which contains
|
/// \<tracked_pointset> which contains \<set> children which contains
|
||||||
/// a storage location and value.
|
/// a storage location and value.
|
||||||
/// \param addr is the given address
|
/// \param addr is the given address
|
||||||
/// \return the response Document
|
/// \param decoder is the stream decoder which will hold the result
|
||||||
Document *ArchitectureGhidra::getTrackedRegisters(const Address &addr)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getTrackedRegisters(const Address &addr,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getTrackedRegisters");
|
writeStringStream(sout,"getTrackedRegisters");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
addr.saveXml(sout);
|
encoder.clear();
|
||||||
|
addr.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The first operand to a CALLOTHER op indicates the specific user-defined op.
|
/// The first operand to a CALLOTHER op indicates the specific user-defined op.
|
||||||
@@ -491,7 +500,8 @@ uint1 *ArchitectureGhidra::getPcodePacked(const Address &addr)
|
|||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getPacked");
|
writeStringStream(sout,"getPacked");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
addr.saveXml(sout);
|
encoder.clear();
|
||||||
|
addr.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
@@ -499,54 +509,59 @@ uint1 *ArchitectureGhidra::getPcodePacked(const Address &addr)
|
|||||||
return readPackedAll(sin);
|
return readPackedAll(sin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client will return a \<symbol> tag, \<function> tag, or some
|
/// The Ghidra client will pass back a \<symbol> element, \<function> element, or some
|
||||||
/// other related Symbol information. If there no symbol at the address
|
/// other related Symbol information, in the given stream decoder. If there is no symbol at the address
|
||||||
/// the client should return a \<hole> tag describing the size of the
|
/// the client will return a \<hole> element describing the size of the
|
||||||
/// memory region that is free of symbols.
|
/// memory region that is free of symbols.
|
||||||
/// \param addr is the given address
|
/// \param addr is the given address
|
||||||
/// \return the symbol document
|
/// \param decoder is the given stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getMappedSymbolsXML(const Address &addr)
|
/// \return \b true if the query completes successfully
|
||||||
|
bool ArchitectureGhidra::getMappedSymbolsXML(const Address &addr,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getMappedSymbolsXML");
|
writeStringStream(sout,"getMappedSymbolsXML");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string
|
||||||
addr.saveXml(sout);
|
encoder.clear();
|
||||||
|
addr.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This asks the Ghidra client to resolve an \e external \e reference.
|
/// This asks the Ghidra client to resolve an \e external \e reference.
|
||||||
/// This is an address for which the client holds a reference to a function
|
/// This is an address for which the client holds a reference to a function
|
||||||
/// that is elsewhere in memory or not in memory at all. The client
|
/// that is elsewhere in memory or not in memory at all. The client
|
||||||
/// should unravel the reference from the given address and return either
|
/// should unravel the reference from the given address and pass back either
|
||||||
/// a \<function> tag describing the referred to function symbol or
|
/// a \<function> element describing the referred to function symbol or
|
||||||
/// a \<hole> tag if the reference can't be resolved
|
/// a \<hole> element if the reference can't be resolved.
|
||||||
/// \param addr is the given address
|
/// \param addr is the given address
|
||||||
/// \return a description of the referred to function
|
/// \param decoder is the stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getExternalRefXML(const Address &addr)
|
/// \return \b true if the query completes successfully
|
||||||
|
bool ArchitectureGhidra::getExternalRefXML(const Address &addr,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getExternalRefXML");
|
writeStringStream(sout,"getExternalRefXML");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
addr.saveXml(sout);
|
encoder.clear();
|
||||||
|
addr.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ask the Ghidra client to list all namespace elements between the global root
|
/// Ask the Ghidra client to list all namespace elements between the global root
|
||||||
/// and the namespace of the given id. The client should return a \<parent> tag with
|
/// and the namespace of the given id. The client will pass back a \<parent> element with
|
||||||
/// a \<val> child for each namespace in the path.
|
/// a \<val> child for each namespace in the path, in the given stream decoder
|
||||||
/// \param id is the given id of the namespace to resolve
|
/// \param id is the given id of the namespace to resolve
|
||||||
/// \return the XML document
|
/// \param decoder is the given stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getNamespacePath(uint8 id)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getNamespacePath(uint8 id,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
@@ -557,7 +572,7 @@ Document *ArchitectureGhidra::getNamespacePath(uint8 id)
|
|||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArchitectureGhidra::isNameUsed(const string &nm,uint8 startId,uint8 stopId)
|
bool ArchitectureGhidra::isNameUsed(const string &nm,uint8 startId,uint8 stopId)
|
||||||
@@ -593,7 +608,8 @@ string ArchitectureGhidra::getCodeLabel(const Address &addr)
|
|||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getSymbol");
|
writeStringStream(sout,"getSymbol");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
addr.saveXml(sout);
|
encoder.clear();
|
||||||
|
addr.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
@@ -605,12 +621,13 @@ string ArchitectureGhidra::getCodeLabel(const Address &addr)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client should respond with a \<type> tag giving details
|
/// The Ghidra client will pass back a \<type> element giving details
|
||||||
/// about the data-type.
|
/// about the data-type.
|
||||||
/// \param name is the name of the data-type
|
/// \param name is the name of the data-type
|
||||||
/// \param id is a unique id associated with the data-type, pass 0 if unknown
|
/// \param id is a unique id associated with the data-type, pass 0 if unknown
|
||||||
/// \return the data-type XML element or NULL
|
/// \param decoder is the stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getType(const string &name,uint8 id)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getType(const string &name,uint8 id,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
@@ -622,23 +639,25 @@ Document *ArchitectureGhidra::getType(const string &name,uint8 id)
|
|||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ask Ghidra client for all comments associated with one function.
|
/// Ask Ghidra client for all comments associated with one function.
|
||||||
/// The caller must provide the sub-set of properties (Comment::comment_type) for
|
/// The caller must provide the sub-set of properties (Comment::comment_type) for
|
||||||
/// the query to match. The client will return a \<commentdb> tag with
|
/// the query to match. A \<commentdb> element with \<comment> element child for each comment found
|
||||||
/// a \<comment> tag child for each comment found.
|
/// will be passed back in the given stream decoder.
|
||||||
/// \param fad is the address of the function to query
|
/// \param fad is the address of the function to query
|
||||||
/// \param flags specifies the properties the query will match (must be non-zero)
|
/// \param flags specifies the properties the query will match (must be non-zero)
|
||||||
/// \return an XML document describing each comment
|
/// \param decoder is the given stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getComments(const Address &fad,uint4 flags)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getComments(const Address &fad,uint4 flags,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getComments");
|
writeStringStream(sout,"getComments");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
fad.saveXml(sout);
|
encoder.clear();
|
||||||
|
fad.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
sout << dec << flags;
|
sout << dec << flags;
|
||||||
@@ -646,7 +665,7 @@ Document *ArchitectureGhidra::getComments(const Address &fad,uint4 flags)
|
|||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client is queried for a range of bytes, which are returned
|
/// The Ghidra client is queried for a range of bytes, which are returned
|
||||||
@@ -661,7 +680,8 @@ void ArchitectureGhidra::getBytes(uint1 *buf,int4 size,const Address &inaddr)
|
|||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getBytes");
|
writeStringStream(sout,"getBytes");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
inaddr.saveXml(sout,size);
|
encoder.clear();
|
||||||
|
inaddr.encode(encoder,size);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
@@ -708,7 +728,8 @@ void ArchitectureGhidra::getStringData(vector<uint1> &buffer,const Address &addr
|
|||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
writeStringStream(sout,"getString");
|
writeStringStream(sout,"getString");
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
addr.saveXml(sout,maxBytes);
|
encoder.clear();
|
||||||
|
addr.encode(encoder,maxBytes);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
writeStringStream(sout,ct->getName());
|
writeStringStream(sout,ct->getName());
|
||||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||||
@@ -753,14 +774,14 @@ void ArchitectureGhidra::getStringData(vector<uint1> &buffer,const Address &addr
|
|||||||
/// - CALLMECHANISM_TYPE
|
/// - CALLMECHANISM_TYPE
|
||||||
/// - EXECUTABLEPCODE_TYPE
|
/// - EXECUTABLEPCODE_TYPE
|
||||||
///
|
///
|
||||||
/// This and additional context is provided to the Ghidra client which returns
|
/// This and additional context is provided to the Ghidra client which passes back
|
||||||
/// an XML document describing the p-code. The document will be an \<inst> tag
|
/// an \<inst> element containing individual \<op> tags corresponding to individual p-code ops.
|
||||||
/// containing individual \<op> tags corresponding to individual p-code ops.
|
|
||||||
/// \param name is the name of the injection
|
/// \param name is the name of the injection
|
||||||
/// \param type is the type of injection
|
/// \param type is the type of injection
|
||||||
/// \param con is the context object
|
/// \param con is the context object
|
||||||
/// \return an XML document describing the p-code ops to inject
|
/// \param decoder is the stream decoder which will hold the result
|
||||||
Document *ArchitectureGhidra::getPcodeInject(const string &name,int4 type,const InjectContext &con)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getPcodeInject(const string &name,int4 type,const InjectContext &con,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
@@ -774,21 +795,22 @@ Document *ArchitectureGhidra::getPcodeInject(const string &name,int4 type,const
|
|||||||
writeStringStream(sout,"getXPcode");
|
writeStringStream(sout,"getXPcode");
|
||||||
writeStringStream(sout,name);
|
writeStringStream(sout,name);
|
||||||
sout.write("\000\000\001\016",4);
|
sout.write("\000\000\001\016",4);
|
||||||
con.saveXml(sout);
|
encoder.clear();
|
||||||
|
con.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client is provided a sequence of 1 or more integer values
|
/// The Ghidra client is provided a sequence of 1 or more integer values
|
||||||
/// extracted from a CPOOLREF op. It returns an XML document describing
|
/// extracted from a CPOOLREF op. A description of the constant pool record referenced by the integer(s)
|
||||||
/// the constant pool record referenced by the integer(s) or will throw
|
/// is passed back in the given stream decoder, or an exception is thrown if the record isn't properly referenced.
|
||||||
/// an exception if record isn't properly referenced.
|
|
||||||
/// \param refs is an array of 1 or more integer values referencing a constant pool record
|
/// \param refs is an array of 1 or more integer values referencing a constant pool record
|
||||||
/// \return a description of the record as a \<cpoolrec> XML document.
|
/// \param decoder is the given stream decoder that will hold the result
|
||||||
Document *ArchitectureGhidra::getCPoolRef(const vector<uintb> &refs)
|
/// \return \b true if the query completed successfully
|
||||||
|
bool ArchitectureGhidra::getCPoolRef(const vector<uintb> &refs,Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
sout.write("\000\000\001\004",4);
|
sout.write("\000\000\001\004",4);
|
||||||
@@ -802,7 +824,7 @@ Document *ArchitectureGhidra::getCPoolRef(const vector<uintb> &refs)
|
|||||||
sout.write("\000\000\001\005",4);
|
sout.write("\000\000\001\005",4);
|
||||||
sout.flush();
|
sout.flush();
|
||||||
|
|
||||||
return readXMLAll(sin);
|
return readAll(sin,decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Document *ArchitectureGhidra::getScopeProperties(Scope *newscope)
|
// Document *ArchitectureGhidra::getScopeProperties(Scope *newscope)
|
||||||
@@ -839,7 +861,7 @@ void ArchitectureGhidra::printMessage(const string &message) const
|
|||||||
/// \param o is the output stream to the Ghidra client
|
/// \param o is the output stream to the Ghidra client
|
||||||
ArchitectureGhidra::ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,
|
ArchitectureGhidra::ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,
|
||||||
const string &corespec,istream &i,ostream &o)
|
const string &corespec,istream &i,ostream &o)
|
||||||
: Architecture(), sin(i), sout(o)
|
: Architecture(), sin(i), sout(o), encoder(sout)
|
||||||
|
|
||||||
{
|
{
|
||||||
print->setXML(true);
|
print->setXML(true);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ struct JavaError : public LowlevelError {
|
|||||||
class ArchitectureGhidra : public Architecture {
|
class ArchitectureGhidra : public Architecture {
|
||||||
istream &sin; ///< Input stream for interfacing with Ghidra
|
istream &sin; ///< Input stream for interfacing with Ghidra
|
||||||
ostream &sout; ///< Output stream for interfacing with Ghidra
|
ostream &sout; ///< Output stream for interfacing with Ghidra
|
||||||
|
XmlEncode encoder; ///< Encoder used to write to Ghidra
|
||||||
mutable string warnings; ///< Warnings accumulated by the decompiler
|
mutable string warnings; ///< Warnings accumulated by the decompiler
|
||||||
string pspecxml; ///< XML pspec passed from Ghidra
|
string pspecxml; ///< XML pspec passed from Ghidra
|
||||||
string cspecxml; ///< XML cspec passed from Ghidra
|
string cspecxml; ///< XML cspec passed from Ghidra
|
||||||
@@ -86,21 +87,21 @@ public:
|
|||||||
istream &i,ostream &o);
|
istream &i,ostream &o);
|
||||||
const string &getWarnings(void) const { return warnings; } ///< Get warnings produced by the last decompilation
|
const string &getWarnings(void) const { return warnings; } ///< Get warnings produced by the last decompilation
|
||||||
void clearWarnings(void) { warnings.clear(); } ///< Clear warnings
|
void clearWarnings(void) { warnings.clear(); } ///< Clear warnings
|
||||||
Document *getRegister(const string ®name); ///< Retrieve a register description given a name
|
bool getRegister(const string ®name,Decoder &decoder); ///< Retrieve a register description given a name
|
||||||
string getRegisterName(const VarnodeData &vndata); ///< Retrieve a register name given its storage location
|
string getRegisterName(const VarnodeData &vndata); ///< Retrieve a register name given its storage location
|
||||||
Document *getTrackedRegisters(const Address &addr); ///< Retrieve \e tracked register values at the given address
|
bool getTrackedRegisters(const Address &addr,Decoder &decoder); ///< Retrieve \e tracked register values at the given address
|
||||||
string getUserOpName(int4 index); ///< Get the name of a user-defined p-code op
|
string getUserOpName(int4 index); ///< Get the name of a user-defined p-code op
|
||||||
uint1 *getPcodePacked(const Address &addr); ///< Get p-code for a single instruction
|
uint1 *getPcodePacked(const Address &addr); ///< Get p-code for a single instruction
|
||||||
Document *getMappedSymbolsXML(const Address &addr); ///< Get symbols associated with the given address
|
bool getMappedSymbolsXML(const Address &addr,Decoder &decoder); ///< Get symbols associated with the given address
|
||||||
Document *getExternalRefXML(const Address &addr); ///< Retrieve a description of an external function
|
bool getExternalRefXML(const Address &addr,Decoder &decoder); ///< Retrieve a description of an external function
|
||||||
Document *getNamespacePath(uint8 id); ///< Get a description of a namespace path
|
bool getNamespacePath(uint8 id,Decoder &decoder); ///< Get a description of a namespace path
|
||||||
bool isNameUsed(const string &nm,uint8 startId,uint8 stopId); ///< Is given name used along namespace path
|
bool isNameUsed(const string &nm,uint8 startId,uint8 stopId); ///< Is given name used along namespace path
|
||||||
string getCodeLabel(const Address &addr); ///< Retrieve a label at the given address
|
string getCodeLabel(const Address &addr); ///< Retrieve a label at the given address
|
||||||
Document *getType(const string &name,uint8 id); ///< Retrieve a data-type description for the given name and id
|
bool getType(const string &name,uint8 id,Decoder &decoder); ///< Retrieve a data-type description for the given name and id
|
||||||
Document *getComments(const Address &fad,uint4 flags); ///< Retrieve comments for a particular function
|
bool getComments(const Address &fad,uint4 flags,Decoder &decoder); ///< Retrieve comments for a particular function
|
||||||
void getBytes(uint1 *buf,int4 size,const Address &inaddr); ///< Retrieve bytes in the LoadImage at the given address
|
void getBytes(uint1 *buf,int4 size,const Address &inaddr); ///< Retrieve bytes in the LoadImage at the given address
|
||||||
Document *getPcodeInject(const string &name,int4 type,const InjectContext &con);
|
bool getPcodeInject(const string &name,int4 type,const InjectContext &con,Decoder &decoder);
|
||||||
Document *getCPoolRef(const vector<uintb> &refs); ///< Resolve a constant pool reference
|
bool getCPoolRef(const vector<uintb> &refs,Decoder &decoder); ///< Resolve a constant pool reference
|
||||||
// Document *getScopeProperties(Scope *newscope);
|
// Document *getScopeProperties(Scope *newscope);
|
||||||
|
|
||||||
/// \brief Toggle whether the data-flow and control-flow is emitted as part of the main decompile action
|
/// \brief Toggle whether the data-flow and control-flow is emitted as part of the main decompile action
|
||||||
@@ -138,8 +139,8 @@ public:
|
|||||||
static void writeStringStream(ostream &s,const string &msg); ///< Send a string to the client
|
static void writeStringStream(ostream &s,const string &msg); ///< Send a string to the client
|
||||||
static void readToResponse(istream &s); ///< Read the query response protocol marker
|
static void readToResponse(istream &s); ///< Read the query response protocol marker
|
||||||
static void readResponseEnd(istream &s); ///< Read the ending query response protocol marker
|
static void readResponseEnd(istream &s); ///< Read the ending query response protocol marker
|
||||||
static Document *readXMLAll(istream &s); ///< Read a whole response as an XML document
|
static bool readAll(istream &s,Decoder &decoder); ///< Read a whole response as an XML document
|
||||||
static Document *readXMLStream(istream &s); ///< Receive an XML document from the client
|
static bool readStream(istream &s,Decoder &decoder); ///< Receive an XML document from the client
|
||||||
static uint1 *readPackedStream(istream &s); ///< Read packed p-code op information
|
static uint1 *readPackedStream(istream &s); ///< Read packed p-code op information
|
||||||
static uint1 *readPackedAll(istream &s); ///< Read a whole response as packed p-code op information
|
static uint1 *readPackedAll(istream &s); ///< Read a whole response as packed p-code op information
|
||||||
static void passJavaException(ostream &s,const string &tp,const string &msg);
|
static void passJavaException(ostream &s,const string &tp,const string &msg);
|
||||||
|
|||||||
@@ -19,11 +19,24 @@ const TrackedSet &ContextGhidra::getTrackedSet(const Address &addr) const
|
|||||||
|
|
||||||
{
|
{
|
||||||
cache.clear();
|
cache.clear();
|
||||||
|
XmlDecode decoder;
|
||||||
|
((ArchitectureGhidra *)glb)->getTrackedRegisters(addr,decoder);
|
||||||
|
|
||||||
Document *doc = ((ArchitectureGhidra *)glb)->getTrackedRegisters(addr);
|
uint4 elemId = decoder.openElement(ELEM_TRACKED_POINTSET);
|
||||||
Element *root = doc->getRoot();
|
decodeTracked(decoder,glb,cache);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
restoreTracked(root,glb,cache);
|
|
||||||
delete doc;
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContextGhidra::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
|
{
|
||||||
|
decoder.skipElement(); // Ignore details handled by ghidra
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextGhidra::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
|
{
|
||||||
|
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 restoreXml(const Element *el,const AddrSpaceManager *manage) {}
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
virtual void restoreFromSpec(const Element *el,const AddrSpaceManager *manage) {}
|
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
|
|
||||||
// Unimplemented routines (should never be called)
|
// Unimplemented routines (should never be called)
|
||||||
virtual int getContextSize(void) const {
|
virtual int getContextSize(void) const {
|
||||||
@@ -63,8 +63,8 @@ public:
|
|||||||
throw LowlevelError("getContext should not be called for GHIDRA"); }
|
throw LowlevelError("getContext should not be called for GHIDRA"); }
|
||||||
virtual void registerVariable(const string &nm,int4 sbit,int4 ebit) {
|
virtual void registerVariable(const string &nm,int4 sbit,int4 ebit) {
|
||||||
throw LowlevelError("registerVariable should not be called for GHIDRA"); }
|
throw LowlevelError("registerVariable should not be called for GHIDRA"); }
|
||||||
virtual void saveXml(ostream &s) const {
|
virtual void encode(Encoder &encoder) const {
|
||||||
throw LowlevelError("context::saveXml should not be called for GHIDRA"); }
|
throw LowlevelError("context::encode should not be called for GHIDRA"); }
|
||||||
|
|
||||||
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2) {
|
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2) {
|
||||||
throw LowlevelError("createSet should not be called for GHIDRA"); }
|
throw LowlevelError("createSet should not be called for GHIDRA"); }
|
||||||
|
|||||||
@@ -274,12 +274,9 @@ void DecompileAt::loadParameters(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
Document *doc;
|
XmlDecode decoder;
|
||||||
doc = ArchitectureGhidra::readXMLStream(sin); // Read XML of address directly from in stream
|
ArchitectureGhidra::readStream(sin,decoder); // Read encoded address directly from in stream
|
||||||
addr = Address::restoreXml(doc->getRoot(),ghidra); // Parse XML for functions address
|
addr = Address::decode(decoder,ghidra); // Decode for functions address
|
||||||
addr.toPhysical(); // Only for backward compatibility
|
|
||||||
// with SLED
|
|
||||||
delete doc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompileAt::rawAction(void)
|
void DecompileAt::rawAction(void)
|
||||||
@@ -305,25 +302,18 @@ void DecompileAt::rawAction(void)
|
|||||||
sout.write("\000\000\001\016",4);
|
sout.write("\000\000\001\016",4);
|
||||||
// Write output XML directly to outstream
|
// Write output XML directly to outstream
|
||||||
if (fd->isProcComplete()) {
|
if (fd->isProcComplete()) {
|
||||||
//bool v1 = ghidra->getSendParamMeasures();
|
|
||||||
//sout << "value: " << ghidra->getSendParamMeasures() << "\n";
|
|
||||||
//bool v2 = (ghidra->allacts.getCurrentName() == "paramid");
|
|
||||||
//sout << "value: " << (ghidra->allacts.getCurrentName() == "paramid") << "\n";
|
|
||||||
//bool v3 = v1 && v2;
|
|
||||||
|
|
||||||
sout << "<doc>\n";
|
sout << "<doc>\n";
|
||||||
//sout << (v1?"1":"0") << "(" << (int4)v1 << ")\n" << (v2?"1":"0") << "\n" << (v3?"1":"0") << "\n";
|
XmlEncode encoder(sout);
|
||||||
|
|
||||||
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
||||||
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
||||||
pidanalysis.saveXml( sout, true );
|
pidanalysis.encode( encoder, true );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ghidra->getSendParamMeasures()) {
|
if (ghidra->getSendParamMeasures()) {
|
||||||
ParamIDAnalysis pidanalysis( fd, false );
|
ParamIDAnalysis pidanalysis( fd, false );
|
||||||
pidanalysis.saveXml( sout, true );
|
pidanalysis.encode( encoder, true );
|
||||||
}
|
}
|
||||||
fd->saveXml(sout,0,ghidra->getSendSyntaxTree());
|
fd->encode(encoder,0,ghidra->getSendSyntaxTree());
|
||||||
if (ghidra->getSendCCode()&&
|
if (ghidra->getSendCCode()&&
|
||||||
(ghidra->allacts.getCurrentName() == "decompile"))
|
(ghidra->allacts.getCurrentName() == "decompile"))
|
||||||
ghidra->print->docFunction(fd);
|
ghidra->print->docFunction(fd);
|
||||||
@@ -337,10 +327,10 @@ void StructureGraph::loadParameters(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
Document *doc;
|
|
||||||
doc = ArchitectureGhidra::readXMLStream(sin);
|
XmlDecode decoder;
|
||||||
ingraph.restoreXml(doc->getRoot(),ghidra);
|
ArchitectureGhidra::readStream(sin,decoder);
|
||||||
delete doc;
|
ingraph.decode(decoder,ghidra);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StructureGraph::rawAction(void)
|
void StructureGraph::rawAction(void)
|
||||||
@@ -358,7 +348,8 @@ void StructureGraph::rawAction(void)
|
|||||||
resultgraph.orderBlocks();
|
resultgraph.orderBlocks();
|
||||||
|
|
||||||
sout.write("\000\000\001\016",4);
|
sout.write("\000\000\001\016",4);
|
||||||
resultgraph.saveXml(sout);
|
XmlEncode encoder(sout);
|
||||||
|
resultgraph.encode(encoder);
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
ingraph.clear();
|
ingraph.clear();
|
||||||
}
|
}
|
||||||
@@ -413,28 +404,12 @@ void SetAction::sendResult(void)
|
|||||||
GhidraCommand::sendResult();
|
GhidraCommand::sendResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetOptions::SetOptions(void) : GhidraCommand()
|
|
||||||
|
|
||||||
{
|
|
||||||
doc = (Document *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetOptions::~SetOptions(void)
|
|
||||||
|
|
||||||
{
|
|
||||||
if (doc != (Document *)0)
|
|
||||||
delete doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetOptions::loadParameters(void)
|
void SetOptions::loadParameters(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
GhidraCommand::loadParameters();
|
GhidraCommand::loadParameters();
|
||||||
if (doc != (Document *)0) {
|
decoder.clear();
|
||||||
delete doc;
|
ArchitectureGhidra::readStream(sin,decoder);
|
||||||
doc = (Document *)0;
|
|
||||||
}
|
|
||||||
doc = ArchitectureGhidra::readXMLStream(sin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOptions::rawAction(void)
|
void SetOptions::rawAction(void)
|
||||||
@@ -443,9 +418,8 @@ void SetOptions::rawAction(void)
|
|||||||
res = false;
|
res = false;
|
||||||
|
|
||||||
ghidra->resetDefaults();
|
ghidra->resetDefaults();
|
||||||
ghidra->options->restoreXml(doc->getRoot());
|
ghidra->options->decode(decoder);
|
||||||
delete doc;
|
decoder.clear();
|
||||||
doc = (Document *)0;
|
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,6 +488,8 @@ int main(int argc,char **argv)
|
|||||||
|
|
||||||
{
|
{
|
||||||
signal(SIGSEGV, &ArchitectureGhidra::segvHandler); // Exit on SEGV errors
|
signal(SIGSEGV, &ArchitectureGhidra::segvHandler); // Exit on SEGV errors
|
||||||
|
AttributeId::initialize();
|
||||||
|
ElementId::initialize();
|
||||||
CapabilityPoint::initializeAll();
|
CapabilityPoint::initializeAll();
|
||||||
int4 status = 0;
|
int4 status = 0;
|
||||||
while(status == 0) {
|
while(status == 0) {
|
||||||
|
|||||||
@@ -220,12 +220,10 @@ 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 {
|
||||||
Document *doc; ///< The XML option document
|
XmlDecode decoder; ///< The XML option document
|
||||||
virtual void loadParameters(void);
|
virtual void loadParameters(void);
|
||||||
virtual void sendResult(void);
|
virtual void sendResult(void);
|
||||||
public:
|
public:
|
||||||
SetOptions(void);
|
|
||||||
virtual ~SetOptions(void);
|
|
||||||
bool res; ///< Set to \b true if the option change succeeded
|
bool res; ///< Set to \b true if the option change succeeded
|
||||||
virtual void rawAction(void);
|
virtual void rawAction(void);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ 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");
|
||||||
restoreXml(el);
|
XmlDecode decoder(el);
|
||||||
|
decode(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
||||||
@@ -45,9 +46,10 @@ 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;
|
||||||
Document *doc;
|
XmlDecode decoder;
|
||||||
try {
|
try {
|
||||||
doc = glb->getRegister(nm); // Ask Ghidra client about the register
|
if (!glb->getRegister(nm,decoder)) // Ask Ghidra client about the register
|
||||||
|
throw LowlevelError("No register named "+nm);
|
||||||
}
|
}
|
||||||
catch(XmlError &err) {
|
catch(XmlError &err) {
|
||||||
ostringstream errmsg;
|
ostringstream errmsg;
|
||||||
@@ -55,16 +57,13 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
|||||||
errmsg << " -- " << err.explain;
|
errmsg << " -- " << err.explain;
|
||||||
throw LowlevelError(errmsg.str());
|
throw LowlevelError(errmsg.str());
|
||||||
}
|
}
|
||||||
if (doc == (Document *)0)
|
|
||||||
throw LowlevelError("No register named "+nm);
|
|
||||||
Address regaddr;
|
Address regaddr;
|
||||||
int4 regsize;
|
int4 regsize;
|
||||||
regaddr = Address::restoreXml( doc->getRoot(), this, regsize);
|
regaddr = Address::decode( decoder, this, regsize);
|
||||||
VarnodeData vndata;
|
VarnodeData vndata;
|
||||||
vndata.space = regaddr.getSpace();
|
vndata.space = regaddr.getSpace();
|
||||||
vndata.offset = regaddr.getOffset();
|
vndata.offset = regaddr.getOffset();
|
||||||
vndata.size = regsize;
|
vndata.size = regsize;
|
||||||
delete doc;
|
|
||||||
return cacheRegister(nm,vndata);
|
return cacheRegister(nm,vndata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,33 +141,23 @@ int4 GhidraTranslate::oneInstruction(PcodeEmit &emit,const Address &baseaddr) co
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Ghidra client passes descriptions of address spaces and other
|
/// Parse the \<sleigh> element passed back by the Ghidra client, describing address spaces
|
||||||
/// information that needs to be cached by the decompiler
|
/// and other information that needs to be cached by the decompiler.
|
||||||
/// \param el is the element of the initialization tag
|
/// \param decoder is the stream decoder
|
||||||
void GhidraTranslate::restoreXml(const Element *el)
|
void GhidraTranslate::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
|
uint4 elemId = decoder.openElement(ELEM_SLEIGH);
|
||||||
{
|
setBigEndian(decoder.readBool(ATTRIB_BIGENDIAN));
|
||||||
istringstream s(el->getAttributeValue("uniqbase"));
|
setUniqueBase(decoder.readUnsignedInteger(ATTRIB_UNIQBASE));
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
decodeSpaces(decoder,this);
|
||||||
uintm ubase;
|
for(;;) {
|
||||||
s >> ubase;
|
uint4 subId = decoder.peekElement();
|
||||||
setUniqueBase(ubase);
|
if (subId != ELEM_TRUNCATE_SPACE) break;
|
||||||
}
|
TruncationTag tag;
|
||||||
const List &list(el->getChildren());
|
tag.decode(decoder);
|
||||||
List::const_iterator iter;
|
truncateSpace(tag);
|
||||||
iter = list.begin();
|
|
||||||
restoreXmlSpaces(*iter,this);
|
|
||||||
++iter;
|
|
||||||
while(iter != list.end()) {
|
|
||||||
const Element *subel = *iter;
|
|
||||||
if (subel->getName() == "truncate_space") {
|
|
||||||
TruncationTag tag;
|
|
||||||
tag.restoreXml(subel);
|
|
||||||
truncateSpace(tag);
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class GhidraTranslate : public Translate {
|
|||||||
mutable map<string,VarnodeData> nm2addr; ///< Mapping from register name to Varnode
|
mutable map<string,VarnodeData> nm2addr; ///< Mapping from register name to Varnode
|
||||||
mutable map<VarnodeData,string> addr2nm; ///< Mapping rom Varnode to register name
|
mutable map<VarnodeData,string> addr2nm; ///< Mapping rom Varnode to register name
|
||||||
const VarnodeData &cacheRegister(const string &nm,const VarnodeData &data) const;
|
const VarnodeData &cacheRegister(const string &nm,const VarnodeData &data) const;
|
||||||
void restoreXml(const Element *el); ///< Initialize \b this Translate from XML
|
void decode(Decoder &decoder); ///< Initialize \b this Translate from a stream
|
||||||
public:
|
public:
|
||||||
GhidraTranslate(ArchitectureGhidra *g) { glb = g; } ///< Constructor
|
GhidraTranslate(ArchitectureGhidra *g) { glb = g; } ///< Constructor
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
#include "globalcontext.hh"
|
#include "globalcontext.hh"
|
||||||
|
|
||||||
|
ElementId ELEM_CONTEXT_DATA = ElementId("context_data",94);
|
||||||
|
ElementId ELEM_CONTEXT_POINTS = ElementId("context_points",95);
|
||||||
|
ElementId ELEM_CONTEXT_POINTSET = ElementId("context_pointset",96);
|
||||||
|
ElementId ELEM_CONTEXT_SET = ElementId("context_set",97);
|
||||||
|
ElementId ELEM_SET = ElementId("set",98);
|
||||||
|
ElementId ELEM_TRACKED_POINTSET = ElementId("tracked_pointset",99);
|
||||||
|
ElementId ELEM_TRACKED_SET = ElementId("tracked_set",100);
|
||||||
|
|
||||||
/// Bits within the whole context blob are labeled starting with 0 as the most significant bit
|
/// Bits within the whole context blob are labeled starting with 0 as the most significant bit
|
||||||
/// in the first word in the sequence. The new context value must be contained within a single
|
/// in the first word in the sequence. The new context value must be contained within a single
|
||||||
/// word.
|
/// word.
|
||||||
@@ -30,76 +38,64 @@ ContextBitRange::ContextBitRange(int4 sbit,int4 ebit)
|
|||||||
mask = (~((uintm)0))>>(startbit+shift);
|
mask = (~((uintm)0))>>(startbit+shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The register storage and value are serialized as a \<set> tag.
|
/// The register storage and value are encoded as a \<set> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void TrackedContext::saveXml(ostream &s) const
|
void TrackedContext::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<set";
|
encoder.openElement(ELEM_SET);
|
||||||
loc.space->saveXmlAttributes(s,loc.offset,loc.size);
|
loc.space->encodeAttributes(encoder,loc.offset,loc.size);
|
||||||
a_v_u(s,"val",val);
|
encoder.writeUnsignedInteger(ATTRIB_VAL, val);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a \<set> tag to fill in the storage and value details
|
/// Parse a \<set> element to fill in the storage and value details.
|
||||||
/// \param el is the root \<set> tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param manage is the manager used to decode address references
|
/// \param manage is the manager used to decode address references
|
||||||
void TrackedContext::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void TrackedContext::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
int4 size;
|
uint4 elemId = decoder.openElement(ELEM_SET);
|
||||||
Address addr = Address::restoreXml(el,manage,size);
|
loc.decodeFromAttributes(decoder, manage);
|
||||||
|
|
||||||
istringstream s(el->getAttributeValue("val"));
|
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> val;
|
|
||||||
|
|
||||||
loc.space = addr.getSpace();
|
val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||||
loc.offset = addr.getOffset();
|
decoder.closeElement(elemId);
|
||||||
loc.size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Save all tracked register values for a specific address to an XML stream
|
/// \brief Encode all tracked register values for a specific address to a stream
|
||||||
///
|
///
|
||||||
/// Encode all the tracked register values associated with a specific target address
|
/// Encode all the tracked register values associated with a specific target address
|
||||||
/// as a \<tracked_pointset> tag.
|
/// as a \<tracked_pointset> tag.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
/// \param addr is the specific address we have tracked values for
|
/// \param addr is the specific address we have tracked values for
|
||||||
/// \param vec is the list of tracked values
|
/// \param vec is the list of tracked values
|
||||||
void ContextDatabase::saveTracked(ostream &s,const Address &addr,
|
void ContextDatabase::encodeTracked(Encoder &encoder,const Address &addr,const TrackedSet &vec)
|
||||||
const TrackedSet &vec)
|
|
||||||
{
|
{
|
||||||
if (vec.empty()) return;
|
if (vec.empty()) return;
|
||||||
s << "<tracked_pointset";
|
encoder.openElement(ELEM_TRACKED_POINTSET);
|
||||||
addr.getSpace()->saveXmlAttributes(s,addr.getOffset() );
|
addr.getSpace()->encodeAttributes(encoder,addr.getOffset() );
|
||||||
s << ">\n";
|
|
||||||
for(int4 i=0;i<vec.size();++i) {
|
for(int4 i=0;i<vec.size();++i) {
|
||||||
s << " ";
|
vec[i].encode(encoder);
|
||||||
vec[i].saveXml(s);
|
|
||||||
}
|
}
|
||||||
s << "</tracked_pointset>\n";
|
encoder.closeElement(ELEM_TRACKED_POINTSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Restore a sequence of tracked register values from an XML stream
|
/// \brief Restore a sequence of tracked register values from the given stream decoder
|
||||||
///
|
///
|
||||||
/// Given a root \<tracked_pointset> tag, decode each child in turn populating a list of
|
/// Parse a \<tracked_pointset> element, decoding each child in turn to populate a list of
|
||||||
/// TrackedContext objects.
|
/// TrackedContext objects.
|
||||||
/// \param el is the root tag
|
/// \param decoder is the given stream decoder
|
||||||
/// \param manage is used to resolve address space references
|
/// \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::restoreTracked(const Element *el,const AddrSpaceManager *manage,
|
void ContextDatabase::decodeTracked(Decoder &decoder,const AddrSpaceManager *manage,
|
||||||
TrackedSet &vec)
|
TrackedSet &vec)
|
||||||
|
|
||||||
{
|
{
|
||||||
vec.clear(); // Clear out any old stuff
|
vec.clear(); // Clear out any old stuff
|
||||||
const List &list(el->getChildren());
|
while(decoder.peekElement() != 0) {
|
||||||
List::const_iterator iter = list.begin();
|
|
||||||
|
|
||||||
while(iter != list.end()) {
|
|
||||||
const Element *subel = *iter;
|
|
||||||
vec.emplace_back();
|
vec.emplace_back();
|
||||||
vec.back().restoreXml(subel,manage);
|
vec.back().decode(decoder,manage);
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,54 +310,47 @@ ContextInternal::FreeArray &ContextInternal::FreeArray::operator=(const FreeArra
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Write out a single context block as an XML tag
|
/// \brief Encode a single context block to a stream
|
||||||
///
|
///
|
||||||
/// The blob is broken up into individual values and written out as a series
|
/// The blob is broken up into individual values and written out as a series
|
||||||
/// of \<set> tags within a parent \<context_pointset> tag.
|
/// of \<set> elements within a parent \<context_pointset> element.
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
/// \param addr is the address of the split point where the blob is valid
|
/// \param addr is the address of the split point where the blob is valid
|
||||||
/// \param vec is the array of words holding the blob values
|
/// \param vec is the array of words holding the blob values
|
||||||
void ContextInternal::saveContext(ostream &s,const Address &addr,
|
void ContextInternal::encodeContext(Encoder &encoder,const Address &addr,const uintm *vec) const
|
||||||
const uintm *vec) const
|
|
||||||
{
|
{
|
||||||
s << "<context_pointset";
|
encoder.openElement(ELEM_CONTEXT_POINTSET);
|
||||||
addr.getSpace()->saveXmlAttributes(s,addr.getOffset() );
|
addr.getSpace()->encodeAttributes(encoder,addr.getOffset() );
|
||||||
s << ">\n";
|
|
||||||
map<string,ContextBitRange>::const_iterator iter;
|
map<string,ContextBitRange>::const_iterator iter;
|
||||||
for(iter=variables.begin();iter!=variables.end();++iter) {
|
for(iter=variables.begin();iter!=variables.end();++iter) {
|
||||||
uintm val = (*iter).second.getValue(vec);
|
uintm val = (*iter).second.getValue(vec);
|
||||||
s << " <set";
|
encoder.openElement(ELEM_SET);
|
||||||
a_v(s,"name",(*iter).first);
|
encoder.writeString(ATTRIB_NAME, (*iter).first);
|
||||||
a_v_u(s,"val",val);
|
encoder.writeUnsignedInteger(ATTRIB_VAL, val);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_SET);
|
||||||
}
|
}
|
||||||
s << "</context_pointset>\n";
|
encoder.closeElement(ELEM_CONTEXT_POINTSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Restore a context blob for given address range from an XML tag
|
/// \brief Restore a context blob for given address range from a stream decoder
|
||||||
///
|
///
|
||||||
/// The tag can be either \<context_pointset> or \<context_set>. In either case,
|
/// Parse either a \<context_pointset> or \<context_set> element. In either case,
|
||||||
/// children are parsed to get context variable values. Then a context blob is
|
/// children are parsed to get context variable values. Then a context blob is
|
||||||
/// reconstructed from the values. The new blob is added to the interval map based
|
/// reconstructed from the values. The new blob is added to the interval map based
|
||||||
/// on the address range. If the start address is invalid, the default value of
|
/// on the address range. If the start address is invalid, the default value of
|
||||||
/// the context variables are painted. The second address can be invalid, if
|
/// the context variables are painted. The second address can be invalid, if
|
||||||
/// only a split point is known.
|
/// only a split point is known.
|
||||||
/// \param el is the root XML tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param addr1 is the starting address of the given range
|
/// \param addr1 is the starting address of the given range
|
||||||
/// \param addr2 is the ending address of the given range
|
/// \param addr2 is the ending address of the given range
|
||||||
void ContextInternal::restoreContext(const Element *el,const Address &addr1,const Address &addr2)
|
void ContextInternal::decodeContext(Decoder &decoder,const Address &addr1,const Address &addr2)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
for(;;) {
|
||||||
List::const_iterator iter = list.begin();
|
uint4 subId = decoder.openElement();
|
||||||
|
if (subId != ELEM_SET) break;
|
||||||
while(iter != list.end()) {
|
uintm val = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||||
const Element *subel = *iter;
|
ContextBitRange &var(getVariable(decoder.readString(ATTRIB_NAME)));
|
||||||
istringstream s(subel->getAttributeValue("val"));
|
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
uintm val;
|
|
||||||
s >> val;
|
|
||||||
ContextBitRange &var(getVariable(subel->getAttributeValue("name")));
|
|
||||||
vector<uintm *> vec;
|
vector<uintm *> vec;
|
||||||
if (addr1.isInvalid()) { // Invalid addr1, indicates we should set default value
|
if (addr1.isInvalid()) { // Invalid addr1, indicates we should set default value
|
||||||
uintm *defaultBuffer = getDefaultValue();
|
uintm *defaultBuffer = getDefaultValue();
|
||||||
@@ -373,7 +362,7 @@ void ContextInternal::restoreContext(const Element *el,const Address &addr1,cons
|
|||||||
getRegionForSet(vec,addr1,addr2,var.getWord(),var.getMask()<<var.getShift());
|
getRegionForSet(vec,addr1,addr2,var.getWord(),var.getMask()<<var.getShift());
|
||||||
for(int4 i=0;i<vec.size();++i)
|
for(int4 i=0;i<vec.size();++i)
|
||||||
var.setValue(vec[i],val);
|
var.setValue(vec[i],val);
|
||||||
++iter;
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,83 +476,81 @@ TrackedSet &ContextInternal::createSet(const Address &addr1,const Address &addr2
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextInternal::saveXml(ostream &s) const
|
void ContextInternal::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (database.empty() && trackbase.empty()) return;
|
if (database.empty() && trackbase.empty()) return;
|
||||||
|
|
||||||
s << "<context_points>\n";
|
encoder.openElement(ELEM_CONTEXT_POINTS);
|
||||||
|
|
||||||
partmap<Address,FreeArray>::const_iterator fiter,fenditer;
|
partmap<Address,FreeArray>::const_iterator fiter,fenditer;
|
||||||
fiter = database.begin();
|
fiter = database.begin();
|
||||||
fenditer = database.end();
|
fenditer = database.end();
|
||||||
for(;fiter!=fenditer;++fiter) // Save context at each changepoint
|
for(;fiter!=fenditer;++fiter) // Save context at each changepoint
|
||||||
saveContext(s,(*fiter).first,(*fiter).second.array);
|
encodeContext(encoder,(*fiter).first,(*fiter).second.array);
|
||||||
|
|
||||||
partmap<Address,TrackedSet>::const_iterator titer,tenditer;
|
partmap<Address,TrackedSet>::const_iterator titer,tenditer;
|
||||||
titer = trackbase.begin();
|
titer = trackbase.begin();
|
||||||
tenditer = trackbase.end();
|
tenditer = trackbase.end();
|
||||||
for(;titer!=tenditer;++titer)
|
for(;titer!=tenditer;++titer)
|
||||||
saveTracked(s,(*titer).first,(*titer).second);
|
encodeTracked(encoder,(*titer).first,(*titer).second);
|
||||||
|
|
||||||
s << "</context_points>\n";
|
encoder.closeElement(ELEM_CONTEXT_POINTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextInternal::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
void ContextInternal::decode(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CONTEXT_POINTS);
|
||||||
List::const_iterator iter = list.begin();
|
for(;;) {
|
||||||
|
uint4 subId = decoder.openElement();
|
||||||
while(iter != list.end()) {
|
if (subId == 0) break;
|
||||||
const Element *subel = *iter;
|
if (subId == ELEM_CONTEXT_POINTSET) {
|
||||||
if (subel->getName() == "context_pointset") {
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (subel->getNumAttributes()==0) {
|
decoder.rewindAttributes();
|
||||||
restoreContext(subel,Address(),Address()); // Restore the default value
|
if (attribId==0) {
|
||||||
|
decodeContext(decoder,Address(),Address()); // Restore the default value
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Address addr = Address::restoreXml(subel,manage);
|
VarnodeData vData;
|
||||||
restoreContext(subel,addr,Address());
|
vData.decodeFromAttributes(decoder, manage);
|
||||||
|
decodeContext(decoder,vData.getAddr(),Address());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "tracked_pointset") {
|
else if (subId == ELEM_TRACKED_POINTSET) {
|
||||||
Address addr = Address::restoreXml(subel,manage);
|
VarnodeData vData;
|
||||||
restoreTracked(subel,manage,trackbase.split(addr) );
|
vData.decodeFromAttributes(decoder, manage);
|
||||||
|
decodeTracked(decoder,manage,trackbase.split(vData.getAddr()) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Bad <context_points> tag: "+subel->getName());
|
throw LowlevelError("Bad <context_points> tag");
|
||||||
++iter;
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextInternal::restoreFromSpec(const Element *el,const AddrSpaceManager *manage)
|
void ContextInternal::decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CONTEXT_DATA);
|
||||||
List::const_iterator iter = list.begin();
|
for(;;) {
|
||||||
|
uint4 subId = decoder.openElement();
|
||||||
while(iter != list.end()) {
|
if (subId == 0) break;
|
||||||
const Element *subel = *iter;
|
Range range;
|
||||||
if (subel->getName() == "context_set") {
|
range.decodeFromAttributes(decoder, manage); // There MUST be a range
|
||||||
Range range;
|
Address addr1 = range.getFirstAddr();
|
||||||
range.restoreXml(subel,manage); // There MUST be a range
|
Address addr2 = range.getLastAddrOpen(manage);
|
||||||
Address addr1,addr2;
|
if (subId == ELEM_CONTEXT_SET) {
|
||||||
addr1 = range.getFirstAddr();
|
decodeContext(decoder,addr1,addr2);
|
||||||
addr2 = range.getLastAddrOpen(manage);
|
|
||||||
restoreContext(subel,addr1,addr2);
|
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "tracked_set") {
|
else if (subId == ELEM_TRACKED_SET) {
|
||||||
Range range;
|
decodeTracked(decoder,manage,createSet(addr1,addr2));
|
||||||
range.restoreXml(subel,manage); // There MUST be a range
|
|
||||||
Address addr1,addr2;
|
|
||||||
addr1 = range.getFirstAddr();
|
|
||||||
addr2 = range.getLastAddrOpen(manage);
|
|
||||||
restoreTracked(subel,manage,createSet(addr1,addr2));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Bad <context_data> tag: "+subel->getName());
|
throw LowlevelError("Bad <context_data> tag");
|
||||||
++iter;
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param db is the context database that will be encapsulated
|
/// \param db is the context database that will be encapsulated
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
#include "pcoderaw.hh"
|
#include "pcoderaw.hh"
|
||||||
#include "partmap.hh"
|
#include "partmap.hh"
|
||||||
|
|
||||||
|
extern ElementId ELEM_CONTEXT_DATA; ///< Marshaling element \<context_data>
|
||||||
|
extern ElementId ELEM_CONTEXT_POINTS; ///< Marshaling element \<context_points>
|
||||||
|
extern ElementId ELEM_CONTEXT_POINTSET; ///< Marshaling element \<context_pointset>
|
||||||
|
extern ElementId ELEM_CONTEXT_SET; ///< Marshaling element \<context_set>
|
||||||
|
extern ElementId ELEM_SET; ///< Marshaling element \<set>
|
||||||
|
extern ElementId ELEM_TRACKED_POINTSET; ///< Marshaling element \<tracked_pointset>
|
||||||
|
extern ElementId ELEM_TRACKED_SET; ///< Marshaling element \<tracked_set>
|
||||||
|
|
||||||
/// \brief Description of a context variable within the disassembly context \e blob
|
/// \brief Description of a context variable within the disassembly context \e blob
|
||||||
///
|
///
|
||||||
/// Disassembly context is stored as individual (integer) values packed into a sequence of words. This class
|
/// Disassembly context is stored as individual (integer) values packed into a sequence of words. This class
|
||||||
@@ -34,7 +42,7 @@ class ContextBitRange {
|
|||||||
int4 shift; ///< Right-shift amount to apply when unpacking this value from its word
|
int4 shift; ///< Right-shift amount to apply when unpacking this value from its word
|
||||||
uintm mask; ///< Mask to apply (after shifting) when unpacking this value from its word
|
uintm mask; ///< Mask to apply (after shifting) when unpacking this value from its word
|
||||||
public:
|
public:
|
||||||
ContextBitRange(void) { } ///< Constructor for use with restoreXml()
|
ContextBitRange(void) { } ///< Construct an undefined bit range
|
||||||
ContextBitRange(int4 sbit,int4 ebit); ///< Construct a context value given an absolute bit range
|
ContextBitRange(int4 sbit,int4 ebit); ///< Construct a context value given an absolute bit range
|
||||||
int4 getShift(void) const { return shift; } ///< Return the shift-amount for \b this value
|
int4 getShift(void) const { return shift; } ///< Return the shift-amount for \b this value
|
||||||
uintm getMask(void) const { return mask; } ///< Return the mask for \b this value
|
uintm getMask(void) const { return mask; } ///< Return the mask for \b this value
|
||||||
@@ -68,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 restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore \b this from an XML stream
|
void decode(Decoder &decoder,const AddrSpaceManager *manage); ///< Decode \b this from a stream
|
||||||
void saveXml(ostream &s) const; ///< Save \b this to an XML 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)
|
||||||
|
|
||||||
@@ -107,8 +115,8 @@ typedef vector<TrackedContext> TrackedSet; ///< A set of tracked registers and
|
|||||||
/// a list of TrackedContext objects.
|
/// a list of TrackedContext objects.
|
||||||
class ContextDatabase {
|
class ContextDatabase {
|
||||||
protected:
|
protected:
|
||||||
static void saveTracked(ostream &s,const Address &addr,const TrackedSet &vec);
|
static void encodeTracked(Encoder &encoder,const Address &addr,const TrackedSet &vec);
|
||||||
static void restoreTracked(const Element *el,const AddrSpaceManager *manage,TrackedSet &vec);
|
static void decodeTracked(Decoder &decoder,const AddrSpaceManager *manage,TrackedSet &vec);
|
||||||
|
|
||||||
/// \brief Retrieve the context variable description object by name
|
/// \brief Retrieve the context variable description object by name
|
||||||
///
|
///
|
||||||
@@ -218,24 +226,24 @@ public:
|
|||||||
/// \return the empty set of tracked register values
|
/// \return the empty set of tracked register values
|
||||||
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2)=0;
|
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2)=0;
|
||||||
|
|
||||||
/// \brief Serialize the entire database to an XML stream
|
/// \brief Encode the entire database to a stream
|
||||||
///
|
///
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
virtual void saveXml(ostream &s) const=0;
|
virtual void encode(Encoder &encoder) const=0;
|
||||||
|
|
||||||
/// \brief Restore the state of \b this database object from a serialized XML stream
|
/// \brief Restore the state of \b this database object from the given stream decoder
|
||||||
///
|
///
|
||||||
/// \param el is the root element of the XML describing the database state
|
/// \param decoder is the given stream decoder
|
||||||
/// \param manage is used to resolve address space references
|
/// \param manage is used to resolve address space references
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage)=0;
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage)=0;
|
||||||
|
|
||||||
/// \brief Add initial context state from XML tags in compiler/processor specifications
|
/// \brief Add initial context state from elements in the compiler/processor specifications
|
||||||
///
|
///
|
||||||
/// The database can be configured with a consistent initial state by providing
|
/// Parse a \<context_data> element from the given stream decoder from either the compiler
|
||||||
/// \<context_data> tags in either the compiler or processor specification file for the architecture
|
/// or processor specification file for the architecture, initializing this database.
|
||||||
/// \param el is a \<context_data> tag
|
/// \param decoder is the given stream decoder
|
||||||
/// \param manage is used to resolve address space references
|
/// \param manage is used to resolve address space references
|
||||||
virtual void restoreFromSpec(const Element *el,const AddrSpaceManager *manage)=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
|
||||||
@@ -274,8 +282,8 @@ class ContextInternal : public ContextDatabase {
|
|||||||
map<string,ContextBitRange> variables; ///< Map from context variable name to description object
|
map<string,ContextBitRange> variables; ///< Map from context variable name to description object
|
||||||
partmap<Address,FreeArray> database; ///< Partition map of context blobs (FreeArray)
|
partmap<Address,FreeArray> database; ///< Partition map of context blobs (FreeArray)
|
||||||
partmap<Address,TrackedSet> trackbase; ///< Partition map of tracked register sets
|
partmap<Address,TrackedSet> trackbase; ///< Partition map of tracked register sets
|
||||||
void saveContext(ostream &s,const Address &addr,const uintm *vec) const;
|
void encodeContext(Encoder &encoder,const Address &addr,const uintm *vec) const;
|
||||||
void restoreContext(const Element *el,const Address &addr1,const Address &addr2);
|
void decodeContext(Decoder &decoder,const Address &addr1,const Address &addr2);
|
||||||
virtual ContextBitRange &getVariable(const string &nm);
|
virtual ContextBitRange &getVariable(const string &nm);
|
||||||
virtual const ContextBitRange &getVariable(const string &nm) const;
|
virtual const ContextBitRange &getVariable(const string &nm) const;
|
||||||
virtual void getRegionForSet(vector<uintm *> &res,const Address &addr1,
|
virtual void getRegionForSet(vector<uintm *> &res,const Address &addr1,
|
||||||
@@ -296,9 +304,9 @@ public:
|
|||||||
virtual const TrackedSet &getTrackedSet(const Address &addr) const { return trackbase.getValue(addr); }
|
virtual const TrackedSet &getTrackedSet(const Address &addr) const { return trackbase.getValue(addr); }
|
||||||
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2);
|
virtual TrackedSet &createSet(const Address &addr1,const Address &addr2);
|
||||||
|
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
virtual void decode(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
virtual void restoreFromSpec(const Element *el,const AddrSpaceManager *manage);
|
virtual void decodeFromSpec(Decoder &decoder,const AddrSpaceManager *manage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \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
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ void IfcOption::execute(istream &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
string res = dcp->conf->options->set(optname,p1,p2,p3);
|
string res = dcp->conf->options->set(ElementId::find(optname),p1,p2,p3);
|
||||||
*status->optr << res << endl;
|
*status->optr << res << endl;
|
||||||
}
|
}
|
||||||
catch(ParseError &err) {
|
catch(ParseError &err) {
|
||||||
@@ -2690,7 +2690,8 @@ void IfcCallGraphDump::execute(istream &s)
|
|||||||
if (!os)
|
if (!os)
|
||||||
throw IfaceExecutionError("Unable to open file "+name);
|
throw IfaceExecutionError("Unable to open file "+name);
|
||||||
|
|
||||||
dcp->cgraph->saveXml(os);
|
XmlEncode encoder(os);
|
||||||
|
dcp->cgraph->encode(encoder);
|
||||||
os.close();
|
os.close();
|
||||||
*status->optr << "Successfully saved callgraph to " << name << endl;
|
*status->optr << "Successfully saved callgraph to " << name << endl;
|
||||||
}
|
}
|
||||||
@@ -2723,7 +2724,8 @@ void IfcCallGraphLoad::execute(istream &s)
|
|||||||
Document *doc = store.parseDocument(is);
|
Document *doc = store.parseDocument(is);
|
||||||
|
|
||||||
dcp->allocateCallGraph();
|
dcp->allocateCallGraph();
|
||||||
dcp->cgraph->restoreXml(doc->getRoot());
|
XmlDecode decoder(doc->getRoot());
|
||||||
|
dcp->cgraph->decoder(decoder);
|
||||||
*status->optr << "Successfully read in callgraph" << endl;
|
*status->optr << "Successfully read in callgraph" << endl;
|
||||||
|
|
||||||
Scope *gscope = dcp->conf->symboltab->getGlobalScope();
|
Scope *gscope = dcp->conf->symboltab->getGlobalScope();
|
||||||
@@ -3014,7 +3016,8 @@ void IfcStructureBlocks::execute(istream &s)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
BlockGraph ingraph;
|
BlockGraph ingraph;
|
||||||
ingraph.restoreXml(doc->getRoot(),dcp->conf);
|
XmlDecode decoder(doc->getRoot());
|
||||||
|
ingraph.decode(decoder,dcp->conf);
|
||||||
|
|
||||||
BlockGraph resultgraph;
|
BlockGraph resultgraph;
|
||||||
vector<FlowBlock *> rootlist;
|
vector<FlowBlock *> rootlist;
|
||||||
@@ -3030,7 +3033,8 @@ void IfcStructureBlocks::execute(istream &s)
|
|||||||
sout.open(outfile.c_str());
|
sout.open(outfile.c_str());
|
||||||
if (!sout)
|
if (!sout)
|
||||||
throw IfaceExecutionError("Unable to open output file: "+outfile);
|
throw IfaceExecutionError("Unable to open output file: "+outfile);
|
||||||
resultgraph.saveXml(sout);
|
XmlEncode encoder(sout);
|
||||||
|
resultgraph.encode(encoder);
|
||||||
sout.close();
|
sout.close();
|
||||||
}
|
}
|
||||||
catch(LowlevelError &err) {
|
catch(LowlevelError &err) {
|
||||||
|
|||||||
@@ -15,42 +15,43 @@
|
|||||||
*/
|
*/
|
||||||
#include "inject_ghidra.hh"
|
#include "inject_ghidra.hh"
|
||||||
|
|
||||||
void InjectContextGhidra::saveXml(ostream &s) const
|
void InjectContextGhidra::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<context>\n";
|
encoder.openElement(ELEM_CONTEXT);
|
||||||
baseaddr.saveXml(s);
|
baseaddr.encode(encoder);
|
||||||
calladdr.saveXml(s);
|
calladdr.encode(encoder);
|
||||||
if (!inputlist.empty()) {
|
if (!inputlist.empty()) {
|
||||||
s << "<input>\n";
|
encoder.openElement(ELEM_INPUT);
|
||||||
for(int4 i=0;i<inputlist.size();++i) {
|
for(int4 i=0;i<inputlist.size();++i) {
|
||||||
const VarnodeData &vn( inputlist[i] );
|
const VarnodeData &vn( inputlist[i] );
|
||||||
s << "<addr";
|
encoder.openElement(ELEM_ADDR);
|
||||||
vn.space->saveXmlAttributes(s,vn.offset,vn.size);
|
vn.space->encodeAttributes(encoder,vn.offset,vn.size);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_ADDR);
|
||||||
}
|
}
|
||||||
s << "</input>\n";
|
encoder.closeElement(ELEM_INPUT);
|
||||||
}
|
}
|
||||||
if (!output.empty()) {
|
if (!output.empty()) {
|
||||||
s << "<output>\n";
|
encoder.openElement(ELEM_OUTPUT);
|
||||||
for(int4 i=0;i<output.size();++i) {
|
for(int4 i=0;i<output.size();++i) {
|
||||||
const VarnodeData &vn( output[i] );
|
const VarnodeData &vn( output[i] );
|
||||||
s << "<addr";
|
encoder.openElement(ELEM_ADDR);
|
||||||
vn.space->saveXmlAttributes(s,vn.offset,vn.size);
|
vn.space->encodeAttributes(encoder,vn.offset,vn.size);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_ADDR);
|
||||||
}
|
}
|
||||||
s << "</output>\n";
|
encoder.closeElement(ELEM_OUTPUT);
|
||||||
}
|
}
|
||||||
s << "</context>\n";
|
encoder.closeElement(ELEM_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Document *doc;
|
|
||||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||||
|
XmlDecode decoder;
|
||||||
try {
|
try {
|
||||||
doc = ghidra->getPcodeInject(name,type,con);
|
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||||
|
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||||
}
|
}
|
||||||
catch(JavaError &err) {
|
catch(JavaError &err) {
|
||||||
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
||||||
@@ -58,15 +59,19 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||||||
catch(XmlError &err) {
|
catch(XmlError &err) {
|
||||||
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
||||||
}
|
}
|
||||||
if (doc == (Document *)0) {
|
uint4 elemId = decoder.openElement();
|
||||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
while(decoder.peekElement() != 0)
|
||||||
}
|
emit.decodeOp(decoder,ghidra->translate);
|
||||||
const Element *el = doc->getRoot();
|
decoder.closeElement(elemId);
|
||||||
const List &list(el->getChildren());
|
}
|
||||||
List::const_iterator iter;
|
|
||||||
for(iter=list.begin();iter!=list.end();++iter)
|
void InjectPayloadGhidra::decode(Decoder &decoder)
|
||||||
emit.restoreXmlOp(*iter,ghidra->translate);
|
|
||||||
delete doc;
|
{
|
||||||
|
// Restore a raw <pcode> tag. Used for uponentry, uponreturn
|
||||||
|
uint4 elemId = decoder.openElement(ELEM_PCODE);
|
||||||
|
decodePayloadAttributes(decoder);
|
||||||
|
decoder.closeElementSkipping(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadGhidra::printTemplate(ostream &s) const
|
void InjectPayloadGhidra::printTemplate(ostream &s) const
|
||||||
@@ -80,10 +85,12 @@ InjectCallfixupGhidra::InjectCallfixupGhidra(const string &src,const string &nm)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectCallfixupGhidra::restoreXml(const Element *el)
|
void InjectCallfixupGhidra::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
name = el->getAttributeValue("name");
|
uint4 elemId = decoder.openElement(ELEM_CALLFIXUP);
|
||||||
|
name = decoder.readString(ATTRIB_NAME);
|
||||||
|
decoder.closeElementSkipping(elemId); // Skip processing the body, let ghidra handle this
|
||||||
}
|
}
|
||||||
|
|
||||||
InjectCallotherGhidra::InjectCallotherGhidra(const string &src,const string &nm)
|
InjectCallotherGhidra::InjectCallotherGhidra(const string &src,const string &nm)
|
||||||
@@ -91,16 +98,18 @@ InjectCallotherGhidra::InjectCallotherGhidra(const string &src,const string &nm)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectCallotherGhidra::restoreXml(const Element *el)
|
void InjectCallotherGhidra::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CALLOTHERFIXUP);
|
||||||
List::const_iterator iter;
|
name = decoder.readString(ATTRIB_TARGETOP);
|
||||||
name = el->getAttributeValue("targetop");
|
uint4 subId = decoder.openElement();
|
||||||
iter = list.begin();
|
if (subId != ELEM_PCODE)
|
||||||
if ((iter == list.end()) || ((*iter)->getName() != "pcode"))
|
|
||||||
throw LowlevelError("<callotherfixup> does not contain a <pcode> tag");
|
throw LowlevelError("<callotherfixup> does not contain a <pcode> tag");
|
||||||
InjectPayload::restoreXml(*iter);
|
decodePayloadAttributes(decoder);
|
||||||
|
decodePayloadParams(decoder);
|
||||||
|
decoder.closeElementSkipping(subId); // Skip processing the body, let ghidra handle this
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutablePcodeGhidra::ExecutablePcodeGhidra(Architecture *g,const string &src,const string &nm)
|
ExecutablePcodeGhidra::ExecutablePcodeGhidra(Architecture *g,const string &src,const string &nm)
|
||||||
@@ -111,10 +120,11 @@ ExecutablePcodeGhidra::ExecutablePcodeGhidra(Architecture *g,const string &src,c
|
|||||||
void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Document *doc;
|
|
||||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||||
|
XmlDecode decoder;
|
||||||
try {
|
try {
|
||||||
doc = ghidra->getPcodeInject(name,type,con);
|
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||||
|
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||||
}
|
}
|
||||||
catch(JavaError &err) {
|
catch(JavaError &err) {
|
||||||
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
||||||
@@ -122,22 +132,22 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||||||
catch(XmlError &err) {
|
catch(XmlError &err) {
|
||||||
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
||||||
}
|
}
|
||||||
if (doc == (Document *)0) {
|
uint4 elemId = decoder.openElement();
|
||||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
while(decoder.peekElement() != 0)
|
||||||
}
|
emit.decodeOp(decoder,ghidra->translate);
|
||||||
const Element *el = doc->getRoot();
|
decoder.closeElement(elemId);
|
||||||
const List &list(el->getChildren());
|
|
||||||
List::const_iterator iter;
|
|
||||||
for(iter=list.begin();iter!=list.end();++iter)
|
|
||||||
emit.restoreXmlOp(*iter,ghidra->translate);
|
|
||||||
delete doc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutablePcodeGhidra::restoreXml(const Element *el)
|
void ExecutablePcodeGhidra::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
InjectPayload::restoreXml(el); // Read parameters
|
uint4 elemId = decoder.openElement();
|
||||||
// But ignore rest of body
|
if (elemId != ELEM_CASE_PCODE && elemId != ELEM_ADDR_PCODE &&
|
||||||
|
elemId != ELEM_DEFAULT_PCODE && elemId != ELEM_SIZE_PCODE)
|
||||||
|
throw XmlError("Expecting <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||||
|
decodePayloadAttributes(decoder);
|
||||||
|
decodePayloadParams(decoder); // Parse the parameters
|
||||||
|
decoder.closeElementSkipping(elemId); // But skip rest of body
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutablePcodeGhidra::printTemplate(ostream &s) const
|
void ExecutablePcodeGhidra::printTemplate(ostream &s) const
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
/// that can then be forwarded to the Ghidra client.
|
/// that can then be forwarded to the Ghidra client.
|
||||||
class InjectContextGhidra : public InjectContext {
|
class InjectContextGhidra : public InjectContext {
|
||||||
public:
|
public:
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An injection payload that uses a Ghidra client to generate the p-code ops
|
/// \brief An injection payload that uses a Ghidra client to generate the p-code ops
|
||||||
@@ -41,7 +41,7 @@ class InjectPayloadGhidra : public InjectPayload {
|
|||||||
public:
|
public:
|
||||||
InjectPayloadGhidra(const string &src,const string &nm,int4 tp) : InjectPayload(nm,tp) { source = src; } ///< Constructor
|
InjectPayloadGhidra(const string &src,const string &nm,int4 tp) : InjectPayload(nm,tp) { source = src; } ///< Constructor
|
||||||
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
||||||
virtual void restoreXml(const Element *el) {}
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void printTemplate(ostream &s) const;
|
virtual void printTemplate(ostream &s) const;
|
||||||
virtual string getSource(void) const { return source; }
|
virtual string getSource(void) const { return source; }
|
||||||
};
|
};
|
||||||
@@ -50,14 +50,14 @@ public:
|
|||||||
class InjectCallfixupGhidra : public InjectPayloadGhidra {
|
class InjectCallfixupGhidra : public InjectPayloadGhidra {
|
||||||
public:
|
public:
|
||||||
InjectCallfixupGhidra(const string &src,const string &nm); ///< Constructor
|
InjectCallfixupGhidra(const string &src,const string &nm); ///< Constructor
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A callother-fixup injection that uses a Ghidra client to generate the p-code ops
|
/// \brief A callother-fixup injection that uses a Ghidra client to generate the p-code ops
|
||||||
class InjectCallotherGhidra : public InjectPayloadGhidra {
|
class InjectCallotherGhidra : public InjectPayloadGhidra {
|
||||||
public:
|
public:
|
||||||
InjectCallotherGhidra(const string &src,const string &nm); ///< Constructor
|
InjectCallotherGhidra(const string &src,const string &nm); ///< Constructor
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A \e p-code \e script that uses a Ghidra client to generate the p-code ops
|
/// \brief A \e p-code \e script that uses a Ghidra client to generate the p-code ops
|
||||||
@@ -69,7 +69,7 @@ class ExecutablePcodeGhidra : public ExecutablePcode {
|
|||||||
public:
|
public:
|
||||||
ExecutablePcodeGhidra(Architecture *g,const string &src,const string &nm); ///< Constructor
|
ExecutablePcodeGhidra(Architecture *g,const string &src,const string &nm); ///< Constructor
|
||||||
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void printTemplate(ostream &s) const;
|
virtual void printTemplate(ostream &s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,22 +61,31 @@ void InjectPayloadSleigh::inject(InjectContext &context,PcodeEmit &emit) const
|
|||||||
con.cacher.emit(con.baseaddr,&emit);
|
con.cacher.emit(con.baseaddr,&emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadSleigh::restoreXml(const Element *el)
|
/// The content is read as raw p-code source
|
||||||
|
/// \param decoder is the XML stream decoder
|
||||||
|
void InjectPayloadSleigh::decodeBody(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
InjectPayload::restoreXml(el);
|
uint4 elemId = decoder.openElement(); // Tag may not be present
|
||||||
const List &list(el->getChildren());
|
if (elemId == ELEM_BODY) {
|
||||||
List::const_iterator iter;
|
parsestring = decoder.readString(ATTRIB_CONTENT);
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
decoder.closeElement(elemId);
|
||||||
const Element *subel = *iter;
|
|
||||||
if (subel->getName() == "body") {
|
|
||||||
parsestring = subel->getContent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (parsestring.size() == 0 && (!dynamic))
|
if (parsestring.size() == 0 && (!dynamic))
|
||||||
throw LowlevelError("Missing <body> subtag in <pcode>: "+getSource());
|
throw LowlevelError("Missing <body> subtag in <pcode>: "+getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InjectPayloadSleigh::decode(Decoder &decoder)
|
||||||
|
|
||||||
|
{
|
||||||
|
// Restore a raw <pcode> tag. Used for uponentry, uponreturn
|
||||||
|
uint4 elemId = decoder.openElement(ELEM_PCODE);
|
||||||
|
decodePayloadAttributes(decoder);
|
||||||
|
decodePayloadParams(decoder);
|
||||||
|
decodeBody(decoder);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
|
}
|
||||||
|
|
||||||
void InjectPayloadSleigh::printTemplate(ostream &s) const
|
void InjectPayloadSleigh::printTemplate(ostream &s) const
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -138,23 +147,27 @@ InjectPayloadCallfixup::InjectPayloadCallfixup(const string &sourceName)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadCallfixup::restoreXml(const Element *el)
|
void InjectPayloadCallfixup::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CALLFIXUP);
|
||||||
List::const_iterator iter;
|
name = decoder.readString(ATTRIB_NAME);
|
||||||
name = el->getAttributeValue("name");
|
|
||||||
bool pcodeSubtag = false;
|
bool pcodeSubtag = false;
|
||||||
|
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
for(;;) {
|
||||||
const Element *subel = *iter;
|
uint4 subId = decoder.openElement();
|
||||||
if (subel->getName() == "pcode") {
|
if (subId == 0) break;
|
||||||
InjectPayloadSleigh::restoreXml(subel);
|
if (subId == ELEM_PCODE) {
|
||||||
|
decodePayloadAttributes(decoder);
|
||||||
|
decodePayloadParams(decoder);
|
||||||
|
decodeBody(decoder);
|
||||||
pcodeSubtag = true;
|
pcodeSubtag = true;
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "target")
|
else if (subId == ELEM_TARGET)
|
||||||
targetSymbolNames.push_back(subel->getAttributeValue("name"));
|
targetSymbolNames.push_back(decoder.readString(ATTRIB_NAME));
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
if (!pcodeSubtag)
|
if (!pcodeSubtag)
|
||||||
throw LowlevelError("<callfixup> is missing <pcode> subtag: "+name);
|
throw LowlevelError("<callfixup> is missing <pcode> subtag: "+name);
|
||||||
}
|
}
|
||||||
@@ -164,16 +177,19 @@ InjectPayloadCallother::InjectPayloadCallother(const string &sourceName)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadCallother::restoreXml(const Element *el)
|
void InjectPayloadCallother::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_CALLOTHERFIXUP);
|
||||||
List::const_iterator iter;
|
name = decoder.readString(ATTRIB_TARGETOP);
|
||||||
name = el->getAttributeValue("targetop");
|
uint4 subId = decoder.openElement();
|
||||||
iter = list.begin();
|
if (subId != ELEM_PCODE)
|
||||||
if ((iter == list.end()) || ((*iter)->getName() != "pcode"))
|
|
||||||
throw LowlevelError("<callotherfixup> does not contain a <pcode> tag");
|
throw LowlevelError("<callotherfixup> does not contain a <pcode> tag");
|
||||||
InjectPayloadSleigh::restoreXml(*iter);
|
decodePayloadAttributes(decoder);
|
||||||
|
decodePayloadParams(decoder);
|
||||||
|
decodeBody(decoder);
|
||||||
|
decoder.closeElement(subId);
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutablePcodeSleigh::ExecutablePcodeSleigh(Architecture *g,const string &src,const string &nm)
|
ExecutablePcodeSleigh::ExecutablePcodeSleigh(Architecture *g,const string &src,const string &nm)
|
||||||
@@ -211,22 +227,18 @@ void ExecutablePcodeSleigh::inject(InjectContext &context,PcodeEmit &emit) const
|
|||||||
con.cacher.emit(con.baseaddr,&emit);
|
con.cacher.emit(con.baseaddr,&emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutablePcodeSleigh::restoreXml(const Element *el)
|
void ExecutablePcodeSleigh::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
InjectPayload::restoreXml(el);
|
uint4 elemId = decoder.openElement();
|
||||||
const List &list(el->getChildren());
|
if (elemId != ELEM_CASE_PCODE && elemId != ELEM_ADDR_PCODE && elemId != ELEM_DEFAULT_PCODE && elemId != ELEM_SIZE_PCODE)
|
||||||
List::const_iterator iter;
|
throw XmlError("Expecting <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||||
bool hasbody = false;
|
decodePayloadAttributes(decoder);
|
||||||
for (iter = list.begin(); iter != list.end(); ++iter) {
|
decodePayloadParams(decoder);
|
||||||
const Element *subel = *iter;
|
uint4 subId = decoder.openElement(ELEM_BODY);
|
||||||
if (subel->getName() == "body") {
|
parsestring = decoder.readString(ATTRIB_CONTENT);
|
||||||
hasbody = true;
|
decoder.closeElement(subId);
|
||||||
parsestring = subel->getContent();
|
decoder.closeElement(elemId);
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasbody)
|
|
||||||
throw LowlevelError("Missing <body> subtag in <pcode>: " + getSource());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutablePcodeSleigh::printTemplate(ostream &s) const
|
void ExecutablePcodeSleigh::printTemplate(ostream &s) const
|
||||||
@@ -243,16 +255,12 @@ InjectPayloadDynamic::~InjectPayloadDynamic(void)
|
|||||||
delete (*iter).second;
|
delete (*iter).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadDynamic::restoreEntry(const Element *el)
|
void InjectPayloadDynamic::decodeEntry(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
Address addr = Address::decode(decoder,glb);
|
||||||
List::const_iterator iter;
|
uint4 subId = decoder.openElement(ELEM_PAYLOAD);
|
||||||
|
istringstream s(decoder.readString(ATTRIB_CONTENT));
|
||||||
iter = list.begin();
|
|
||||||
Address addr = Address::restoreXml(*iter,glb);
|
|
||||||
++iter;
|
|
||||||
istringstream s((*iter)->getContent());
|
|
||||||
try {
|
try {
|
||||||
Document *doc = xml_tree(s);
|
Document *doc = xml_tree(s);
|
||||||
map<Address,Document *>::iterator iter = addrMap.find(addr);
|
map<Address,Document *>::iterator iter = addrMap.find(addr);
|
||||||
@@ -263,6 +271,7 @@ void InjectPayloadDynamic::restoreEntry(const Element *el)
|
|||||||
catch(XmlError &err) {
|
catch(XmlError &err) {
|
||||||
throw LowlevelError("Error in dynamic payload XML");
|
throw LowlevelError("Error in dynamic payload XML");
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
|
void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
|
||||||
@@ -272,10 +281,11 @@ 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();
|
||||||
const List &list(el->getChildren());
|
XmlDecode decoder(el);
|
||||||
List::const_iterator iter;
|
uint4 rootId = decoder.openElement(ELEM_INST);
|
||||||
for(iter=list.begin();iter!=list.end();++iter)
|
while(decoder.peekElement() != 0)
|
||||||
emit.restoreXmlOp(*iter,glb->translate);
|
emit.decodeOp(decoder,glb->translate);
|
||||||
|
decoder.closeElement(rootId);
|
||||||
}
|
}
|
||||||
|
|
||||||
PcodeInjectLibrarySleigh::PcodeInjectLibrarySleigh(Architecture *g)
|
PcodeInjectLibrarySleigh::PcodeInjectLibrarySleigh(Architecture *g)
|
||||||
@@ -402,26 +412,24 @@ void PcodeInjectLibrarySleigh::registerInject(int4 injectid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcodeInjectLibrarySleigh::restoreDebug(const Element *el)
|
void PcodeInjectLibrarySleigh::decodeDebug(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list(el->getChildren());
|
uint4 elemId = decoder.openElement(ELEM_INJECTDEBUG);
|
||||||
List::const_iterator iter;
|
for(;;) {
|
||||||
|
uint4 subId = decoder.openElement();
|
||||||
for(iter=list.begin();iter!=list.end();++iter) {
|
if (subId != ELEM_INJECT) break;
|
||||||
const Element *subel = *iter;
|
string name = decoder.readString(ATTRIB_NAME);
|
||||||
const string &name( subel->getAttributeValue("name") );
|
int4 type = decoder.readSignedInteger(ATTRIB_TYPE);
|
||||||
istringstream s( subel->getAttributeValue("type") );
|
|
||||||
int4 type = -1;
|
|
||||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s >> type;
|
|
||||||
int4 id = getPayloadId(type,name);
|
int4 id = getPayloadId(type,name);
|
||||||
InjectPayloadDynamic *payload = dynamic_cast<InjectPayloadDynamic *>(getPayload(id));
|
InjectPayloadDynamic *payload = dynamic_cast<InjectPayloadDynamic *>(getPayload(id));
|
||||||
if (payload == (InjectPayloadDynamic *)0) {
|
if (payload == (InjectPayloadDynamic *)0) {
|
||||||
payload = forceDebugDynamic(id);
|
payload = forceDebugDynamic(id);
|
||||||
}
|
}
|
||||||
payload->restoreEntry(subel);
|
payload->decodeEntry(decoder);
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vector<OpBehavior *> &PcodeInjectLibrarySleigh::getBehaviors(void)
|
const vector<OpBehavior *> &PcodeInjectLibrarySleigh::getBehaviors(void)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public:
|
|||||||
ParserContext *pos;
|
ParserContext *pos;
|
||||||
InjectContextSleigh(void) { pos = (ParserContext *)0; }
|
InjectContextSleigh(void) { pos = (ParserContext *)0; }
|
||||||
virtual ~InjectContextSleigh(void);
|
virtual ~InjectContextSleigh(void);
|
||||||
virtual void saveXml(ostream &s) const {} // We don't need this functionality for sleigh
|
virtual void encode(Encoder &encoder) const {} // We don't need this functionality for sleigh
|
||||||
};
|
};
|
||||||
|
|
||||||
class InjectPayloadSleigh : public InjectPayload {
|
class InjectPayloadSleigh : public InjectPayload {
|
||||||
@@ -33,11 +33,13 @@ class InjectPayloadSleigh : public InjectPayload {
|
|||||||
ConstructTpl *tpl;
|
ConstructTpl *tpl;
|
||||||
string parsestring;
|
string parsestring;
|
||||||
string source;
|
string source;
|
||||||
|
protected:
|
||||||
|
void decodeBody(Decoder &decoder); ///< Parse the <body> tag
|
||||||
public:
|
public:
|
||||||
InjectPayloadSleigh(const string &src,const string &nm,int4 tp);
|
InjectPayloadSleigh(const string &src,const string &nm,int4 tp);
|
||||||
virtual ~InjectPayloadSleigh(void);
|
virtual ~InjectPayloadSleigh(void);
|
||||||
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void printTemplate(ostream &s) const;
|
virtual void printTemplate(ostream &s) const;
|
||||||
virtual string getSource(void) const { return source; }
|
virtual string getSource(void) const { return source; }
|
||||||
|
|
||||||
@@ -52,13 +54,13 @@ class InjectPayloadCallfixup : public InjectPayloadSleigh {
|
|||||||
vector<string> targetSymbolNames;
|
vector<string> targetSymbolNames;
|
||||||
public:
|
public:
|
||||||
InjectPayloadCallfixup(const string &sourceName);
|
InjectPayloadCallfixup(const string &sourceName);
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InjectPayloadCallother : public InjectPayloadSleigh {
|
class InjectPayloadCallother : public InjectPayloadSleigh {
|
||||||
public:
|
public:
|
||||||
InjectPayloadCallother(const string &sourceName);
|
InjectPayloadCallother(const string &sourceName);
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExecutablePcodeSleigh : public ExecutablePcode {
|
class ExecutablePcodeSleigh : public ExecutablePcode {
|
||||||
@@ -70,7 +72,7 @@ protected:
|
|||||||
ExecutablePcodeSleigh(Architecture *g,const string &src,const string &nm);
|
ExecutablePcodeSleigh(Architecture *g,const string &src,const string &nm);
|
||||||
virtual ~ExecutablePcodeSleigh(void);
|
virtual ~ExecutablePcodeSleigh(void);
|
||||||
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void decode(Decoder &decoder);
|
||||||
virtual void printTemplate(ostream &s) const;
|
virtual void printTemplate(ostream &s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,8 +82,9 @@ class InjectPayloadDynamic : public InjectPayload {
|
|||||||
public:
|
public:
|
||||||
InjectPayloadDynamic(Architecture *g,const string &nm,int4 tp) : InjectPayload(nm,tp) { glb = g; dynamic = true; }
|
InjectPayloadDynamic(Architecture *g,const string &nm,int4 tp) : InjectPayload(nm,tp) { glb = g; dynamic = true; }
|
||||||
virtual ~InjectPayloadDynamic(void);
|
virtual ~InjectPayloadDynamic(void);
|
||||||
void restoreEntry(const Element *el);
|
void decodeEntry(Decoder &decoder);
|
||||||
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
virtual void inject(InjectContext &context,PcodeEmit &emit) const;
|
||||||
|
virtual void decode(Decoder &decoder) { throw LowlevelError("decode not supported for InjectPayloadDynamic"); }
|
||||||
virtual void printTemplate(ostream &s) const { s << "dynamic"; }
|
virtual void printTemplate(ostream &s) const { s << "dynamic"; }
|
||||||
virtual string getSource(void) const { return "dynamic"; }
|
virtual string getSource(void) const { return "dynamic"; }
|
||||||
};
|
};
|
||||||
@@ -98,7 +101,7 @@ protected:
|
|||||||
virtual void registerInject(int4 injectid);
|
virtual void registerInject(int4 injectid);
|
||||||
public:
|
public:
|
||||||
PcodeInjectLibrarySleigh(Architecture *g);
|
PcodeInjectLibrarySleigh(Architecture *g);
|
||||||
virtual void restoreDebug(const Element *el);
|
virtual void decodeDebug(Decoder &decoder);
|
||||||
virtual int4 manualCallFixup(const string &name,const string &snippetstring);
|
virtual int4 manualCallFixup(const string &name,const string &snippetstring);
|
||||||
virtual int4 manualCallOtherFixup(const string &name,const string &outname,const vector<string> &inname,
|
virtual int4 manualCallOtherFixup(const string &name,const string &outname,const vector<string> &inname,
|
||||||
const string &snippet);
|
const string &snippet);
|
||||||
|
|||||||
@@ -17,32 +17,38 @@
|
|||||||
#include "emulate.hh"
|
#include "emulate.hh"
|
||||||
#include "flow.hh"
|
#include "flow.hh"
|
||||||
|
|
||||||
/// \param s is the XML stream to write to
|
AttributeId ATTRIB_LABEL = AttributeId("label",71);
|
||||||
void LoadTable::saveXml(ostream &s) const
|
AttributeId ATTRIB_NUM = AttributeId("num",72);
|
||||||
|
|
||||||
|
ElementId ELEM_BASICOVERRIDE = ElementId("basicoverride",101);
|
||||||
|
ElementId ELEM_DEST = ElementId("dest",102);
|
||||||
|
ElementId ELEM_JUMPTABLE = ElementId("jumptable",103);
|
||||||
|
ElementId ELEM_LOADTABLE = ElementId("loadtable",104);
|
||||||
|
ElementId ELEM_NORMADDR = ElementId("normaddr",105);
|
||||||
|
ElementId ELEM_NORMHASH = ElementId("normhash",106);
|
||||||
|
ElementId ELEM_STARTVAL = ElementId("startval",107);
|
||||||
|
|
||||||
|
/// \param encoder is the stream encoder
|
||||||
|
void LoadTable::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<loadtable";
|
encoder.openElement(ELEM_LOADTABLE);
|
||||||
a_v_i(s,"size",size);
|
encoder.writeSignedInteger(ATTRIB_SIZE, size);
|
||||||
a_v_i(s,"num",num);
|
encoder.writeSignedInteger(ATTRIB_NUM, num);
|
||||||
s << ">\n ";
|
addr.encode(encoder);
|
||||||
addr.saveXml(s);
|
encoder.closeElement(ELEM_LOADTABLE);
|
||||||
s << "</loadtable>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param el is the root \<loadtable> tag
|
/// \param decoder is the stream decoder
|
||||||
/// \param glb is the architecture for resolving address space tags
|
/// \param glb is the architecture for resolving address space tags
|
||||||
void LoadTable::restoreXml(const Element *el,Architecture *glb)
|
void LoadTable::decode(Decoder &decoder,Architecture *glb)
|
||||||
|
|
||||||
{
|
{
|
||||||
istringstream s1(el->getAttributeValue("size"));
|
uint4 elemId = decoder.openElement(ELEM_LOADTABLE);
|
||||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
size = decoder.readSignedInteger(ATTRIB_SIZE);
|
||||||
s1 >> size;
|
num = decoder.readSignedInteger(ATTRIB_NUM);
|
||||||
istringstream s2(el->getAttributeValue("num"));
|
addr = Address::decode( decoder, glb);
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
decoder.closeElement(elemId);
|
||||||
s2 >> num;
|
|
||||||
const List &list( el->getChildren() );
|
|
||||||
List::const_iterator iter = list.begin();
|
|
||||||
addr = Address::restoreXml( *iter, glb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We assume the list of LoadTable entries is sorted and perform an in-place
|
/// We assume the list of LoadTable entries is sorted and perform an in-place
|
||||||
@@ -1899,55 +1905,61 @@ void JumpBasicOverride::clear(void)
|
|||||||
istrivial = false;
|
istrivial = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JumpBasicOverride::saveXml(ostream &s) const
|
void JumpBasicOverride::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
set<Address>::const_iterator iter;
|
set<Address>::const_iterator iter;
|
||||||
|
|
||||||
s << "<basicoverride>\n";
|
encoder.openElement(ELEM_BASICOVERRIDE);
|
||||||
for(iter=adset.begin();iter!=adset.end();++iter) {
|
for(iter=adset.begin();iter!=adset.end();++iter) {
|
||||||
s << " <dest";
|
encoder.openElement(ELEM_DEST);
|
||||||
AddrSpace *spc = (*iter).getSpace();
|
AddrSpace *spc = (*iter).getSpace();
|
||||||
uintb off = (*iter).getOffset();
|
uintb off = (*iter).getOffset();
|
||||||
spc->saveXmlAttributes(s,off);
|
spc->encodeAttributes(encoder,off);
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_DEST);
|
||||||
}
|
}
|
||||||
if (hash != 0) {
|
if (hash != 0) {
|
||||||
s << " <normaddr";
|
encoder.openElement(ELEM_NORMADDR);
|
||||||
normaddress.getSpace()->saveXmlAttributes(s,normaddress.getOffset());
|
normaddress.getSpace()->encodeAttributes(encoder,normaddress.getOffset());
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_NORMADDR);
|
||||||
s << " <normhash>0x" << hex << hash << "</normhash>\n";
|
encoder.openElement(ELEM_NORMHASH);
|
||||||
|
encoder.writeUnsignedInteger(ATTRIB_CONTENT, hash);
|
||||||
|
encoder.closeElement(ELEM_NORMHASH);
|
||||||
}
|
}
|
||||||
if (startingvalue != 0) {
|
if (startingvalue != 0) {
|
||||||
s << " <startval>0x" << hex << startingvalue << "</startval>\n";
|
encoder.openElement(ELEM_STARTVAL);
|
||||||
|
encoder.writeUnsignedInteger(ATTRIB_CONTENT, startingvalue);
|
||||||
|
encoder.closeElement(ELEM_STARTVAL);
|
||||||
}
|
}
|
||||||
s << "</basicoverride>\n";
|
encoder.closeElement(ELEM_BASICOVERRIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JumpBasicOverride::restoreXml(const Element *el,Architecture *glb)
|
void JumpBasicOverride::decode(Decoder &decoder,Architecture *glb)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list( el->getChildren() );
|
uint4 elemId = decoder.openElement(ELEM_BASICOVERRIDE);
|
||||||
List::const_iterator iter = list.begin();
|
for(;;) {
|
||||||
while(iter != list.end()) {
|
uint4 subId = decoder.openElement();
|
||||||
const Element *subel = *iter;
|
if (subId == 0) break;
|
||||||
++iter;
|
if (subId == ELEM_DEST) {
|
||||||
if (subel->getName() == "dest") {
|
VarnodeData vData;
|
||||||
adset.insert( Address::restoreXml(subel,glb) );
|
vData.decodeFromAttributes(decoder, glb);
|
||||||
|
adset.insert( vData.getAddr() );
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "normaddr")
|
else if (subId == ELEM_NORMADDR) {
|
||||||
normaddress = Address::restoreXml(subel,glb);
|
VarnodeData vData;
|
||||||
else if (subel->getName() == "normhash") {
|
vData.decodeFromAttributes(decoder, glb);
|
||||||
istringstream s1(subel->getContent());
|
normaddress = vData.getAddr();
|
||||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s1 >> hash;
|
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "startval") {
|
else if (subId == ELEM_NORMHASH) {
|
||||||
istringstream s2(subel->getContent());
|
hash = decoder.readUnsignedInteger(ATTRIB_CONTENT);
|
||||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
s2 >> startingvalue;
|
|
||||||
}
|
}
|
||||||
|
else if (subId == ELEM_STARTVAL) {
|
||||||
|
startingvalue = decoder.readUnsignedInteger(ATTRIB_CONTENT);
|
||||||
|
}
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
if (adset.empty())
|
if (adset.empty())
|
||||||
throw LowlevelError("Empty jumptable override");
|
throw LowlevelError("Empty jumptable override");
|
||||||
}
|
}
|
||||||
@@ -2594,83 +2606,81 @@ void JumpTable::clear(void)
|
|||||||
// -opaddress- -maxtablesize- -maxaddsub- -maxleftright- -maxext- -collectloads- are permanent
|
// -opaddress- -maxtablesize- -maxaddsub- -maxleftright- -maxext- -collectloads- are permanent
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The recovered addresses and case labels are saved to the XML stream.
|
/// The recovered addresses and case labels are encode to the stream.
|
||||||
/// If override information is present, this is also incorporated into the tag.
|
/// If override information is present, this is also incorporated into the element.
|
||||||
/// \param s is the stream to write to
|
/// \param encoder is the stream encoder
|
||||||
void JumpTable::saveXml(ostream &s) const
|
void JumpTable::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!isRecovered())
|
if (!isRecovered())
|
||||||
throw LowlevelError("Trying to save unrecovered jumptable");
|
throw LowlevelError("Trying to save unrecovered jumptable");
|
||||||
|
|
||||||
s << "<jumptable>\n";
|
encoder.openElement(ELEM_JUMPTABLE);
|
||||||
opaddress.saveXml(s);
|
opaddress.encode(encoder);
|
||||||
s << '\n';
|
|
||||||
for(int4 i=0;i<addresstable.size();++i) {
|
for(int4 i=0;i<addresstable.size();++i) {
|
||||||
s << "<dest";
|
encoder.openElement(ELEM_DEST);
|
||||||
AddrSpace *spc = addresstable[i].getSpace();
|
AddrSpace *spc = addresstable[i].getSpace();
|
||||||
uintb off = addresstable[i].getOffset();
|
uintb off = addresstable[i].getOffset();
|
||||||
if (spc != (AddrSpace *)0)
|
if (spc != (AddrSpace *)0)
|
||||||
spc->saveXmlAttributes(s,off);
|
spc->encodeAttributes(encoder,off);
|
||||||
if (i<label.size()) {
|
if (i<label.size()) {
|
||||||
if (label[i] != 0xBAD1ABE1)
|
if (label[i] != 0xBAD1ABE1)
|
||||||
a_v_u(s,"label",label[i]);
|
encoder.writeUnsignedInteger(ATTRIB_LABEL, label[i]);
|
||||||
}
|
}
|
||||||
s << "/>\n";
|
encoder.closeElement(ELEM_DEST);
|
||||||
}
|
}
|
||||||
if (!loadpoints.empty()) {
|
if (!loadpoints.empty()) {
|
||||||
for(int4 i=0;i<loadpoints.size();++i)
|
for(int4 i=0;i<loadpoints.size();++i)
|
||||||
loadpoints[i].saveXml(s);
|
loadpoints[i].encode(encoder);
|
||||||
}
|
}
|
||||||
if ((jmodel != (JumpModel *)0)&&(jmodel->isOverride()))
|
if ((jmodel != (JumpModel *)0)&&(jmodel->isOverride()))
|
||||||
jmodel->saveXml(s);
|
jmodel->encode(encoder);
|
||||||
s << "</jumptable>\n";
|
encoder.closeElement(ELEM_JUMPTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restore the addresses, \e case labels, and any override information from the tag.
|
/// Parse addresses, \e case labels, and any override information from a \<jumptable> element.
|
||||||
/// Other parts of the model and jump-table will still need to be recovered.
|
/// Other parts of the model and jump-table will still need to be recovered.
|
||||||
/// \param el is the root \<jumptable> tag to restore from
|
/// \param decoder is the stream decoder
|
||||||
void JumpTable::restoreXml(const Element *el)
|
void JumpTable::decode(Decoder &decoder)
|
||||||
|
|
||||||
{
|
{
|
||||||
const List &list( el->getChildren() );
|
uint4 elemId = decoder.openElement(ELEM_JUMPTABLE);
|
||||||
List::const_iterator iter = list.begin();
|
opaddress = Address::decode( decoder, glb);
|
||||||
opaddress = Address::restoreXml( *iter, glb);
|
|
||||||
bool missedlabel = false;
|
bool missedlabel = false;
|
||||||
++iter;
|
for(;;) {
|
||||||
while(iter != list.end()) {
|
uint4 subId = decoder.peekElement();
|
||||||
const Element *subel = *iter;
|
if (subId == 0) break;
|
||||||
if (subel->getName() == "dest") {
|
if (subId == ELEM_DEST) {
|
||||||
addresstable.push_back( Address::restoreXml( subel, glb) );
|
decoder.openElement();
|
||||||
int4 maxnum = subel->getNumAttributes();
|
bool foundlabel = false;
|
||||||
int4 i;
|
for(;;) {
|
||||||
for(i=0;i<maxnum;++i) {
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (subel->getAttributeName(i) == "label") break;
|
if (attribId == 0) break;
|
||||||
|
if (attribId == ATTRIB_LABEL) {
|
||||||
|
if (missedlabel)
|
||||||
|
throw LowlevelError("Jumptable entries are missing labels");
|
||||||
|
uintb lab = decoder.readUnsignedInteger();
|
||||||
|
label.push_back(lab);
|
||||||
|
foundlabel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i<maxnum) { // Found a label attribute
|
if (!foundlabel) // No label attribute
|
||||||
if (missedlabel)
|
|
||||||
throw LowlevelError("Jumptable entries are missing labels");
|
|
||||||
istringstream s1(subel->getAttributeValue(i));
|
|
||||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
|
||||||
uintb lab;
|
|
||||||
s1 >> lab;
|
|
||||||
label.push_back(lab);
|
|
||||||
}
|
|
||||||
else // 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) );
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "loadtable") {
|
else if (subId == ELEM_LOADTABLE) {
|
||||||
loadpoints.emplace_back();
|
loadpoints.emplace_back();
|
||||||
loadpoints.back().restoreXml(subel,glb);
|
loadpoints.back().decode(decoder,glb);
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "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->restoreXml(subel,glb);
|
jmodel->decode(decoder,glb);
|
||||||
}
|
}
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
|
|
||||||
if (label.size()!=0) {
|
if (label.size()!=0) {
|
||||||
while(label.size() < addresstable.size())
|
while(label.size() < addresstable.size())
|
||||||
|
|||||||
@@ -24,6 +24,17 @@
|
|||||||
|
|
||||||
class EmulateFunction;
|
class EmulateFunction;
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_LABEL; ///< Marshaling attribute "label"
|
||||||
|
extern AttributeId ATTRIB_NUM; ///< Marshaling attribute "num"
|
||||||
|
|
||||||
|
extern ElementId ELEM_BASICOVERRIDE; ///< Marshaling element \<basicoverride>
|
||||||
|
extern ElementId ELEM_DEST; ///< Marshaling element \<dest>
|
||||||
|
extern ElementId ELEM_JUMPTABLE; ///< Marshaling element \<jumptable>
|
||||||
|
extern ElementId ELEM_LOADTABLE; ///< Marshaling element \<loadtable>
|
||||||
|
extern ElementId ELEM_NORMADDR; ///< Marshaling element \<normaddr>
|
||||||
|
extern ElementId ELEM_NORMHASH; ///< Marshaling element \<normhash>
|
||||||
|
extern ElementId ELEM_STARTVAL; ///< Marshaling element \<startval>
|
||||||
|
|
||||||
/// \brief Exception thrown for a thunk mechanism that looks like a jump-table
|
/// \brief Exception thrown for a thunk mechanism that looks like a jump-table
|
||||||
struct JumptableThunkError : public LowlevelError {
|
struct JumptableThunkError : public LowlevelError {
|
||||||
JumptableThunkError(const string &s) : LowlevelError(s) {} ///< Construct with an explanatory string
|
JumptableThunkError(const string &s) : LowlevelError(s) {} ///< Construct with an explanatory string
|
||||||
@@ -44,12 +55,12 @@ class LoadTable {
|
|||||||
int4 size; ///< Size of table entry
|
int4 size; ///< Size of table entry
|
||||||
int4 num; ///< Number of entries in table;
|
int4 num; ///< Number of entries in table;
|
||||||
public:
|
public:
|
||||||
LoadTable(void) {} // Constructor for use with restoreXml
|
LoadTable(void) {} // Constructor for use with decode
|
||||||
LoadTable(const Address &ad,int4 sz) { addr = ad, size = sz; num = 1; } ///< Constructor for a single entry table
|
LoadTable(const Address &ad,int4 sz) { addr = ad, size = sz; num = 1; } ///< Constructor for a single entry table
|
||||||
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 saveXml(ostream &s) const; ///< Save a description of \b this as an \<loadtable> XML tag
|
void encode(Encoder &encoder) const; ///< Encode a description of \b this as an \<loadtable> element
|
||||||
void restoreXml(const Element *el,Architecture *glb); ///< Read in \b this table from a \<loadtable> XML description
|
void decode(Decoder &decoder,Architecture *glb); ///< 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
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -308,9 +319,9 @@ public:
|
|||||||
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable)=0;
|
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable)=0;
|
||||||
|
|
||||||
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 saveXml(ostream &s) const {} ///< Save this model as an XML tag
|
virtual void encode(Encoder &encoder) const {} ///< Encode this model to a stream
|
||||||
virtual void restoreXml(const Element *el,Architecture *glb) {} ///< Restore \b this model from an XML tag
|
virtual void decode(Decoder &decoder,Architecture *glb) {} ///< 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
|
||||||
@@ -451,8 +462,8 @@ public:
|
|||||||
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) { return true; }
|
virtual bool sanityCheck(Funcdata *fd,PcodeOp *indop,vector<Address> &addresstable) { return true; }
|
||||||
virtual JumpModel *clone(JumpTable *jt) const;
|
virtual JumpModel *clone(JumpTable *jt) const;
|
||||||
virtual void clear(void);
|
virtual void clear(void);
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void encode(Encoder &encoder) const;
|
||||||
virtual void restoreXml(const Element *el,Architecture *glb);
|
virtual void decode(Decoder &decoder,Architecture *glb);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JumpAssistOp;
|
class JumpAssistOp;
|
||||||
@@ -563,9 +574,9 @@ public:
|
|||||||
bool recoverLabels(Funcdata *fd); ///< Recover the case labels for \b this jump-table
|
bool recoverLabels(Funcdata *fd); ///< Recover the case labels for \b this jump-table
|
||||||
bool checkForMultistage(Funcdata *fd); ///< Check if this jump-table requires an additional recovery stage
|
bool checkForMultistage(Funcdata *fd); ///< Check if this jump-table requires an additional recovery stage
|
||||||
void clear(void); ///< Clear instance specific data for \b this jump-table
|
void clear(void); ///< Clear instance specific data for \b this jump-table
|
||||||
void saveXml(ostream &s) const; ///< Save \b this jump-table as a \<jumptable> XML tag
|
void encode(Encoder &encoder) const; ///< Encode \b this jump-table as a \<jumptable> element
|
||||||
void restoreXml(const Element *el); ///< Recover \b this jump-table from a \<jumptable> XML tag
|
void decode(Decoder &decoder); ///< Decode \b this jump-table from a \<jumptable> element
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \param op2 is the other IndexPair to compare with \b this
|
/// \param op2 is the other IndexPair to compare with \b this
|
||||||
/// \return \b true if \b this is ordered before the other IndexPair
|
/// \return \b true if \b this is ordered before the other IndexPair
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
void startDecompilerLibrary(const char *sleighhome)
|
void startDecompilerLibrary(const char *sleighhome)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
AttributeId::initialize();
|
||||||
|
ElementId::initialize();
|
||||||
CapabilityPoint::initializeAll();
|
CapabilityPoint::initializeAll();
|
||||||
ArchitectureCapability::sortCapabilities();
|
ArchitectureCapability::sortCapabilities();
|
||||||
|
|
||||||
@@ -28,6 +30,8 @@ void startDecompilerLibrary(const char *sleighhome)
|
|||||||
void startDecompilerLibrary(const vector<string> &extrapaths)
|
void startDecompilerLibrary(const vector<string> &extrapaths)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
AttributeId::initialize();
|
||||||
|
ElementId::initialize();
|
||||||
CapabilityPoint::initializeAll();
|
CapabilityPoint::initializeAll();
|
||||||
ArchitectureCapability::sortCapabilities();
|
ArchitectureCapability::sortCapabilities();
|
||||||
|
|
||||||
@@ -38,6 +42,8 @@ void startDecompilerLibrary(const vector<string> &extrapaths)
|
|||||||
void startDecompilerLibrary(const char *sleighhome,const vector<string> &extrapaths)
|
void startDecompilerLibrary(const char *sleighhome,const vector<string> &extrapaths)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
AttributeId::initialize();
|
||||||
|
ElementId::initialize();
|
||||||
CapabilityPoint::initializeAll();
|
CapabilityPoint::initializeAll();
|
||||||
ArchitectureCapability::sortCapabilities();
|
ArchitectureCapability::sortCapabilities();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,11 @@
|
|||||||
#include "loadimage_xml.hh"
|
#include "loadimage_xml.hh"
|
||||||
#include "translate.hh"
|
#include "translate.hh"
|
||||||
|
|
||||||
|
AttributeId ATTRIB_ARCH = AttributeId("arch",73);
|
||||||
|
|
||||||
|
ElementId ELEM_BINARYIMAGE = ElementId("binaryimage",108);
|
||||||
|
ElementId ELEM_BYTECHUNK = ElementId("bytechunk",109);
|
||||||
|
|
||||||
/// \param f is the (path to the) underlying XML file
|
/// \param f is the (path to the) underlying XML file
|
||||||
/// \param el is the parsed form of the file
|
/// \param el is the parsed form of the file
|
||||||
LoadImageXml::LoadImageXml(const string &f,const Element *el) : LoadImage(f)
|
LoadImageXml::LoadImageXml(const string &f,const Element *el) : LoadImage(f)
|
||||||
@@ -30,37 +35,42 @@ LoadImageXml::LoadImageXml(const string &f,const Element *el) : LoadImage(f)
|
|||||||
archtype = el->getAttributeValue("arch");
|
archtype = el->getAttributeValue("arch");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write out the byte chunks and symbols as XML tags
|
/// Encode the byte chunks and symbols as elements
|
||||||
/// \param s is the output stream
|
/// \param encoder is the stream encoder
|
||||||
void LoadImageXml::saveXml(ostream &s) const
|
void LoadImageXml::encode(Encoder &encoder) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "<binaryimage arch=\"" << archtype << "\">\n";
|
encoder.openElement(ELEM_BINARYIMAGE);
|
||||||
|
encoder.writeString(ATTRIB_ARCH, archtype);
|
||||||
|
|
||||||
map<Address,vector<uint1> >::const_iterator iter1;
|
map<Address,vector<uint1> >::const_iterator iter1;
|
||||||
for(iter1=chunk.begin();iter1!=chunk.end();++iter1) {
|
for(iter1=chunk.begin();iter1!=chunk.end();++iter1) {
|
||||||
const vector<uint1> &vec((*iter1).second);
|
const vector<uint1> &vec((*iter1).second);
|
||||||
if (vec.size() == 0) continue;
|
if (vec.size() == 0) continue;
|
||||||
s << " <bytechunk";
|
encoder.openElement(ELEM_BYTECHUNK);
|
||||||
(*iter1).first.getSpace()->saveXmlAttributes(s,(*iter1).first.getOffset());
|
(*iter1).first.getSpace()->encodeAttributes(encoder,(*iter1).first.getOffset());
|
||||||
if (readonlyset.find((*iter1).first) != readonlyset.end())
|
if (readonlyset.find((*iter1).first) != readonlyset.end())
|
||||||
s << " readonly=\"true\"";
|
encoder.writeBool(ATTRIB_READONLY, "true");
|
||||||
s << ">\n " << setfill('0');
|
ostringstream s;
|
||||||
|
s << '\n' << setfill('0');
|
||||||
for(int4 i=0;i<vec.size();++i) {
|
for(int4 i=0;i<vec.size();++i) {
|
||||||
s << hex << setw(2) << (int4)vec[i];
|
s << hex << setw(2) << (int4)vec[i];
|
||||||
if (i%20 == 19)
|
if (i%20 == 19)
|
||||||
s << "\n ";
|
s << '\n';
|
||||||
}
|
}
|
||||||
s << "\n </bytechunk>\n";
|
s << '\n';
|
||||||
|
encoder.writeString(ATTRIB_CONTENT, s.str());
|
||||||
|
encoder.closeElement(ELEM_BYTECHUNK);
|
||||||
}
|
}
|
||||||
|
|
||||||
map<Address,string>::const_iterator iter2;
|
map<Address,string>::const_iterator iter2;
|
||||||
for(iter2=addrtosymbol.begin();iter2!=addrtosymbol.end();++iter2) {
|
for(iter2=addrtosymbol.begin();iter2!=addrtosymbol.end();++iter2) {
|
||||||
s << " <symbol";
|
encoder.openElement(ELEM_SYMBOL);
|
||||||
(*iter2).first.getSpace()->saveXmlAttributes(s,(*iter2).first.getOffset());
|
(*iter2).first.getSpace()->encodeAttributes(encoder,(*iter2).first.getOffset());
|
||||||
s << " name=\"" << (*iter2).second << "\"/>\n";
|
encoder.writeString(ATTRIB_NAME, (*iter2).second);
|
||||||
|
encoder.closeElement(ELEM_SYMBOL);
|
||||||
}
|
}
|
||||||
s << "</binaryimage>\n";
|
encoder.closeElement(ELEM_BINARYIMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param m is for looking up address space
|
/// \param m is for looking up address space
|
||||||
@@ -71,35 +81,40 @@ void LoadImageXml::open(const AddrSpaceManager *m)
|
|||||||
uint4 sz; // unused size
|
uint4 sz; // unused size
|
||||||
|
|
||||||
// Read parsed xml file
|
// Read parsed xml file
|
||||||
const List &list(rootel->getChildren());
|
XmlDecode decoder(rootel);
|
||||||
List::const_iterator iter;
|
uint4 elemId = decoder.openElement(ELEM_BINARYIMAGE);
|
||||||
iter = list.begin();
|
for(;;) {
|
||||||
while(iter != list.end()) {
|
uint4 subId = decoder.openElement();
|
||||||
Element *subel = *iter++;
|
if (subId == 0) break;
|
||||||
if (subel->getName()=="symbol") {
|
if (subId==ELEM_SYMBOL) {
|
||||||
AddrSpace *base = (AddrSpace *)0;
|
AddrSpace *base = (AddrSpace *)0;
|
||||||
base = manage->getSpaceByName(subel->getAttributeValue("space"));
|
string spaceName = decoder.readString(ATTRIB_SPACE);
|
||||||
|
base = manage->getSpaceByName(spaceName);
|
||||||
if (base == (AddrSpace *)0)
|
if (base == (AddrSpace *)0)
|
||||||
throw LowlevelError("Unknown space name: "+subel->getAttributeValue("space"));
|
throw LowlevelError("Unknown space name: "+spaceName);
|
||||||
Address addr(base,base->restoreXmlAttributes(subel,sz));
|
Address addr(base,base->decodeAttributes(decoder,sz));
|
||||||
const string &nm(subel->getAttributeValue("name"));
|
string nm = decoder.readString(ATTRIB_NAME);
|
||||||
addrtosymbol[addr] = nm;
|
addrtosymbol[addr] = nm;
|
||||||
}
|
}
|
||||||
else if (subel->getName() == "bytechunk") {
|
else if (subId == ELEM_BYTECHUNK) {
|
||||||
AddrSpace *base = (AddrSpace *)0;
|
AddrSpace *base = (AddrSpace *)0;
|
||||||
base = manage->getSpaceByName(subel->getAttributeValue("space"));
|
string spaceName = decoder.readString(ATTRIB_SPACE);
|
||||||
|
base = manage->getSpaceByName(spaceName);
|
||||||
if (base == (AddrSpace *)0)
|
if (base == (AddrSpace *)0)
|
||||||
throw LowlevelError("Unknown space name: "+subel->getAttributeValue("space"));
|
throw LowlevelError("Unknown space name: "+spaceName);
|
||||||
Address addr(base,base->restoreXmlAttributes(subel,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] );
|
||||||
vec.clear();
|
vec.clear();
|
||||||
for(int4 i=0;i<subel->getNumAttributes();++i) {
|
decoder.rewindAttributes();
|
||||||
if (subel->getAttributeName(i) == "readonly")
|
for(;;) {
|
||||||
if (xml_readbool(subel->getAttributeValue(i)))
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) break;
|
||||||
|
if (attribId == ATTRIB_READONLY)
|
||||||
|
if (decoder.readBool())
|
||||||
readonlyset.insert(addr);
|
readonlyset.insert(addr);
|
||||||
}
|
}
|
||||||
istringstream is(subel->getContent());
|
istringstream is(decoder.readString(ATTRIB_CONTENT));
|
||||||
int4 val;
|
int4 val;
|
||||||
char c1,c2;
|
char c1,c2;
|
||||||
is >> ws;
|
is >> ws;
|
||||||
@@ -126,8 +141,10 @@ void LoadImageXml::open(const AddrSpaceManager *m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Unknown LoadImageXml tag: "+subel->getName());
|
throw LowlevelError("Unknown LoadImageXml tag");
|
||||||
|
decoder.closeElement(subId);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elemId);
|
||||||
pad();
|
pad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,11 @@
|
|||||||
|
|
||||||
#include "loadimage.hh"
|
#include "loadimage.hh"
|
||||||
|
|
||||||
|
extern AttributeId ATTRIB_ARCH; ///< Marshaling attribute "arch"
|
||||||
|
|
||||||
|
extern ElementId ELEM_BINARYIMAGE; ///< Marshaling element \<binaryimage>
|
||||||
|
extern ElementId ELEM_BYTECHUNK; ///< Marshaling element \<bytechunk>
|
||||||
|
|
||||||
/// \brief Implementation of the LoadImage interface using underlying data stored in an XML format
|
/// \brief Implementation of the LoadImage interface using underlying data stored in an XML format
|
||||||
///
|
///
|
||||||
/// The image data is stored in an XML file in a \<binaryimage> file.
|
/// The image data is stored in an XML file in a \<binaryimage> file.
|
||||||
@@ -38,7 +43,7 @@ public:
|
|||||||
LoadImageXml(const string &f,const Element *el); ///< Constructor
|
LoadImageXml(const string &f,const Element *el); ///< Constructor
|
||||||
void open(const AddrSpaceManager *m); ///< Read XML tags into the containers
|
void open(const AddrSpaceManager *m); ///< Read XML tags into the containers
|
||||||
void clear(void); ///< Clear out all the caches
|
void clear(void); ///< Clear out all the caches
|
||||||
void saveXml(ostream &s) const; ///< Save the image back out to an XML stream
|
void encode(Encoder &encoder) const; ///< Encode the image to a stream
|
||||||
virtual ~LoadImageXml(void) { clear(); }
|
virtual ~LoadImageXml(void) { clear(); }
|
||||||
virtual void loadFill(uint1 *ptr,int4 size,const Address &addr);
|
virtual void loadFill(uint1 *ptr,int4 size,const Address &addr);
|
||||||
virtual void openSymbols(void) const;
|
virtual void openSymbols(void) const;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user