mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-2358 Packed protocol for decompiler marshaling
This commit is contained in:
parent
6a1a649213
commit
79c3508f54
119 changed files with 4238 additions and 2207 deletions
|
@ -304,7 +304,7 @@ void Range::decode(Decoder &decoder)
|
|||
{
|
||||
uint4 elemId = decoder.openElement();
|
||||
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
||||
throw XmlError("Expecting <range> or <register> element");
|
||||
throw DecoderError("Expecting <range> or <register> element");
|
||||
decodeFromAttributes(decoder);
|
||||
decoder.closeElement(elemId);
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ void RangeProperties::decode(Decoder &decoder)
|
|||
{
|
||||
uint4 elemId = decoder.openElement();
|
||||
if (elemId != ELEM_RANGE && elemId != ELEM_REGISTER)
|
||||
throw XmlError("Expecting <range> or <register> element");
|
||||
throw DecoderError("Expecting <range> or <register> element");
|
||||
for(;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
|
|
|
@ -534,22 +534,25 @@ void Architecture::nameFunction(const Address &addr,string &name) const
|
|||
name = defname.str();
|
||||
}
|
||||
|
||||
/// This process sets up a "register relative" space for this architecture
|
||||
/// If the name is "stack", this space takes on the role of an "official" stack space
|
||||
/// Should only be called once during initialization
|
||||
/// \brief Create a new address space associated with a pointer register
|
||||
///
|
||||
/// This process sets up a \e register \e relative"space for this architecture.
|
||||
/// If indicated, this space takes on the role of the \e formal stack space.
|
||||
/// Should only be called once during initialization.
|
||||
/// \param basespace is the address space underlying the stack
|
||||
/// \param nm is the name of the new space
|
||||
/// \param ptrdata is the register location acting as a pointer into the new space
|
||||
/// \param truncSize is the (possibly truncated) size of the register that fits the space
|
||||
/// \param isreversejustified is \b true if small variables are justified opposite of endianness
|
||||
/// \param stackGrowth is \b true if a stack implemented in this space grows in the negative direction
|
||||
/// \param isFormal is the indicator for the \b formal stack space
|
||||
void Architecture::addSpacebase(AddrSpace *basespace,const string &nm,const VarnodeData &ptrdata,
|
||||
int4 truncSize,bool isreversejustified,bool stackGrowth)
|
||||
int4 truncSize,bool isreversejustified,bool stackGrowth,bool isFormal)
|
||||
|
||||
{
|
||||
int4 ind = numSpaces();
|
||||
|
||||
SpacebaseSpace *spc = new SpacebaseSpace(this,translate,nm,ind,truncSize,basespace,ptrdata.space->getDelay()+1);
|
||||
SpacebaseSpace *spc = new SpacebaseSpace(this,translate,nm,ind,truncSize,basespace,ptrdata.space->getDelay()+1,isFormal);
|
||||
if (isreversejustified)
|
||||
setReverseJustified(spc);
|
||||
insertSpace(spc);
|
||||
|
@ -1047,7 +1050,7 @@ void Architecture::decodeStackPointer(Decoder &decoder)
|
|||
truncSize = basespace->getAddrSize();
|
||||
}
|
||||
|
||||
addSpacebase(basespace,"stack",point,truncSize,isreversejustify,stackGrowth); // Create the "official" stackpointer
|
||||
addSpacebase(basespace,"stack",point,truncSize,isreversejustify,stackGrowth,true); // Create the "official" stackpointer
|
||||
}
|
||||
|
||||
/// Manually alter the dead-code delay for a specific address space,
|
||||
|
@ -1114,7 +1117,7 @@ void Architecture::decodeSpacebase(Decoder &decoder)
|
|||
AddrSpace *basespace = decoder.readSpace(ATTRIB_SPACE);
|
||||
decoder.closeElement(elemId);
|
||||
const VarnodeData &point(translate->getRegister(registerName));
|
||||
addSpacebase(basespace,nameString,point,point.size,false,false);
|
||||
addSpacebase(basespace,nameString,point,point.size,false,false,false);
|
||||
}
|
||||
|
||||
/// Configure memory based on a \<nohighptr> element. Mark specific address ranges
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
#endif
|
||||
protected:
|
||||
void addSpacebase(AddrSpace *basespace,const string &nm,const VarnodeData &ptrdata,
|
||||
int4 truncSize,bool isreversejustified,bool stackGrowth); ///< Create a new space and associated pointer
|
||||
int4 truncSize,bool isreversejustified,bool stackGrowth,bool isFormal);
|
||||
void addNoHighPtr(const Range &rng); ///< Add a new region where pointers do not exist
|
||||
|
||||
// Factory routines for building this architecture
|
||||
|
|
|
@ -40,7 +40,7 @@ void CommentDatabaseGhidra::fillCache(const Address &fad) const
|
|||
iter = cache.beginComment(fad);
|
||||
iterend = cache.endComment(fad);
|
||||
|
||||
XmlDecode decoder(ghidra);
|
||||
PackedDecode decoder(ghidra);
|
||||
if (ghidra->getComments(fad,commentfilter,decoder)) {
|
||||
cache.decode(decoder);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ void IfcLoadFile::execute(istream &s)
|
|||
else
|
||||
*status->optr << "Wrong tag type for experimental rules: "+root->getName() << endl;
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
*status->optr << err.explain << endl;
|
||||
*status->optr << "Skipping experimental rules" << endl;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void IfcLoadFile::execute(istream &s)
|
|||
bool iserror = false;
|
||||
try {
|
||||
dcp->conf->init(store);
|
||||
} catch(XmlError &err) {
|
||||
} catch(DecoderError &err) {
|
||||
errmsg = err.explain;
|
||||
iserror = true;
|
||||
} catch(LowlevelError &err) {
|
||||
|
@ -156,7 +156,7 @@ void IfcRestore::execute(istream &s)
|
|||
dcp->conf->restoreXml(store);
|
||||
} catch(LowlevelError &err) {
|
||||
throw IfaceExecutionError(err.explain);
|
||||
} catch(XmlError &err) {
|
||||
} catch(DecoderError &err) {
|
||||
throw IfaceExecutionError(err.explain);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,16 +32,16 @@ const CPoolRecord *ConstantPoolGhidra::getRecord(const vector<uintb> &refs) cons
|
|||
{
|
||||
const CPoolRecord *rec = cache.getRecord(refs);
|
||||
if (rec == (const CPoolRecord *)0) {
|
||||
XmlDecode decoder(ghidra);
|
||||
bool success;
|
||||
PackedDecode decoder(ghidra);
|
||||
try {
|
||||
success = ghidra->getCPoolRef(refs,decoder);
|
||||
}
|
||||
catch(JavaError &err) {
|
||||
throw LowlevelError("Error fetching constant pool record: " + err.explain);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
throw LowlevelError("Error in constant pool record xml: "+err.explain);
|
||||
catch(DecoderError &err) {
|
||||
throw LowlevelError("Error in constant pool record encoding: "+err.explain);
|
||||
}
|
||||
if (!success) {
|
||||
ostringstream s;
|
||||
|
|
|
@ -52,7 +52,7 @@ Scope *ScopeGhidra::reresolveScope(uint8 id) const
|
|||
if (cacheScope != (Scope *)0)
|
||||
return cacheScope; // Scope was previously cached
|
||||
|
||||
XmlDecode decoder(ghidra);
|
||||
PackedDecode decoder(ghidra);
|
||||
if (!ghidra->getNamespacePath(id,decoder))
|
||||
throw LowlevelError("Could not get namespace info");
|
||||
|
||||
|
@ -212,7 +212,7 @@ Symbol *ScopeGhidra::removeQuery(const Address &addr) const
|
|||
|
||||
// Have we queried this address before
|
||||
if (holes.inRange(addr,1)) return (Symbol *)0;
|
||||
XmlDecode decoder(ghidra);
|
||||
PackedDecode decoder(ghidra);
|
||||
if (ghidra->getMappedSymbolsXML(addr,decoder)) { // Query GHIDRA about this address
|
||||
sym = dump2Cache(decoder); // Add it to the cache
|
||||
}
|
||||
|
@ -349,9 +349,9 @@ Funcdata *ScopeGhidra::resolveExternalRefFunction(ExternRefSymbol *sym) const
|
|||
if (resFd == (Funcdata *)0) {
|
||||
// If the function isn't in cache, we use the special
|
||||
// getExternalRefXML interface to recover the external function
|
||||
PackedDecode decoder(ghidra);
|
||||
SymbolEntry *entry = sym->getFirstWholeMap();
|
||||
XmlDecode decoder(ghidra);
|
||||
if (ghidra->getExternalRefXML(entry->getAddr(),decoder)) {
|
||||
if (ghidra->getExternalRef(entry->getAddr(),decoder)) {
|
||||
FunctionSymbol *funcSym;
|
||||
// Make sure referenced function is cached
|
||||
funcSym = dynamic_cast<FunctionSymbol *>(dump2Cache(decoder));
|
||||
|
|
|
@ -4395,13 +4395,10 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb)
|
|||
}
|
||||
else if (attribId == ATTRIB_EXTRAPOP) {
|
||||
seenextrapop = true;
|
||||
string expopval = decoder.readString();
|
||||
if (expopval == "unknown")
|
||||
try {
|
||||
readextrapop = decoder.readSignedInteger();
|
||||
} catch(DecoderError &err) {
|
||||
readextrapop = ProtoModel::extrapop_unknown;
|
||||
else {
|
||||
istringstream i1(expopval);
|
||||
i1.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i1 >> readextrapop;
|
||||
}
|
||||
}
|
||||
else if (attribId == ATTRIB_MODELLOCK) {
|
||||
|
|
|
@ -23,6 +23,28 @@
|
|||
#include "cpool_ghidra.hh"
|
||||
#include "inject_ghidra.hh"
|
||||
|
||||
//AttributeId ATTRIB_BADDATA = AttributeId("baddata",145);
|
||||
|
||||
ElementId ELEM_COMMAND_ISNAMEUSED = ElementId("command_isnameused",239);
|
||||
ElementId ELEM_COMMAND_GETBYTES = ElementId("command_getbytes",240);
|
||||
ElementId ELEM_COMMAND_GETCALLFIXUP = ElementId("command_getcallfixup",241);
|
||||
ElementId ELEM_COMMAND_GETCALLMECH = ElementId("command_getcallmech",242);
|
||||
ElementId ELEM_COMMAND_GETCALLOTHERFIXUP = ElementId("command_getcallotherfixup",243);
|
||||
ElementId ELEM_COMMAND_GETCODELABEL = ElementId("command_getcodelabel",244);
|
||||
ElementId ELEM_COMMAND_GETCOMMENTS = ElementId("command_getcomments",245);
|
||||
ElementId ELEM_COMMAND_GETCPOOLREF = ElementId("command_getcpoolref",246);
|
||||
ElementId ELEM_COMMAND_GETDATATYPE = ElementId("command_getdatatype",247);
|
||||
ElementId ELEM_COMMAND_GETEXTERNALREF = ElementId("command_getexternalref",248);
|
||||
ElementId ELEM_COMMAND_GETMAPPEDSYMBOLS = ElementId("command_getmappedsymbols",249);
|
||||
ElementId ELEM_COMMAND_GETNAMESPACEPATH = ElementId("command_getnamespacepath",250);
|
||||
ElementId ELEM_COMMAND_GETPCODE = ElementId("command_getpcode",251);
|
||||
ElementId ELEM_COMMAND_GETPCODEEXECUTABLE = ElementId("command_getpcodeexecutable",252);
|
||||
ElementId ELEM_COMMAND_GETREGISTER = ElementId("command_getregister",253);
|
||||
ElementId ELEM_COMMAND_GETREGISTERNAME = ElementId("command_getregistername",254);
|
||||
ElementId ELEM_COMMAND_GETSTRINGDATA = ElementId("command_getstringdata",255);
|
||||
ElementId ELEM_COMMAND_GETTRACKEDREGISTERS = ElementId("command_gettrackedregisters",256);
|
||||
ElementId ELEM_COMMAND_GETUSEROPNAME = ElementId("command_getuseropname",257);
|
||||
|
||||
/// Catch the signal so the OS doesn't pop up a dialog
|
||||
/// \param sig is the OS signal (should always be SIGSEGV)
|
||||
void ArchitectureGhidra::segvHandler(int4 sig)
|
||||
|
@ -143,7 +165,7 @@ void ArchitectureGhidra::readStringStream(istream &s,string &res)
|
|||
/// \param s is the input stream from the client.
|
||||
/// \param decoder is the given stream decoder that will hold the result
|
||||
/// \return \b true if a response was received
|
||||
bool ArchitectureGhidra::readStream(istream &s,Decoder &decoder)
|
||||
bool ArchitectureGhidra::readStringStream(istream &s,Decoder &decoder)
|
||||
|
||||
{
|
||||
int4 type = readToAnyBurst(s);
|
||||
|
@ -159,38 +181,6 @@ bool ArchitectureGhidra::readStream(istream &s,Decoder &decoder)
|
|||
throw JavaError("alignment","Expecting string or end of query response");
|
||||
}
|
||||
|
||||
/// The method expects to see protocol markers indicating a string from the client,
|
||||
/// otherwise it throws and exception. An array size is encoded in the first 4 characters
|
||||
/// of the string. An array of this size is allocated and filled with the
|
||||
/// rest of the string.
|
||||
/// \param s is the input stream from the client
|
||||
/// \return the array of packed p-code data
|
||||
uint1 *ArchitectureGhidra::readPackedStream(istream &s)
|
||||
|
||||
{
|
||||
int4 type = readToAnyBurst(s);
|
||||
if (type == 14) {
|
||||
uint4 size = 0;
|
||||
int4 c = s.get();
|
||||
size ^= (c-0x20);
|
||||
c = s.get();
|
||||
size ^= ((c-0x20)<<6);
|
||||
c = s.get();
|
||||
size ^= ((c-0x20)<<12);
|
||||
c = s.get();
|
||||
size ^= ((c-0x20)<<18);
|
||||
uint1 *res = new uint1[ size ];
|
||||
s.read((char *)res,size);
|
||||
type = readToAnyBurst(s);
|
||||
if (type != 15)
|
||||
throw JavaError("alignment","Expecting packed string end");
|
||||
return res;
|
||||
}
|
||||
if ((type&1)==1)
|
||||
return (uint1 *)0;
|
||||
throw JavaError("alignment","Expecting string or end of query response");
|
||||
}
|
||||
|
||||
/// Write out a string with correct protocol markers
|
||||
/// \param s is the output stream to the client
|
||||
/// \param msg is the string to send
|
||||
|
@ -240,27 +230,13 @@ bool ArchitectureGhidra::readAll(istream &s,Decoder &decoder)
|
|||
|
||||
{
|
||||
readToResponse(s);
|
||||
if (readStream(s,decoder)) {
|
||||
if (readStringStream(s,decoder)) {
|
||||
readResponseEnd(s);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Read up to the beginning of a query response, check for an
|
||||
/// exception record, otherwise read in packed p-code op data.
|
||||
/// \param s is the input stream from the client
|
||||
/// \return the array of packed p-coded data
|
||||
uint1 *ArchitectureGhidra::readPackedAll(istream &s)
|
||||
|
||||
{
|
||||
readToResponse(s);
|
||||
uint1 *doc = readPackedStream(s);
|
||||
if (doc != (uint1 *)0)
|
||||
readResponseEnd(s);
|
||||
return doc;
|
||||
}
|
||||
|
||||
/// \brief Send an exception message to the Ghidra client
|
||||
///
|
||||
/// This generally called because of some sort of alignment issue in the
|
||||
|
@ -412,8 +388,12 @@ bool ArchitectureGhidra::getRegister(const string ®name,Decoder &decoder)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getRegister");
|
||||
writeStringStream(sout,regname);
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETREGISTER);
|
||||
encoder.writeString(ATTRIB_NAME, regname);
|
||||
encoder.closeElement(ELEM_COMMAND_GETREGISTER);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
||||
|
@ -429,11 +409,12 @@ string ArchitectureGhidra::getRegisterName(const VarnodeData &vndata)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getRegisterName");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
Address addr(vndata.space,vndata.offset);
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETREGISTERNAME);
|
||||
addr.encode(encoder,vndata.size);
|
||||
encoder.closeElement(ELEM_COMMAND_GETREGISTERNAME);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -456,10 +437,11 @@ bool ArchitectureGhidra::getTrackedRegisters(const Address &addr,Decoder &decode
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getTrackedRegisters");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETTRACKEDREGISTERS);
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETTRACKEDREGISTERS);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -475,9 +457,11 @@ string ArchitectureGhidra::getUserOpName(int4 index)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getUserOpName");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << dec << index;
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETUSEROPNAME);
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, index);
|
||||
encoder.closeElement(ELEM_COMMAND_GETUSEROPNAME);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -489,24 +473,24 @@ string ArchitectureGhidra::getUserOpName(int4 index)
|
|||
return res;
|
||||
}
|
||||
|
||||
/// Get a description of all the p-code ops for the instruction
|
||||
/// at the given address. The information is stored in a special
|
||||
/// compressed format. (See PcodeEmit::restorePackedOp)
|
||||
/// Get a description of all the p-code ops for the instruction at the given address.
|
||||
/// \param addr is the address of the instruction
|
||||
/// \return an array of the packed data
|
||||
uint1 *ArchitectureGhidra::getPcodePacked(const Address &addr)
|
||||
/// \param decoder is the stream decoder for holding the result
|
||||
/// \return true if the request is successful and ops are ready to be decoded
|
||||
bool ArchitectureGhidra::getPcode(const Address &addr,Decoder &decoder)
|
||||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getPacked");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETPCODE);
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETPCODE);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
||||
return readPackedAll(sin);
|
||||
return readAll(sin,decoder);
|
||||
}
|
||||
|
||||
/// The Ghidra client will pass back a \<symbol> element, \<function> element, or some
|
||||
|
@ -520,10 +504,11 @@ bool ArchitectureGhidra::getMappedSymbolsXML(const Address &addr,Decoder &decode
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getMappedSymbolsXML");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETMAPPEDSYMBOLS);
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETMAPPEDSYMBOLS);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -540,14 +525,15 @@ bool ArchitectureGhidra::getMappedSymbolsXML(const Address &addr,Decoder &decode
|
|||
/// \param addr is the given address
|
||||
/// \param decoder is the stream decoder that will hold the result
|
||||
/// \return \b true if the query completes successfully
|
||||
bool ArchitectureGhidra::getExternalRefXML(const Address &addr,Decoder &decoder)
|
||||
bool ArchitectureGhidra::getExternalRef(const Address &addr,Decoder &decoder)
|
||||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getExternalRefXML");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETEXTERNALREF);
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETEXTERNALREF);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -565,9 +551,11 @@ bool ArchitectureGhidra::getNamespacePath(uint8 id,Decoder &decoder)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getNamespacePath");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << hex << id;
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETNAMESPACEPATH);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||
encoder.closeElement(ELEM_COMMAND_GETNAMESPACEPATH);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -579,15 +567,13 @@ bool ArchitectureGhidra::isNameUsed(const string &nm,uint8 startId,uint8 stopId)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"isNameUsed");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << nm;
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << hex << startId;
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << hex << stopId;
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_ISNAMEUSED);
|
||||
encoder.writeString(ATTRIB_NAME, nm);
|
||||
encoder.writeUnsignedInteger(ATTRIB_FIRST, startId);
|
||||
encoder.writeUnsignedInteger(ATTRIB_LAST, stopId);
|
||||
encoder.closeElement(ELEM_COMMAND_ISNAMEUSED);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -606,10 +592,11 @@ string ArchitectureGhidra::getCodeLabel(const Address &addr)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getSymbol");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETCODELABEL);
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETCODELABEL);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -627,14 +614,16 @@ string ArchitectureGhidra::getCodeLabel(const Address &addr)
|
|||
/// \param id is a unique id associated with the data-type, pass 0 if unknown
|
||||
/// \param decoder is the stream decoder that will hold the result
|
||||
/// \return \b true if the query completed successfully
|
||||
bool ArchitectureGhidra::getType(const string &name,uint8 id,Decoder &decoder)
|
||||
bool ArchitectureGhidra::getDataType(const string &name,uint8 id,Decoder &decoder)
|
||||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getType");
|
||||
writeStringStream(sout,name);
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << dec << (int8)id; // Pass as a signed integer
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETDATATYPE);
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
encoder.writeSignedInteger(ATTRIB_ID, id);
|
||||
encoder.closeElement(ELEM_COMMAND_GETDATATYPE);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -654,13 +643,12 @@ bool ArchitectureGhidra::getComments(const Address &fad,uint4 flags,Decoder &dec
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getComments");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETCOMMENTS);
|
||||
encoder.writeUnsignedInteger(ATTRIB_TYPE, flags);
|
||||
fad.encode(encoder);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << dec << flags;
|
||||
encoder.closeElement(ELEM_COMMAND_GETCOMMENTS);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -678,10 +666,11 @@ void ArchitectureGhidra::getBytes(uint1 *buf,int4 size,const Address &inaddr)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getBytes");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETBYTES);
|
||||
inaddr.encode(encoder,size);
|
||||
encoder.closeElement(ELEM_COMMAND_GETBYTES);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -726,14 +715,14 @@ void ArchitectureGhidra::getStringData(vector<uint1> &buffer,const Address &addr
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getString");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
encoder.clear();
|
||||
addr.encode(encoder,maxBytes);
|
||||
sout.write("\000\000\001\017",4);
|
||||
writeStringStream(sout,ct->getName());
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << dec << (int8)ct->getId(); // Pass as a signed integer
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETSTRINGDATA);
|
||||
encoder.writeSignedInteger(ATTRIB_MAXSIZE, maxBytes);
|
||||
encoder.writeString(ATTRIB_TYPE,ct->getName());
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, ct->getId());
|
||||
addr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETSTRINGDATA);
|
||||
sout.write("\000\000\001\017",4);
|
||||
|
||||
sout.write("\000\000\001\005",4);
|
||||
|
@ -785,18 +774,33 @@ bool ArchitectureGhidra::getPcodeInject(const string &name,int4 type,const Injec
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
if (type == InjectPayload::CALLFIXUP_TYPE)
|
||||
writeStringStream(sout,"getCallFixup");
|
||||
else if (type == InjectPayload::CALLOTHERFIXUP_TYPE)
|
||||
writeStringStream(sout,"getCallotherFixup");
|
||||
else if (type == InjectPayload::CALLMECHANISM_TYPE)
|
||||
writeStringStream(sout,"getCallMech");
|
||||
else
|
||||
writeStringStream(sout,"getXPcode");
|
||||
writeStringStream(sout,name);
|
||||
sout.write("\000\000\001\016",4);
|
||||
encoder.clear();
|
||||
con.encode(encoder);
|
||||
PackedEncode encoder(sout);
|
||||
if (type == InjectPayload::CALLFIXUP_TYPE) {
|
||||
encoder.openElement(ELEM_COMMAND_GETCALLFIXUP);
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
con.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETCALLFIXUP);
|
||||
}
|
||||
else if (type == InjectPayload::CALLOTHERFIXUP_TYPE) {
|
||||
encoder.openElement(ELEM_COMMAND_GETCALLOTHERFIXUP);
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
con.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETCALLOTHERFIXUP);
|
||||
}
|
||||
else if (type == InjectPayload::CALLMECHANISM_TYPE) {
|
||||
encoder.openElement(ELEM_COMMAND_GETCALLMECH);
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
con.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETCALLMECH);
|
||||
}
|
||||
else {
|
||||
encoder.openElement(ELEM_COMMAND_GETPCODEEXECUTABLE);
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
con.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMMAND_GETPCODEEXECUTABLE);
|
||||
}
|
||||
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -814,12 +818,16 @@ bool ArchitectureGhidra::getCPoolRef(const vector<uintb> &refs,Decoder &decoder)
|
|||
|
||||
{
|
||||
sout.write("\000\000\001\004",4);
|
||||
writeStringStream(sout,"getCPoolRef");
|
||||
sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
sout << hex << refs[0];
|
||||
for(int4 i=1;i<refs.size();++i) {
|
||||
sout << ',' << hex << refs[i];
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_COMMAND_GETCPOOLREF);
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, refs.size());
|
||||
for(int4 i=0;i<refs.size();++i) {
|
||||
encoder.openElement(ELEM_VALUE);
|
||||
encoder.writeUnsignedInteger(ATTRIB_CONTENT, refs[i]);
|
||||
encoder.closeElement(ELEM_VALUE);
|
||||
}
|
||||
encoder.closeElement(ELEM_COMMAND_GETCPOOLREF);
|
||||
sout.write("\000\000\001\017",4);
|
||||
sout.write("\000\000\001\005",4);
|
||||
sout.flush();
|
||||
|
@ -827,24 +835,6 @@ bool ArchitectureGhidra::getCPoolRef(const vector<uintb> &refs,Decoder &decoder)
|
|||
return readAll(sin,decoder);
|
||||
}
|
||||
|
||||
// Document *ArchitectureGhidra::getScopeProperties(Scope *newscope)
|
||||
|
||||
// { // Query ghidra about the properties of a namespace scope
|
||||
// vector<string> namepath;
|
||||
// newscope->getNameSegments(namepath);
|
||||
// sout.write("\000\000\001\004",4);
|
||||
// writeStringStream(sout,"getScope");
|
||||
// sout.write("\000\000\001\016",4); // Beginning of string header
|
||||
// sout << "<name>\n";
|
||||
// for(int4 i=0;i<namepath.size();++i)
|
||||
// sout << "<val>" << namepath[i] << "</val>\n";
|
||||
// sout << "</name>\n";
|
||||
// sout.write("\000\000\001\017",4);
|
||||
// sout.write("\000\000\001\005",4);
|
||||
// sout.flush();
|
||||
// return readXMLAll(sin);
|
||||
// }
|
||||
|
||||
void ArchitectureGhidra::printMessage(const string &message) const
|
||||
|
||||
{
|
||||
|
@ -861,7 +851,7 @@ void ArchitectureGhidra::printMessage(const string &message) const
|
|||
/// \param o is the output stream to the Ghidra client
|
||||
ArchitectureGhidra::ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,
|
||||
const string &corespec,istream &i,ostream &o)
|
||||
: Architecture(), sin(i), sout(o), encoder(sout)
|
||||
: Architecture(), sin(i), sout(o)
|
||||
|
||||
{
|
||||
print->setMarkup(true);
|
||||
|
|
|
@ -21,6 +21,26 @@
|
|||
|
||||
#include "architecture.hh"
|
||||
|
||||
extern ElementId ELEM_COMMAND_ISNAMEUSED; ///< Marshaling element \<command_isnameused>
|
||||
extern ElementId ELEM_COMMAND_GETBYTES; ///< Marshaling element \<command_getbytes>
|
||||
extern ElementId ELEM_COMMAND_GETCALLFIXUP; ///< Marshaling element \<command_getcallfixup>
|
||||
extern ElementId ELEM_COMMAND_GETCALLMECH; ///< Marshaling element \<command_getcallmech>
|
||||
extern ElementId ELEM_COMMAND_GETCALLOTHERFIXUP; ///< Marshaling element \<command_getcallotherfixup>
|
||||
extern ElementId ELEM_COMMAND_GETCODELABEL; ///< Marshaling element \<command_getcodelabel>
|
||||
extern ElementId ELEM_COMMAND_GETCOMMENTS; ///< Marshaling element \<command_getcomments>
|
||||
extern ElementId ELEM_COMMAND_GETCPOOLREF; ///< Marshaling element \<command_getcpoolref>
|
||||
extern ElementId ELEM_COMMAND_GETDATATYPE; ///< Marshaling element \<command_datatype>
|
||||
extern ElementId ELEM_COMMAND_GETEXTERNALREF; ///< Marshaling element \<command_getexternalref>
|
||||
extern ElementId ELEM_COMMAND_GETMAPPEDSYMBOLS; ///< Marshaling element \<command_getmappedsymbols>
|
||||
extern ElementId ELEM_COMMAND_GETNAMESPACEPATH; ///< Marshaling element \<command_getnamespacepath>
|
||||
extern ElementId ELEM_COMMAND_GETPCODE; ///< Marshaling element \<command_getpcode>
|
||||
extern ElementId ELEM_COMMAND_GETPCODEEXECUTABLE; ///< Marshaling element \<command_getpcodeexecutable>
|
||||
extern ElementId ELEM_COMMAND_GETREGISTER; ///< Marshaling element \<command_getregister>
|
||||
extern ElementId ELEM_COMMAND_GETREGISTERNAME; ///< Marshaling element \<command_getregistername>
|
||||
extern ElementId ELEM_COMMAND_GETSTRINGDATA; ///< Marshaling element \<command_getstringdata>
|
||||
extern ElementId ELEM_COMMAND_GETTRACKEDREGISTERS; ///< Marshaling element \<command_gettrackedregisters>
|
||||
extern ElementId ELEM_COMMAND_GETUSEROPNAME; ///< Marshaling element \<command_getuseropname>
|
||||
|
||||
/// \brief Exception that mirrors exceptions thrown by the Ghidra client
|
||||
///
|
||||
/// If the Ghidra client throws an exception while trying to answer a query,
|
||||
|
@ -60,7 +80,6 @@ struct JavaError : public LowlevelError {
|
|||
class ArchitectureGhidra : public Architecture {
|
||||
istream &sin; ///< Input 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
|
||||
string pspecxml; ///< XML pspec passed from Ghidra
|
||||
string cspecxml; ///< XML cspec passed from Ghidra
|
||||
|
@ -91,13 +110,13 @@ public:
|
|||
string getRegisterName(const VarnodeData &vndata); ///< Retrieve a register name given its storage location
|
||||
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
|
||||
uint1 *getPcodePacked(const Address &addr); ///< Get p-code for a single instruction
|
||||
bool getPcode(const Address &addr,Decoder &decoder); ///< Get p-code for a single instruction
|
||||
bool getMappedSymbolsXML(const Address &addr,Decoder &decoder); ///< Get symbols associated with the given address
|
||||
bool getExternalRefXML(const Address &addr,Decoder &decoder); ///< Retrieve a description of an external function
|
||||
bool getExternalRef(const Address &addr,Decoder &decoder); ///< Retrieve a description of an external function
|
||||
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
|
||||
string getCodeLabel(const Address &addr); ///< Retrieve a label at the given address
|
||||
bool getType(const string &name,uint8 id,Decoder &decoder); ///< Retrieve a data-type description for the given name and id
|
||||
bool getDataType(const string &name,uint8 id,Decoder &decoder); ///< Retrieve a data-type description for the given name and id
|
||||
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
|
||||
bool getPcodeInject(const string &name,int4 type,const InjectContext &con,Decoder &decoder);
|
||||
|
@ -136,13 +155,11 @@ public:
|
|||
static int4 readToAnyBurst(istream &s); ///< Read the next message protocol marker
|
||||
static bool readBoolStream(istream &s); ///< Read a boolean value from the client
|
||||
static void readStringStream(istream &s,string &res); ///< Receive a string from the client
|
||||
static bool readStringStream(istream &s,Decoder &decoder); ///< Receive an encoded string from 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 readResponseEnd(istream &s); ///< Read the ending query response protocol marker
|
||||
static bool readAll(istream &s,Decoder &decoder); ///< Read a whole response as an XML document
|
||||
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 *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 bool isDynamicSymbolName(const string &nm); ///< Check if name is of form FUN_.. or DAT_..
|
||||
|
|
|
@ -19,7 +19,7 @@ const TrackedSet &ContextGhidra::getTrackedSet(const Address &addr) const
|
|||
|
||||
{
|
||||
cache.clear();
|
||||
XmlDecode decoder(glb);
|
||||
PackedDecode decoder(glb);
|
||||
glb->getTrackedRegisters(addr,decoder);
|
||||
|
||||
uint4 elemId = decoder.openElement(ELEM_TRACKED_POINTSET);
|
||||
|
|
|
@ -126,9 +126,9 @@ int4 GhidraCommand::doit(void)
|
|||
throw JavaError("alignment","Missing end of command");
|
||||
rawAction();
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
string errmsg;
|
||||
errmsg = "XML processing error: " + err.explain;
|
||||
errmsg = "Marshaling error: " + err.explain;
|
||||
ghidra->printMessage( errmsg );
|
||||
}
|
||||
catch(JavaError &err) {
|
||||
|
@ -277,8 +277,8 @@ void DecompileAt::loadParameters(void)
|
|||
|
||||
{
|
||||
GhidraCommand::loadParameters();
|
||||
XmlDecode decoder(ghidra);
|
||||
ArchitectureGhidra::readStream(sin,decoder); // Read encoded address directly from in stream
|
||||
PackedDecode decoder(ghidra);
|
||||
ArchitectureGhidra::readStringStream(sin,decoder); // Read encoded address directly from in stream
|
||||
addr = Address::decode(decoder); // Decode for functions address
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ void DecompileAt::rawAction(void)
|
|||
sout.write("\000\000\001\016",4);
|
||||
|
||||
if (fd->isProcComplete()) {
|
||||
XmlEncode encoder(sout);
|
||||
PackedEncode encoder(sout);
|
||||
encoder.openElement(ELEM_DOC);
|
||||
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
||||
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
||||
|
@ -331,8 +331,8 @@ void StructureGraph::loadParameters(void)
|
|||
{
|
||||
GhidraCommand::loadParameters();
|
||||
|
||||
XmlDecode decoder(ghidra);
|
||||
ArchitectureGhidra::readStream(sin,decoder);
|
||||
PackedDecode decoder(ghidra);
|
||||
ArchitectureGhidra::readStringStream(sin,decoder);
|
||||
ingraph.decode(decoder);
|
||||
}
|
||||
|
||||
|
@ -351,7 +351,7 @@ void StructureGraph::rawAction(void)
|
|||
resultgraph.orderBlocks();
|
||||
|
||||
sout.write("\000\000\001\016",4);
|
||||
XmlEncode encoder(sout);
|
||||
PackedEncode encoder(sout);
|
||||
resultgraph.encode(encoder);
|
||||
sout.write("\000\000\001\017",4);
|
||||
ingraph.clear();
|
||||
|
@ -411,8 +411,17 @@ void SetOptions::loadParameters(void)
|
|||
|
||||
{
|
||||
GhidraCommand::loadParameters();
|
||||
optionsListTag.clear();
|
||||
ArchitectureGhidra::readStringStream(sin, optionsListTag);
|
||||
if (decoder != (Decoder *)0)
|
||||
delete decoder;
|
||||
decoder = new PackedDecode(ghidra);
|
||||
ArchitectureGhidra::readStringStream(sin, *decoder);
|
||||
}
|
||||
|
||||
SetOptions::~SetOptions(void)
|
||||
|
||||
{
|
||||
if (decoder != (Decoder *)0)
|
||||
delete decoder;
|
||||
}
|
||||
|
||||
void SetOptions::rawAction(void)
|
||||
|
@ -421,12 +430,9 @@ void SetOptions::rawAction(void)
|
|||
res = false;
|
||||
|
||||
ghidra->resetDefaults();
|
||||
DocumentStorage storage;
|
||||
istringstream s(optionsListTag);
|
||||
Document *doc = storage.parseDocument(s);
|
||||
XmlDecode decoder(ghidra,doc->getRoot());
|
||||
ghidra->options->decode(decoder);
|
||||
optionsListTag.clear();
|
||||
ghidra->options->decode(*decoder);
|
||||
delete decoder;
|
||||
decoder = (Decoder *)0;
|
||||
res = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -217,16 +217,18 @@ public:
|
|||
/// The decompiler supports configuration of a variety of named options that affect
|
||||
/// everything from how code is transformed to how it is displayed (See ArchOption).
|
||||
/// The command expects 2 string parameters: the encoded integer id of the program,
|
||||
/// and an XML document containing an \<optionslist> tag. The \<optionslist> tag
|
||||
/// contains one child tag for each option to be configured.
|
||||
/// and an encoded document containing an \<optionslist> element. The \<optionslist> element
|
||||
/// contains one child element for each option to be configured.
|
||||
/// The command returns a single character message, 't' or 'f', indicating whether the
|
||||
/// configuration succeeded.
|
||||
class SetOptions : public GhidraCommand {
|
||||
string optionsListTag; ///< The <optionslist> XML tag
|
||||
Decoder *decoder; ///< The \<optionslist> decoder
|
||||
virtual void loadParameters(void);
|
||||
virtual void sendResult(void);
|
||||
public:
|
||||
bool res; ///< Set to \b true if the option change succeeded
|
||||
SetOptions(void) { decoder = (Decoder *)0; res = false; } ///< Constructor
|
||||
virtual ~SetOptions(void);
|
||||
virtual void rawAction(void);
|
||||
};
|
||||
|
||||
|
|
|
@ -46,14 +46,14 @@ const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
|||
map<string,VarnodeData>::const_iterator iter = nm2addr.find(nm);
|
||||
if (iter != nm2addr.end())
|
||||
return (*iter).second;
|
||||
XmlDecode decoder(glb);
|
||||
PackedDecode decoder(glb);
|
||||
try {
|
||||
if (!glb->getRegister(nm,decoder)) // Ask Ghidra client about the register
|
||||
throw LowlevelError("No register named "+nm);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
ostringstream errmsg;
|
||||
errmsg << "Error parsing XML response for query of register: " << nm;
|
||||
errmsg << "Error decoding response for query of register: " << nm;
|
||||
errmsg << " -- " << err.explain;
|
||||
throw LowlevelError(errmsg.str());
|
||||
}
|
||||
|
@ -100,9 +100,10 @@ int4 GhidraTranslate::oneInstruction(PcodeEmit &emit,const Address &baseaddr) co
|
|||
|
||||
{
|
||||
int4 offset;
|
||||
uint1 *doc;
|
||||
PackedDecode decoder(glb);
|
||||
bool success;
|
||||
try {
|
||||
doc = glb->getPcodePacked(baseaddr); // Request p-code for one instruction
|
||||
success = glb->getPcode(baseaddr,decoder); // Request p-code for one instruction
|
||||
}
|
||||
catch(JavaError &err) {
|
||||
ostringstream s;
|
||||
|
@ -110,34 +111,26 @@ int4 GhidraTranslate::oneInstruction(PcodeEmit &emit,const Address &baseaddr) co
|
|||
baseaddr.printRaw(s);
|
||||
throw LowlevelError(s.str());
|
||||
}
|
||||
if (doc == (uint1 *)0) {
|
||||
if (!success) {
|
||||
ostringstream s;
|
||||
s << "No pcode could be generated at address: " << baseaddr.getShortcut();
|
||||
baseaddr.printRaw(s);
|
||||
throw BadDataError(s.str());
|
||||
}
|
||||
|
||||
uintb val;
|
||||
const uint1 *ptr = PcodeEmit::unpackOffset(doc+1,val);
|
||||
offset = (int4)val;
|
||||
|
||||
if (*doc == PcodeEmit::unimpl_tag) {
|
||||
int4 el = decoder.openElement();
|
||||
offset = decoder.readSignedInteger(ATTRIB_OFFSET);
|
||||
if (el == ELEM_UNIMPL) {
|
||||
ostringstream s;
|
||||
s << "Instruction not implemented in pcode:\n ";
|
||||
baseaddr.printRaw(s);
|
||||
delete [] doc;
|
||||
throw UnimplError(s.str(),offset);
|
||||
}
|
||||
|
||||
int4 spcindex = (int4)(*ptr++ - 0x20);
|
||||
AddrSpace *spc = getSpace(spcindex);
|
||||
uintb instoffset;
|
||||
ptr = PcodeEmit::unpackOffset(ptr,instoffset);
|
||||
Address pc(spc,instoffset);
|
||||
Address pc = Address::decode(decoder);
|
||||
|
||||
while(*ptr == PcodeEmit::op_tag)
|
||||
ptr = emit.restorePackedOp(pc,ptr,this);
|
||||
delete [] doc;
|
||||
while(decoder.peekElement() != 0)
|
||||
emit.decodeOp(pc,decoder);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1872,7 +1872,7 @@ void Heritage::splitJoinLevel(vector<Varnode *> &lastcombo,vector<Varnode *> &ne
|
|||
int4 sizeaccum = 0;
|
||||
int4 j;
|
||||
for(j=recnum;j<numpieces;++j) {
|
||||
sizeaccum += joinrec->getPiece(recnum).size;
|
||||
sizeaccum += joinrec->getPiece(j).size;
|
||||
if (sizeaccum == curvn->getSize()) {
|
||||
j += 1;
|
||||
break;
|
||||
|
|
|
@ -3472,8 +3472,8 @@ void execute(IfaceStatus *status,IfaceDecompData *dcp)
|
|||
*status->optr << "Low-level ERROR: " << err.explain << endl;
|
||||
dcp->abortFunction(*status->optr);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
*status->optr << "XML ERROR: " << err.explain << endl;
|
||||
catch(DecoderError &err) {
|
||||
*status->optr << "Decoding ERROR: " << err.explain << endl;
|
||||
dcp->abortFunction(*status->optr);
|
||||
}
|
||||
status->evaluateError();
|
||||
|
|
|
@ -48,7 +48,7 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||
|
||||
{
|
||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||
XmlDecode decoder(ghidra);
|
||||
PackedDecode decoder(ghidra);
|
||||
try {
|
||||
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||
|
@ -56,12 +56,13 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||
catch(JavaError &err) {
|
||||
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
||||
}
|
||||
uint4 elemId = decoder.openElement();
|
||||
Address addr = Address::decode(decoder);
|
||||
while(decoder.peekElement() != 0)
|
||||
emit.decodeOp(decoder);
|
||||
emit.decodeOp(addr,decoder);
|
||||
decoder.closeElement(elemId);
|
||||
}
|
||||
|
||||
|
@ -121,7 +122,7 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||
|
||||
{
|
||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)con.glb;
|
||||
XmlDecode decoder(ghidra);
|
||||
PackedDecode decoder(ghidra);
|
||||
try {
|
||||
if (!ghidra->getPcodeInject(name,type,con,decoder))
|
||||
throw LowlevelError("Could not retrieve pcode snippet: "+name);
|
||||
|
@ -129,12 +130,13 @@ void ExecutablePcodeGhidra::inject(InjectContext &con,PcodeEmit &emit) const
|
|||
catch(JavaError &err) {
|
||||
throw LowlevelError("Error getting pcode snippet: " + err.explain);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
throw LowlevelError("Error in pcode snippet xml: "+err.explain);
|
||||
}
|
||||
uint4 elemId = decoder.openElement();
|
||||
Address addr = Address::decode(decoder);
|
||||
while(decoder.peekElement() != 0)
|
||||
emit.decodeOp(decoder);
|
||||
emit.decodeOp(addr,decoder);
|
||||
decoder.closeElement(elemId);
|
||||
}
|
||||
|
||||
|
@ -144,7 +146,7 @@ void ExecutablePcodeGhidra::decode(Decoder &decoder)
|
|||
uint4 elemId = decoder.openElement();
|
||||
if (elemId != ELEM_PCODE && elemId != ELEM_CASE_PCODE && elemId != ELEM_ADDR_PCODE &&
|
||||
elemId != ELEM_DEFAULT_PCODE && elemId != ELEM_SIZE_PCODE)
|
||||
throw XmlError("Expecting <pcode>, <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||
throw DecoderError("Expecting <pcode>, <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||
decodePayloadAttributes(decoder);
|
||||
decodePayloadParams(decoder); // Parse the parameters
|
||||
decoder.closeElementSkipping(elemId); // But skip rest of body
|
||||
|
|
|
@ -233,7 +233,7 @@ void ExecutablePcodeSleigh::decode(Decoder &decoder)
|
|||
uint4 elemId = decoder.openElement();
|
||||
if (elemId != ELEM_PCODE && elemId != ELEM_CASE_PCODE &&
|
||||
elemId != ELEM_ADDR_PCODE && elemId != ELEM_DEFAULT_PCODE && elemId != ELEM_SIZE_PCODE)
|
||||
throw XmlError("Expecting <pcode>, <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||
throw DecoderError("Expecting <pcode>, <case_pcode>, <addr_pcode>, <default_pcode>, or <size_pcode>");
|
||||
decodePayloadAttributes(decoder);
|
||||
decodePayloadParams(decoder);
|
||||
uint4 subId = decoder.openElement(ELEM_BODY);
|
||||
|
@ -269,8 +269,8 @@ void InjectPayloadDynamic::decodeEntry(Decoder &decoder)
|
|||
delete (*iter).second; // Delete any preexisting document
|
||||
addrMap[addr] = doc;
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
throw LowlevelError("Error in dynamic payload XML");
|
||||
catch(DecoderError &err) {
|
||||
throw LowlevelError("Error decoding dynamic payload");
|
||||
}
|
||||
decoder.closeElement(subId);
|
||||
}
|
||||
|
@ -284,8 +284,9 @@ void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
|
|||
const Element *el = (*eiter).second->getRoot();
|
||||
XmlDecode decoder(glb->translate,el);
|
||||
uint4 rootId = decoder.openElement(ELEM_INST);
|
||||
Address addr = Address::decode(decoder);
|
||||
while(decoder.peekElement() != 0)
|
||||
emit.decodeOp(decoder);
|
||||
emit.decodeOp(addr,decoder);
|
||||
decoder.closeElement(rootId);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
#include "marshal.hh"
|
||||
#include "translate.hh"
|
||||
|
||||
using namespace PackedFormat;
|
||||
|
||||
unordered_map<string,uint4> AttributeId::lookupAttributeId;
|
||||
|
||||
const int4 PackedDecode::BUFFER_SIZE = 1024;
|
||||
|
||||
/// Access static vector of AttributeId objects that are registered during static initialization
|
||||
/// The list itself is created once on the first call to this method.
|
||||
/// \return a reference to the vector
|
||||
|
@ -48,7 +52,7 @@ void AttributeId::initialize(void)
|
|||
AttributeId *attrib = thelist[i];
|
||||
#ifdef CPUI_DEBUG
|
||||
if (lookupAttributeId.find(attrib->name) != lookupAttributeId.end())
|
||||
throw XmlError(attrib->name + " attribute registered more than once");
|
||||
throw DecoderError(attrib->name + " attribute registered more than once");
|
||||
#endif
|
||||
lookupAttributeId[attrib->name] = attrib->id;
|
||||
}
|
||||
|
@ -88,7 +92,7 @@ void ElementId::initialize(void)
|
|||
ElementId *elem = thelist[i];
|
||||
#ifdef CPUI_DEBUG
|
||||
if (lookupElementId.find(elem->name) != lookupElementId.end())
|
||||
throw XmlError(elem->name + " element registered more than once");
|
||||
throw DecoderError(elem->name + " element registered more than once");
|
||||
#endif
|
||||
lookupElementId[elem->name] = elem->id;
|
||||
}
|
||||
|
@ -103,16 +107,6 @@ XmlDecode::~XmlDecode(void)
|
|||
delete document;
|
||||
}
|
||||
|
||||
void XmlDecode::clear(void)
|
||||
|
||||
{
|
||||
if (document != (Document *)0)
|
||||
delete document;
|
||||
document = (Document *)0;
|
||||
rootElement = (const Element *)0;
|
||||
attributeIndex = -1;
|
||||
}
|
||||
|
||||
void XmlDecode::ingestStream(istream &s)
|
||||
|
||||
{
|
||||
|
@ -169,7 +163,7 @@ uint4 XmlDecode::openElement(const ElementId &elemId)
|
|||
const Element *el;
|
||||
if (elStack.empty()) {
|
||||
if (rootElement == (const Element *)0)
|
||||
throw XmlError("Expecting <" + elemId.getName() + "> but reached end of document");
|
||||
throw DecoderError("Expecting <" + elemId.getName() + "> but reached end of document");
|
||||
el = rootElement;
|
||||
rootElement = (const Element *)0; // Only open document once
|
||||
}
|
||||
|
@ -181,10 +175,10 @@ uint4 XmlDecode::openElement(const ElementId &elemId)
|
|||
iterStack.back() = ++iter;
|
||||
}
|
||||
else
|
||||
throw XmlError("Expecting <" + elemId.getName() + "> but no remaining children in current element");
|
||||
throw DecoderError("Expecting <" + elemId.getName() + "> but no remaining children in current element");
|
||||
}
|
||||
if (el->getName() != elemId.getName())
|
||||
throw XmlError("Expecting <" + elemId.getName() + "> but got <" + el->getName() + ">");
|
||||
throw DecoderError("Expecting <" + elemId.getName() + "> but got <" + el->getName() + ">");
|
||||
elStack.push_back(el);
|
||||
iterStack.push_back(el->getChildren().begin());
|
||||
attributeIndex = -1;
|
||||
|
@ -197,9 +191,9 @@ void XmlDecode::closeElement(uint4 id)
|
|||
#ifdef CPUI_DEBUG
|
||||
const Element *el = elStack.back();
|
||||
if (iterStack.back() != el->getChildren().end())
|
||||
throw XmlError("Closing element <" + el->getName() + "> with additional children");
|
||||
throw DecoderError("Closing element <" + el->getName() + "> with additional children");
|
||||
if (ElementId::find(el->getName()) != id)
|
||||
throw XmlError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
iterStack.pop_back();
|
||||
|
@ -212,7 +206,7 @@ void XmlDecode::closeElementSkipping(uint4 id)
|
|||
#ifdef CPUI_DEBUG
|
||||
const Element *el = elStack.back();
|
||||
if (ElementId::find(el->getName()) != id)
|
||||
throw XmlError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
iterStack.pop_back();
|
||||
|
@ -251,7 +245,7 @@ int4 XmlDecode::findMatchingAttribute(const Element *el,const string &attribName
|
|||
if (el->getAttributeName(i) == attribName)
|
||||
return i;
|
||||
}
|
||||
throw XmlError("Attribute missing: " + attribName);
|
||||
throw DecoderError("Attribute missing: " + attribName);
|
||||
}
|
||||
|
||||
bool XmlDecode::readBool(void)
|
||||
|
@ -355,7 +349,7 @@ AddrSpace *XmlDecode::readSpace(void)
|
|||
string nm = el->getAttributeValue(attributeIndex);
|
||||
AddrSpace *res = spcManager->getSpaceByName(nm);
|
||||
if (res == (AddrSpace *)0)
|
||||
throw XmlError("Unknown address space name: "+nm);
|
||||
throw DecoderError("Unknown address space name: "+nm);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -373,7 +367,7 @@ AddrSpace *XmlDecode::readSpace(const AttributeId &attribId)
|
|||
}
|
||||
AddrSpace *res = spcManager->getSpaceByName(nm);
|
||||
if (res == (AddrSpace *)0)
|
||||
throw XmlError("Unknown address space name: "+nm);
|
||||
throw DecoderError("Unknown address space name: "+nm);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -472,6 +466,543 @@ void XmlEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
|
|||
a_v(outStream,attribId.getName(),spc->getName());
|
||||
}
|
||||
|
||||
/// The integer is encoded, 7-bits per byte, starting with the most significant 7-bits.
|
||||
/// The integer is decode from the \e current position, and the position is advanced.
|
||||
/// \param len is the number of bytes to extract
|
||||
uint8 PackedDecode::readInteger(int4 len)
|
||||
|
||||
{
|
||||
uint8 res = 0;
|
||||
while(len > 0) {
|
||||
res <<= RAWDATA_BITSPERBYTE;
|
||||
res |= (getNextByte(curPos) & RAWDATA_MASK);
|
||||
len -= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// The \e current position is reset to the start of the current open element. Attributes are scanned
|
||||
/// and skipped until the attribute matching the given id is found. The \e current position is set to the
|
||||
/// start of the matching attribute, in preparation for one of the read*() methods.
|
||||
/// If the id is not found an exception is thrown.
|
||||
/// \param attribId is the attribute id to scan for.
|
||||
void PackedDecode::findMatchingAttribute(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
curPos = startPos;
|
||||
for(;;) {
|
||||
uint1 header1 = getByte(curPos);
|
||||
if ((header1 & HEADER_MASK) != ATTRIBUTE) break;
|
||||
uint4 id = header1 & ELEMENTID_MASK;
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0) {
|
||||
id <<= RAWDATA_BITSPERBYTE;
|
||||
id |= (getBytePlus1(curPos) & RAWDATA_MASK);
|
||||
}
|
||||
if (attribId.getId() == id)
|
||||
return; // Found it
|
||||
skipAttribute();
|
||||
}
|
||||
throw DecoderError("Attribute " + attribId.getName() + " is not present");
|
||||
}
|
||||
|
||||
/// The attribute at the \e current position is scanned enough to determine its length, and the position
|
||||
/// is advanced to the following byte.
|
||||
void PackedDecode::skipAttribute(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos); // Attribute header
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0)
|
||||
getNextByte(curPos); // Extra byte for extended id
|
||||
uint1 typeByte = getNextByte(curPos); // Type (and length) byte
|
||||
uint1 attribType = typeByte >> TYPECODE_SHIFT;
|
||||
if (attribType == TYPECODE_BOOLEAN || attribType == TYPECODE_SPECIALSPACE)
|
||||
return; // has no additional data
|
||||
uint4 length = readLengthCode(typeByte); // Length of data in bytes
|
||||
if (attribType == TYPECODE_STRING) {
|
||||
length = readInteger(length); // Read length field to get final length of string
|
||||
}
|
||||
advancePosition(curPos, length); // Skip -length- data
|
||||
}
|
||||
|
||||
/// This assumes the header and \b type \b byte have been read. Decode type and length info and finish
|
||||
/// skipping over the attribute so that the next call to getNextAttributeId() is on cut.
|
||||
/// \param typeByte is the previously scanned type byte
|
||||
void PackedDecode::skipAttributeRemaining(uint1 typeByte)
|
||||
|
||||
{
|
||||
uint1 attribType = typeByte >> TYPECODE_SHIFT;
|
||||
if (attribType == TYPECODE_BOOLEAN || attribType == TYPECODE_SPECIALSPACE)
|
||||
return; // has no additional data
|
||||
uint4 length = readLengthCode(typeByte); // Length of data in bytes
|
||||
if (attribType == TYPECODE_STRING) {
|
||||
length = readInteger(length); // Read length field to get final length of string
|
||||
}
|
||||
advancePosition(curPos, length); // Skip -length- data
|
||||
}
|
||||
|
||||
PackedDecode::~PackedDecode(void)
|
||||
|
||||
{
|
||||
list<ByteChunk>::const_iterator iter;
|
||||
for(iter=inStream.begin();iter!=inStream.end();++iter) {
|
||||
delete [] (*iter).start;
|
||||
}
|
||||
}
|
||||
|
||||
void PackedDecode::ingestStream(istream &s)
|
||||
|
||||
{
|
||||
int4 gcount = 0;
|
||||
while(s.peek() > 0) {
|
||||
uint1 *buf = new uint1[BUFFER_SIZE + 1];
|
||||
inStream.emplace_back(buf,buf+BUFFER_SIZE);
|
||||
s.get((char *)buf,BUFFER_SIZE+1,'\0');
|
||||
gcount = s.gcount();
|
||||
}
|
||||
endPos.seqIter = inStream.begin();
|
||||
if (endPos.seqIter != inStream.end()) {
|
||||
endPos.current = (*endPos.seqIter).start;
|
||||
endPos.end = (*endPos.seqIter).end;
|
||||
// Make sure there is at least one character after ingested buffer
|
||||
if (gcount == BUFFER_SIZE) {
|
||||
// Last buffer was entirely filled
|
||||
uint1 *endbuf = new uint1[1]; // Add one more buffer
|
||||
inStream.emplace_back(endbuf,endbuf + 1);
|
||||
gcount = 0;
|
||||
}
|
||||
uint1 *buf = inStream.back().start;
|
||||
buf[gcount] = ELEMENT_END;
|
||||
}
|
||||
}
|
||||
|
||||
uint4 PackedDecode::peekElement(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getByte(endPos);
|
||||
if ((header1 & HEADER_MASK) != ELEMENT_START)
|
||||
return 0;
|
||||
uint4 id = header1 & ELEMENTID_MASK;
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0) {
|
||||
id <<= RAWDATA_BITSPERBYTE;
|
||||
id |= (getBytePlus1(endPos) & RAWDATA_MASK);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
uint4 PackedDecode::openElement(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getByte(endPos);
|
||||
if ((header1 & HEADER_MASK) != ELEMENT_START)
|
||||
return 0;
|
||||
getNextByte(endPos);
|
||||
uint4 id = header1 & ELEMENTID_MASK;
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0) {
|
||||
id <<= RAWDATA_BITSPERBYTE;
|
||||
id |= (getNextByte(endPos) & RAWDATA_MASK);
|
||||
}
|
||||
startPos = endPos;
|
||||
curPos = endPos;
|
||||
header1 = getByte(curPos);
|
||||
while((header1 & HEADER_MASK) == ATTRIBUTE) {
|
||||
skipAttribute();
|
||||
header1 = getByte(curPos);
|
||||
}
|
||||
endPos = curPos;
|
||||
curPos = startPos;
|
||||
attributeRead = true; // "Last attribute was read" is vacuously true
|
||||
return id;
|
||||
}
|
||||
|
||||
uint4 PackedDecode::openElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
uint4 id = openElement();
|
||||
if (id != elemId.getId()) {
|
||||
if (id == 0)
|
||||
throw DecoderError("Expecting <" + elemId.getName() + "> but did not scan an element");
|
||||
throw DecoderError("Expecting <" + elemId.getName() + "> but id did not match");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void PackedDecode::closeElement(uint4 id)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(endPos);
|
||||
if ((header1 & HEADER_MASK) != ELEMENT_END)
|
||||
throw DecoderError("Expecting element close");
|
||||
uint4 closeId = header1 & ELEMENTID_MASK;
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0) {
|
||||
closeId <<= RAWDATA_BITSPERBYTE;
|
||||
closeId |= (getNextByte(endPos) & RAWDATA_MASK);
|
||||
}
|
||||
if (id != closeId)
|
||||
throw DecoderError("Did not see expected closing element");
|
||||
}
|
||||
|
||||
void PackedDecode::closeElementSkipping(uint4 id)
|
||||
|
||||
{
|
||||
vector<uint4> idstack;
|
||||
idstack.push_back(id);
|
||||
do {
|
||||
uint1 header1 = getByte(endPos) & HEADER_MASK;
|
||||
if (header1 == ELEMENT_END) {
|
||||
closeElement(idstack.back());
|
||||
idstack.pop_back();
|
||||
}
|
||||
else if (header1 == ELEMENT_START) {
|
||||
idstack.push_back(openElement());
|
||||
}
|
||||
else
|
||||
throw DecoderError("Corrupt stream");
|
||||
} while(!idstack.empty());
|
||||
}
|
||||
|
||||
void PackedDecode::rewindAttributes(void)
|
||||
|
||||
{
|
||||
curPos = startPos;
|
||||
attributeRead = true;
|
||||
}
|
||||
|
||||
uint4 PackedDecode::getNextAttributeId(void)
|
||||
|
||||
{
|
||||
if (!attributeRead)
|
||||
skipAttribute();
|
||||
uint1 header1 = getByte(curPos);
|
||||
if ((header1 & HEADER_MASK) != ATTRIBUTE)
|
||||
return 0;
|
||||
uint4 id = header1 & ELEMENTID_MASK;
|
||||
if ((header1 & HEADEREXTEND_MASK) != 0) {
|
||||
id <<= RAWDATA_BITSPERBYTE;
|
||||
id |= (getBytePlus1(curPos) & RAWDATA_MASK);
|
||||
}
|
||||
attributeRead = false;
|
||||
return id;
|
||||
}
|
||||
|
||||
bool PackedDecode::readBool(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos);
|
||||
if ((header1 & HEADEREXTEND_MASK)!=0)
|
||||
getNextByte(curPos);
|
||||
uint1 typeByte = getNextByte(curPos);
|
||||
if ((typeByte >> TYPECODE_SHIFT) != TYPECODE_BOOLEAN)
|
||||
throw DecoderError("Expecting boolean attribute");
|
||||
attributeRead = true;
|
||||
return ((typeByte & LENGTHCODE_MASK) != 0);
|
||||
}
|
||||
|
||||
bool PackedDecode::readBool(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
bool res = readBool();
|
||||
curPos = startPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
intb PackedDecode::readSignedInteger(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos);
|
||||
if ((header1 & HEADEREXTEND_MASK)!=0)
|
||||
getNextByte(curPos);
|
||||
uint1 typeByte = getNextByte(curPos);
|
||||
uint4 typeCode = typeByte >> TYPECODE_SHIFT;
|
||||
intb res;
|
||||
if (typeCode == TYPECODE_SIGNEDINT_POSITIVE) {
|
||||
res = readInteger(readLengthCode(typeByte));
|
||||
}
|
||||
else if (typeCode == TYPECODE_SIGNEDINT_NEGATIVE) {
|
||||
res = readInteger(readLengthCode(typeByte));
|
||||
res = -res;
|
||||
}
|
||||
else {
|
||||
skipAttributeRemaining(typeByte);
|
||||
throw DecoderError("Expecting signed integer attribute");
|
||||
}
|
||||
attributeRead = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
intb PackedDecode::readSignedInteger(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
intb res = readSignedInteger();
|
||||
curPos = startPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
uintb PackedDecode::readUnsignedInteger(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos);
|
||||
if ((header1 & HEADEREXTEND_MASK)!=0)
|
||||
getNextByte(curPos);
|
||||
uint1 typeByte = getNextByte(curPos);
|
||||
uint4 typeCode = typeByte >> TYPECODE_SHIFT;
|
||||
uintb res;
|
||||
if (typeCode == TYPECODE_UNSIGNEDINT) {
|
||||
res = readInteger(readLengthCode(typeByte));
|
||||
}
|
||||
else {
|
||||
skipAttributeRemaining(typeByte);
|
||||
throw DecoderError("Expecting unsigned integer attribute");
|
||||
}
|
||||
attributeRead = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
uintb PackedDecode::readUnsignedInteger(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
uintb res = readUnsignedInteger();
|
||||
curPos = startPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
string PackedDecode::readString(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos);
|
||||
if ((header1 & HEADEREXTEND_MASK)!=0)
|
||||
getNextByte(curPos);
|
||||
uint1 typeByte = getNextByte(curPos);
|
||||
uint4 typeCode = typeByte >> TYPECODE_SHIFT;
|
||||
if (typeCode != TYPECODE_STRING) {
|
||||
skipAttributeRemaining(typeByte);
|
||||
throw DecoderError("Expecting string attribute");
|
||||
}
|
||||
int4 length = readLengthCode(typeByte);
|
||||
length = readInteger(length);
|
||||
|
||||
attributeRead = true;
|
||||
int4 curLen = curPos.end - curPos.current;
|
||||
if (curLen >= length) {
|
||||
string res((const char *)curPos.current,length);
|
||||
advancePosition(curPos, length);
|
||||
return res;
|
||||
}
|
||||
string res((const char *)curPos.current,curLen);
|
||||
length -= curLen;
|
||||
advancePosition(curPos, curLen);
|
||||
while(length > 0) {
|
||||
curLen = curPos.end - curPos.current;
|
||||
if (curLen > length)
|
||||
curLen = length;
|
||||
res.append((const char *)curPos.current,curLen);
|
||||
length -= curLen;
|
||||
advancePosition(curPos, curLen);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
string PackedDecode::readString(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
string res = readString();
|
||||
curPos = startPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
AddrSpace *PackedDecode::readSpace(void)
|
||||
|
||||
{
|
||||
uint1 header1 = getNextByte(curPos);
|
||||
if ((header1 & HEADEREXTEND_MASK)!=0)
|
||||
getNextByte(curPos);
|
||||
uint1 typeByte = getNextByte(curPos);
|
||||
uint4 typeCode = typeByte >> TYPECODE_SHIFT;
|
||||
int4 res;
|
||||
AddrSpace *spc;
|
||||
if (typeCode == TYPECODE_ADDRESSSPACE) {
|
||||
res = readInteger(readLengthCode(typeByte));
|
||||
spc = spcManager->getSpace(res);
|
||||
if (spc == (AddrSpace *)0)
|
||||
throw DecoderError("Unknown address space index");
|
||||
}
|
||||
else if (typeCode == TYPECODE_SPECIALSPACE) {
|
||||
uint4 specialCode = readLengthCode(typeByte);
|
||||
if (specialCode == SPECIALSPACE_STACK)
|
||||
spc = spcManager->getStackSpace();
|
||||
else if (specialCode == SPECIALSPACE_JOIN) {
|
||||
spc = spcManager->getJoinSpace();
|
||||
}
|
||||
else {
|
||||
throw DecoderError("Cannot marshal special address space");
|
||||
}
|
||||
}
|
||||
else {
|
||||
skipAttributeRemaining(typeByte);
|
||||
throw DecoderError("Expecting space attribute");
|
||||
}
|
||||
attributeRead = true;
|
||||
return spc;
|
||||
}
|
||||
|
||||
AddrSpace *PackedDecode::readSpace(const AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
AddrSpace *res = readSpace();
|
||||
curPos = startPos;
|
||||
return res;
|
||||
}
|
||||
|
||||
void PackedEncode::writeInteger(uint1 typeByte,uint8 val)
|
||||
|
||||
{
|
||||
uint1 lenCode;
|
||||
int4 sa;
|
||||
if (val == 0) {
|
||||
lenCode = 0;
|
||||
sa = -1;
|
||||
}
|
||||
if (val < 0x800000000) {
|
||||
if (val < 0x200000) {
|
||||
if (val < 0x80) {
|
||||
lenCode = 1; // 7-bits
|
||||
sa = 0;
|
||||
}
|
||||
else if (val < 0x4000) {
|
||||
lenCode = 2; // 14-bits
|
||||
sa = RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
else {
|
||||
lenCode = 3; // 21-bits
|
||||
sa = 2*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
}
|
||||
else if (val < 0x10000000) {
|
||||
lenCode = 4; // 28-bits
|
||||
sa = 3*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
else {
|
||||
lenCode = 5; // 35-bits
|
||||
sa = 4*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
}
|
||||
else if (val < 0x2000000000000) {
|
||||
if (val < 0x40000000000) {
|
||||
lenCode = 6;
|
||||
sa = 5*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
else {
|
||||
lenCode = 7;
|
||||
sa = 6*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (val < 0x100000000000000) {
|
||||
lenCode = 8;
|
||||
sa = 7*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
else if (val < 0x8000000000000000) {
|
||||
lenCode = 9;
|
||||
sa = 8*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
else {
|
||||
lenCode = 10;
|
||||
sa = 9*RAWDATA_BITSPERBYTE;
|
||||
}
|
||||
}
|
||||
typeByte |= lenCode;
|
||||
outStream.put(typeByte);
|
||||
for(;sa >= 0;sa -= RAWDATA_BITSPERBYTE) {
|
||||
uint1 piece = (val >> sa) & RAWDATA_MASK;
|
||||
piece |= RAWDATA_MARKER;
|
||||
outStream.put(piece);
|
||||
}
|
||||
}
|
||||
|
||||
void PackedEncode::openElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
writeHeader(ELEMENT_START, elemId.getId());
|
||||
}
|
||||
|
||||
void PackedEncode::closeElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
writeHeader(ELEMENT_END, elemId.getId());
|
||||
}
|
||||
|
||||
void PackedEncode::writeBool(const AttributeId &attribId,bool val)
|
||||
|
||||
{
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
uint1 typeByte = val ? ((TYPECODE_BOOLEAN << TYPECODE_SHIFT) | 1) : (TYPECODE_BOOLEAN << TYPECODE_SHIFT);
|
||||
outStream.put(typeByte);
|
||||
}
|
||||
|
||||
void PackedEncode::writeSignedInteger(const AttributeId &attribId,intb val)
|
||||
|
||||
{
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
uint1 typeByte;
|
||||
uint8 num;
|
||||
if (val < 0) {
|
||||
typeByte = (TYPECODE_SIGNEDINT_NEGATIVE << TYPECODE_SHIFT);
|
||||
num = -val;
|
||||
}
|
||||
else {
|
||||
typeByte = (TYPECODE_SIGNEDINT_POSITIVE << TYPECODE_SHIFT);
|
||||
num = val;
|
||||
}
|
||||
writeInteger(typeByte, num);
|
||||
}
|
||||
|
||||
void PackedEncode::writeUnsignedInteger(const AttributeId &attribId,uintb val)
|
||||
|
||||
{
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
writeInteger((TYPECODE_UNSIGNEDINT << TYPECODE_SHIFT),val);
|
||||
}
|
||||
|
||||
void PackedEncode::writeString(const AttributeId &attribId,const string &val)
|
||||
|
||||
{
|
||||
uint8 length = val.length();
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
writeInteger((TYPECODE_STRING << TYPECODE_SHIFT), length);
|
||||
outStream.write(val.c_str(), length);
|
||||
}
|
||||
|
||||
void PackedEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
|
||||
|
||||
{
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
switch(spc->getType()) {
|
||||
case IPTR_FSPEC:
|
||||
outStream.put((TYPECODE_SPECIALSPACE << TYPECODE_SHIFT) | SPECIALSPACE_FSPEC);
|
||||
break;
|
||||
case IPTR_IOP:
|
||||
outStream.put((TYPECODE_SPECIALSPACE << TYPECODE_SHIFT) | SPECIALSPACE_IOP);
|
||||
break;
|
||||
case IPTR_JOIN:
|
||||
outStream.put((TYPECODE_SPECIALSPACE << TYPECODE_SHIFT) | SPECIALSPACE_JOIN);
|
||||
break;
|
||||
case IPTR_SPACEBASE:
|
||||
if (spc->isFormalStackSpace())
|
||||
outStream.put((TYPECODE_SPECIALSPACE << TYPECODE_SHIFT) | SPECIALSPACE_STACK);
|
||||
else
|
||||
outStream.put((TYPECODE_SPECIALSPACE << TYPECODE_SHIFT) | SPECIALSPACE_SPACEBASE); // A secondary register offset space
|
||||
break;
|
||||
default:
|
||||
uint8 spcId = spc->getIndex();
|
||||
writeInteger((TYPECODE_ADDRESSSPACE << TYPECODE_SHIFT), spcId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Common attributes. Attributes with multiple uses
|
||||
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
|
||||
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
|
||||
|
@ -513,4 +1044,4 @@ ElementId ELEM_VAL = ElementId("val",8);
|
|||
ElementId ELEM_VALUE = ElementId("value",9);
|
||||
ElementId ELEM_VOID = ElementId("void",10);
|
||||
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",251); // Number serves as next open index
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",270); // Number serves as next open index
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#define __CPUI_MARSHAL__
|
||||
|
||||
#include "xml.hh"
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
@ -100,11 +101,6 @@ public:
|
|||
const AddrSpaceManager *getAddrSpaceManager(void) const { return spcManager; } ///< Get the manager used for address space decoding
|
||||
virtual ~Decoder(void) {} ///< Destructor
|
||||
|
||||
/// \brief Clear any current decoding state
|
||||
///
|
||||
/// Allows the same decoder to be reused. Object is ready for new call to ingestStream.
|
||||
virtual void clear(void)=0;
|
||||
|
||||
/// \brief Prepare to decode a given stream
|
||||
///
|
||||
/// Called once before any decoding. Currently this is assumed to make an internal copy of the stream data,
|
||||
|
@ -262,11 +258,6 @@ class Encoder {
|
|||
public:
|
||||
virtual ~Encoder(void) {} ///< Destructor
|
||||
|
||||
/// \brief Clear any state associated with the encoder
|
||||
///
|
||||
/// The encoder should be ready to write a new document after this call.
|
||||
virtual void clear(void)=0;
|
||||
|
||||
/// \brief Begin a new element in the encoding
|
||||
///
|
||||
/// The element will have the given ElementId annotation and becomes the \e current element.
|
||||
|
@ -333,7 +324,6 @@ public:
|
|||
XmlDecode(const AddrSpaceManager *spc) : Decoder(spc) {
|
||||
document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
|
||||
virtual ~XmlDecode(void);
|
||||
virtual void clear(void);
|
||||
virtual void ingestStream(istream &s);
|
||||
virtual uint4 peekElement(void);
|
||||
virtual uint4 openElement(void);
|
||||
|
@ -364,7 +354,6 @@ class XmlEncode : public Encoder {
|
|||
bool elementTagIsOpen; ///< If \b true, new attributes can be written to the current element
|
||||
public:
|
||||
XmlEncode(ostream &s) : outStream(s) { elementTagIsOpen = false; } ///< Construct from a stream
|
||||
virtual void clear(void) { elementTagIsOpen = false; }
|
||||
virtual void openElement(const ElementId &elemId);
|
||||
virtual void closeElement(const ElementId &elemId);
|
||||
virtual void writeBool(const AttributeId &attribId,bool val);
|
||||
|
@ -374,6 +363,206 @@ public:
|
|||
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc);
|
||||
};
|
||||
|
||||
/// \brief Protocol format for PackedEncode and PackedDecode classes
|
||||
///
|
||||
/// All bytes in the encoding are expected to be non-zero. Element encoding looks like
|
||||
/// - 01xiiiii is an element start
|
||||
/// - 10xiiiii is an element end
|
||||
/// - 11xiiiii is an attribute start
|
||||
///
|
||||
/// Where iiiii is the (first) 5 bits of the element/attribute id.
|
||||
/// If x=0, the id is complete. If x=1, the next byte contains 7 more bits of the id: 1iiiiiii
|
||||
///
|
||||
/// After an attribute start, there follows a \e type byte: ttttllll, where the first 4 bits indicate the
|
||||
/// type of attribute and final 4 bits are a \b length \b code. The types are:
|
||||
/// - 1 = boolean (lengthcode=0 for false, lengthcode=1 for true)
|
||||
/// - 2 = positive signed integer
|
||||
/// - 3 = negative signed integer (stored in negated form)
|
||||
/// - 4 = unsigned integer
|
||||
/// - 5 = basic address space (encoded as the integer index of the space)
|
||||
/// - 6 = special address space (lengthcode 0=>stack 1=>join 2=>fspec 3=>iop)
|
||||
/// - 7 = string
|
||||
///
|
||||
/// All attribute types except \e boolean and \e special, have an encoded integer after the \e type byte.
|
||||
/// The \b length \b code, indicates the number bytes used to encode the integer, 7-bits of info per byte, 1iiiiiii.
|
||||
/// A \b length \b code of zero is used to encode an integer value of 0, with no following bytes.
|
||||
///
|
||||
/// For strings, the integer encoded after the \e type byte, is the actual length of the string. The
|
||||
/// string data itself is stored immediately after the length integer using UTF8 format.
|
||||
namespace PackedFormat {
|
||||
static const uint1 HEADER_MASK = 0xc0;
|
||||
static const uint1 ELEMENT_START = 0x40;
|
||||
static const uint1 ELEMENT_END = 0x80;
|
||||
static const uint1 ATTRIBUTE = 0xc0;
|
||||
static const uint1 HEADEREXTEND_MASK = 0x20;
|
||||
static const uint1 ELEMENTID_MASK = 0x1f;
|
||||
static const uint1 RAWDATA_MASK = 0x7f;
|
||||
static const int4 RAWDATA_BITSPERBYTE = 7;
|
||||
static const uint1 RAWDATA_MARKER = 0x80;
|
||||
static const int4 TYPECODE_SHIFT = 4;
|
||||
static const uint1 LENGTHCODE_MASK = 0xf;
|
||||
static const uint1 TYPECODE_BOOLEAN = 1;
|
||||
static const uint1 TYPECODE_SIGNEDINT_POSITIVE = 2;
|
||||
static const uint1 TYPECODE_SIGNEDINT_NEGATIVE = 3;
|
||||
static const uint1 TYPECODE_UNSIGNEDINT = 4;
|
||||
static const uint1 TYPECODE_ADDRESSSPACE = 5;
|
||||
static const uint1 TYPECODE_SPECIALSPACE = 6;
|
||||
static const uint1 TYPECODE_STRING = 7;
|
||||
static const uint4 SPECIALSPACE_STACK = 0;
|
||||
static const uint4 SPECIALSPACE_JOIN = 1;
|
||||
static const uint4 SPECIALSPACE_FSPEC = 2;
|
||||
static const uint4 SPECIALSPACE_IOP = 3;
|
||||
static const uint4 SPECIALSPACE_SPACEBASE = 4;
|
||||
}
|
||||
|
||||
/// \brief A byte-based decoder designed to marshal info to the decompiler efficiently
|
||||
///
|
||||
/// The decoder expects an encoding as described in PackedFormat. When ingested, the stream bytes are
|
||||
/// held in a sequence of arrays (ByteChunk). During decoding, \b this object maintains a Position in the
|
||||
/// stream at the start and end of the current open element, and a Position of the next attribute to read to
|
||||
/// facilitate getNextAttributeId() and associated read*() methods.
|
||||
class PackedDecode : public Decoder {
|
||||
public:
|
||||
static const int4 BUFFER_SIZE; ///< The size, in bytes, of a single cached chunk of the input stream
|
||||
private:
|
||||
/// \brief A bounded array of bytes
|
||||
class ByteChunk {
|
||||
friend class PackedDecode;
|
||||
uint1 *start; ///< Start of the byte array
|
||||
uint1 *end; ///< End of the byte array
|
||||
public:
|
||||
ByteChunk(uint1 *s,uint1 *e) { start = s; end = e; } ///< Constructor
|
||||
};
|
||||
/// \brief An iterator into input stream
|
||||
class Position {
|
||||
friend class PackedDecode;
|
||||
list<ByteChunk>::const_iterator seqIter; ///< Current byte sequence
|
||||
uint1 *current; ///< Current position in sequence
|
||||
uint1 *end; ///< End of current sequence
|
||||
};
|
||||
list<ByteChunk> inStream; ///< Incoming raw data as a sequence of byte arrays
|
||||
Position startPos; ///< Position at the start of the current open element
|
||||
Position curPos; ///< Position of the next attribute as returned by getNextAttributeId
|
||||
Position endPos; ///< Ending position after all attributes in current open element
|
||||
bool attributeRead; ///< Has the last attribute returned by getNextAttributeId been read
|
||||
uint1 getByte(Position &pos) { return *pos.current; } ///< Get the byte at the current position, do not advance
|
||||
uint1 getBytePlus1(Position &pos); ///< Get the byte following the current byte, do not advance position
|
||||
uint1 getNextByte(Position &pos); ///< Get the byte at the current position and advance to the next byte
|
||||
void advancePosition(Position &pos,int4 skip); ///< Advance the position by the given number of bytes
|
||||
uint8 readInteger(int4 len); ///< Read an integer from the \e current position given its length in bytes
|
||||
uint4 readLengthCode(uint1 typeByte) { return ((uint4)typeByte & PackedFormat::LENGTHCODE_MASK); } ///< Extract length code from type byte
|
||||
void findMatchingAttribute(const AttributeId &attribId); ///< Find attribute matching the given id in open element
|
||||
void skipAttribute(void); ///< Skip over the attribute at the current position
|
||||
void skipAttributeRemaining(uint1 typeByte); ///< Skip over remaining attribute data, after a mismatch
|
||||
public:
|
||||
PackedDecode(const AddrSpaceManager *spcManager) : Decoder(spcManager) {} ///< Constructor
|
||||
virtual ~PackedDecode(void);
|
||||
virtual void ingestStream(istream &s);
|
||||
virtual uint4 peekElement(void);
|
||||
virtual uint4 openElement(void);
|
||||
virtual uint4 openElement(const ElementId &elemId);
|
||||
virtual void closeElement(uint4 id);
|
||||
virtual void closeElementSkipping(uint4 id);
|
||||
virtual void rewindAttributes(void);
|
||||
virtual uint4 getNextAttributeId(void);
|
||||
virtual bool readBool(void);
|
||||
virtual bool readBool(const AttributeId &attribId);
|
||||
virtual intb readSignedInteger(void);
|
||||
virtual intb readSignedInteger(const AttributeId &attribId);
|
||||
virtual uintb readUnsignedInteger(void);
|
||||
virtual uintb readUnsignedInteger(const AttributeId &attribId);
|
||||
virtual string readString(void);
|
||||
virtual string readString(const AttributeId &attribId);
|
||||
virtual AddrSpace *readSpace(void);
|
||||
virtual AddrSpace *readSpace(const AttributeId &attribId);
|
||||
};
|
||||
|
||||
/// \brief A byte-based encoder designed to marshal from the decompiler efficiently
|
||||
///
|
||||
/// See PackedDecode for details of the encoding format.
|
||||
class PackedEncode : public Encoder {
|
||||
ostream &outStream; ///< The stream receiving the encoded data
|
||||
void writeHeader(uint1 header,uint4 id);
|
||||
void writeInteger(uint1 typeByte,uint8 val);
|
||||
public:
|
||||
PackedEncode(ostream &s) : outStream(s) {} ///< Construct from a stream
|
||||
virtual void openElement(const ElementId &elemId);
|
||||
virtual void closeElement(const ElementId &elemId);
|
||||
virtual void writeBool(const AttributeId &attribId,bool val);
|
||||
virtual void writeSignedInteger(const AttributeId &attribId,intb val);
|
||||
virtual void writeUnsignedInteger(const AttributeId &attribId,uintb val);
|
||||
virtual void writeString(const AttributeId &attribId,const string &val);
|
||||
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc);
|
||||
};
|
||||
|
||||
/// An exception is thrown if the position currently points to the last byte in the stream
|
||||
/// \param pos is the position in the stream to look ahead from
|
||||
/// \return the next byte
|
||||
inline uint1 PackedDecode::getBytePlus1(Position &pos)
|
||||
|
||||
{
|
||||
uint1 *ptr = pos.current + 1;
|
||||
if (ptr == pos.end) {
|
||||
list<ByteChunk>::const_iterator iter = pos.seqIter;
|
||||
++iter;
|
||||
if (iter == inStream.end())
|
||||
throw DecoderError("Unexpected end of stream");
|
||||
ptr = (*iter).start;
|
||||
}
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
/// An exception is thrown if there are no additional bytes in the stream
|
||||
/// \param pos is the position of the byte
|
||||
/// \return the byte at the current position
|
||||
inline uint1 PackedDecode::getNextByte(Position &pos)
|
||||
|
||||
{
|
||||
uint1 res = *pos.current;
|
||||
pos.current += 1;
|
||||
if (pos.current != pos.end)
|
||||
return res;
|
||||
++pos.seqIter;
|
||||
if (pos.seqIter == inStream.end())
|
||||
throw DecoderError("Unexpected end of stream");
|
||||
pos.current = (*pos.seqIter).start;
|
||||
pos.end = (*pos.seqIter).end;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// An exception is thrown of position is advanced past the end of the stream
|
||||
/// \param pos is the position being advanced
|
||||
/// \param skip is the number of bytes to advance
|
||||
inline void PackedDecode::advancePosition(Position &pos,int4 skip)
|
||||
|
||||
{
|
||||
while(pos.end - pos.current <= skip) {
|
||||
skip -= (pos.end - pos.current);
|
||||
++pos.seqIter;
|
||||
if (pos.seqIter == inStream.end())
|
||||
throw DecoderError("Unexpected end of stream");
|
||||
pos.current = (*pos.seqIter).start;
|
||||
pos.end = (*pos.seqIter).end;
|
||||
}
|
||||
pos.current += skip;
|
||||
}
|
||||
|
||||
inline void PackedEncode::writeHeader(uint1 header,uint4 id)
|
||||
|
||||
{
|
||||
if (id > 0x1f) {
|
||||
header |= PackedFormat::HEADEREXTEND_MASK;
|
||||
header |= (id >> PackedFormat::RAWDATA_BITSPERBYTE);
|
||||
uint1 extendByte = (id & PackedFormat::RAWDATA_MASK) | PackedFormat::RAWDATA_MARKER;
|
||||
outStream.put(header);
|
||||
outStream.put(extendByte);
|
||||
}
|
||||
else {
|
||||
header |= id;
|
||||
outStream.put(header);
|
||||
}
|
||||
}
|
||||
|
||||
extern ElementId ELEM_UNKNOWN; ///< Special element to represent an element with an unrecognized name
|
||||
extern AttributeId ATTRIB_UNKNOWN; ///< Special attribute to represent an attribute with an unrecognized name
|
||||
extern AttributeId ATTRIB_CONTENT; ///< Special attribute for XML text content of an element
|
||||
|
|
|
@ -230,6 +230,7 @@ public:
|
|||
const string &getOpName(void) const { return opcode->getName(); } ///< Return the name of this op
|
||||
void printDebug(ostream &s) const; ///< Print debug description of this op to stream
|
||||
void encode(Encoder &encoder) const; ///< Encode a description of \b this op to stream
|
||||
|
||||
/// \brief Retrieve the PcodeOp encoded as the address \e addr
|
||||
static PcodeOp *getOpFromConst(const Address &addr) { return (PcodeOp *)(uintp)addr.getOffset(); }
|
||||
|
||||
|
|
|
@ -63,3 +63,39 @@ bool VarnodeData::contains(const VarnodeData &op2) const
|
|||
if ((offset + (size-1)) < (op2.offset + (op2.size-1))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This assumes the \<op> element is already open.
|
||||
/// Decode info suitable for call to PcodeEmit::dump. The output pointer is changed to null if there
|
||||
/// is no output for this op, otherwise the existing pointer is used to store the output.
|
||||
/// \param decoder is the stream decoder
|
||||
/// \param isize is the (preparsed) number of input parameters for the p-code op
|
||||
/// \param invar is an array of storage for the input Varnodes
|
||||
/// \param outvar is a (handle) to the storage for the output Varnode
|
||||
/// \return the p-code op OpCode
|
||||
OpCode PcodeOpRaw::decode(Decoder &decoder,int4 isize,VarnodeData *invar,VarnodeData **outvar)
|
||||
|
||||
{
|
||||
OpCode opcode = (OpCode)decoder.readSignedInteger(ATTRIB_CODE);
|
||||
uint4 subId = decoder.peekElement();
|
||||
if (subId == ELEM_VOID) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(subId);
|
||||
*outvar = (VarnodeData *)0;
|
||||
}
|
||||
else {
|
||||
(*outvar)->decode(decoder);
|
||||
}
|
||||
for(int4 i=0;i<isize;++i) {
|
||||
subId = decoder.peekElement();
|
||||
if (subId == ELEM_SPACEID) {
|
||||
decoder.openElement();
|
||||
invar[i].space = decoder.getAddrSpaceManager()->getConstantSpace();
|
||||
invar[i].offset = (uintb)(uintp)decoder.readSpace(ATTRIB_NAME);
|
||||
invar[i].size = sizeof(void *);
|
||||
decoder.closeElement(subId);
|
||||
}
|
||||
else
|
||||
invar[i].decode(decoder);
|
||||
}
|
||||
return opcode;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,9 @@ public:
|
|||
void clearInputs(void); ///< Remove all input varnodes to this op
|
||||
int4 numInput(void) const; ///< Get the number of input varnodes to this op
|
||||
VarnodeData *getInput(int4 i) const; ///< Get the i-th input varnode for this op
|
||||
|
||||
/// \brief Decode the raw OpCode and input/output Varnode data for a PcodeOp
|
||||
static OpCode decode(Decoder &decoder,int4 isize,VarnodeData *invar,VarnodeData **outvar);
|
||||
};
|
||||
|
||||
/// The core behavior for this operation is controlled by an OpBehavior object
|
||||
|
|
|
@ -287,7 +287,7 @@ void EmitMarkup::setOutputStream(ostream *t)
|
|||
if (encoder != (Encoder *)0)
|
||||
delete encoder;
|
||||
s = t;
|
||||
encoder = new XmlEncode(*s);
|
||||
encoder = new PackedEncode(*s);
|
||||
}
|
||||
|
||||
int4 TokenSplit::countbase = 0;
|
||||
|
|
|
@ -126,7 +126,7 @@ void SleighArchitecture::loadLanguageDescription(const string &specfile,ostream
|
|||
try {
|
||||
decoder.ingestStream(s);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
errs << "WARNING: Unable to parse sleigh specfile: " << specfile;
|
||||
return;
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
|
|||
Document *doc = store.openDocument(processorfile);
|
||||
store.registerTag(doc->getRoot());
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
ostringstream serr;
|
||||
serr << "XML error parsing processor specification: " << processorfile;
|
||||
serr << "\n " << err.explain;
|
||||
|
@ -263,7 +263,7 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
|
|||
Document *doc = store.openDocument(compilerfile);
|
||||
store.registerTag(doc->getRoot());
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
ostringstream serr;
|
||||
serr << "XML error parsing compiler specification: " << compilerfile;
|
||||
serr << "\n " << err.explain;
|
||||
|
@ -281,7 +281,7 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
|
|||
Document *doc = store.openDocument(slafile);
|
||||
store.registerTag(doc->getRoot());
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
ostringstream serr;
|
||||
serr << "XML error parsing SLEIGH file: " << slafile;
|
||||
serr << "\n " << err.explain;
|
||||
|
|
|
@ -3577,7 +3577,7 @@ static int4 run_xml(const string &filein,SleighCompile &compiler)
|
|||
try {
|
||||
doc = xml_tree(s);
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
catch(DecoderError &err) {
|
||||
cerr << "Unable to parse single input file as XML spec: " << filein << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ uintb AddrSpace::decodeAttributes(Decoder &decoder,uint4 &size) const
|
|||
offset = decoder.readUnsignedInteger();
|
||||
}
|
||||
else if (attribId == ATTRIB_SIZE) {
|
||||
size = decoder.readUnsignedInteger();
|
||||
size = decoder.readSignedInteger();
|
||||
}
|
||||
}
|
||||
if (!foundoffset)
|
||||
|
@ -316,7 +316,7 @@ void AddrSpace::decodeBasicAttributes(Decoder &decoder)
|
|||
if (attribId == ATTRIB_INDEX)
|
||||
index = decoder.readSignedInteger();
|
||||
else if (attribId == ATTRIB_SIZE)
|
||||
addressSize = decoder.readUnsignedInteger();
|
||||
addressSize = decoder.readSignedInteger();
|
||||
else if (attribId == ATTRIB_WORDSIZE)
|
||||
wordsize = decoder.readUnsignedInteger();
|
||||
else if (attribId == ATTRIB_BIGENDIAN) {
|
||||
|
|
|
@ -94,12 +94,13 @@ public:
|
|||
does_deadcode = 4, ///< Dead-code analysis is done on this space
|
||||
programspecific = 8, ///< Space is specific to a particular loadimage
|
||||
reverse_justification = 16, ///< Justification within aligned word is opposite of endianness
|
||||
overlay = 32, ///< This space is an overlay of another space
|
||||
overlaybase = 64, ///< This is the base space for overlay space(s)
|
||||
truncated = 128, ///< Space is truncated from its original size, expect pointers larger than this size
|
||||
hasphysical = 256, ///< Has physical memory associated with it
|
||||
is_otherspace = 512, ///< Quick check for the OtherSpace derived class
|
||||
has_nearpointers = 0x400 ///< Does there exist near pointers into this space
|
||||
formal_stackspace = 0x20, ///< Space attached to the formal \b stack \b pointer
|
||||
overlay = 0x40, ///< This space is an overlay of another space
|
||||
overlaybase = 0x80, ///< This is the base space for overlay space(s)
|
||||
truncated = 0x100, ///< Space is truncated from its original size, expect pointers larger than this size
|
||||
hasphysical = 0x200, ///< Has physical memory associated with it
|
||||
is_otherspace = 0x400, ///< Quick check for the OtherSpace derived class
|
||||
has_nearpointers = 0x800 ///< Does there exist near pointers into this space
|
||||
};
|
||||
private:
|
||||
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
|
||||
|
@ -149,6 +150,7 @@ public:
|
|||
bool hasPhysical(void) const; ///< Return \b true if data is physically stored in this
|
||||
bool isBigEndian(void) const; ///< Return \b true if values in this space are big endian
|
||||
bool isReverseJustified(void) const; ///< Return \b true if alignment justification does not match endianness
|
||||
bool isFormalStackSpace(void) const; ///< Return \b true if \b this is attached to the formal \b stack \b pointer
|
||||
bool isOverlay(void) const; ///< Return \b true if this is an overlay space
|
||||
bool isOverlayBase(void) const; ///< Return \b true if other spaces overlay this space
|
||||
bool isOtherSpace(void) const; ///< Return \b true if \b this is the \e other address space
|
||||
|
@ -446,6 +448,11 @@ inline bool AddrSpace::isReverseJustified(void) const {
|
|||
return ((flags&reverse_justification)!=0);
|
||||
}
|
||||
|
||||
/// Currently an architecture can declare only one formal stack pointer.
|
||||
inline bool AddrSpace::isFormalStackSpace(void) const {
|
||||
return ((flags&formal_stackspace)!=0);
|
||||
}
|
||||
|
||||
inline bool AddrSpace::isOverlay(void) const {
|
||||
return ((flags&overlay)!=0);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ void FunctionTestCollection::buildProgram(DocumentStorage &docStorage)
|
|||
try {
|
||||
dcp->conf->init(docStorage);
|
||||
dcp->conf->readLoaderSymbols("::"); // Read in loader symbols
|
||||
} catch(XmlError &err) {
|
||||
} catch(DecoderError &err) {
|
||||
errmsg = err.explain;
|
||||
iserror = true;
|
||||
} catch(LowlevelError &err) {
|
||||
|
|
|
@ -43,7 +43,7 @@ void TruncationTag::decode(Decoder &decoder)
|
|||
}
|
||||
|
||||
/// Construct a virtual space. This is usually used for the stack
|
||||
/// space, but multiple such spaces are allowed.
|
||||
/// space, which is indicated by the \b isFormal parameters, but multiple such spaces are allowed.
|
||||
/// \param m is the manager for this \b program \b specific address space
|
||||
/// \param t is associated processor translator
|
||||
/// \param nm is the name of the space
|
||||
|
@ -51,13 +51,16 @@ void TruncationTag::decode(Decoder &decoder)
|
|||
/// \param sz is the size of the space
|
||||
/// \param base is the containing space
|
||||
/// \param dl is the heritage delay
|
||||
/// \param isFormal is the formal stack space indicator
|
||||
SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,
|
||||
AddrSpace *base,int4 dl)
|
||||
AddrSpace *base,int4 dl,bool isFormal)
|
||||
: AddrSpace(m,t,IPTR_SPACEBASE,nm,sz,base->getWordSize(),ind,0,dl)
|
||||
{
|
||||
contain = base;
|
||||
hasbaseregister = false; // No base register assigned yet
|
||||
isNegativeStack = true; // default stack growth
|
||||
if (isFormal)
|
||||
setFlags(formal_stackspace);
|
||||
}
|
||||
|
||||
/// This is a partial constructor, which must be followed up
|
||||
|
@ -907,124 +910,24 @@ const FloatFormat *Translate::getFloatFormat(int4 size) const
|
|||
/// A single pcode operation is parsed from an \<op> element and
|
||||
/// returned to the application via the PcodeEmit::dump method.
|
||||
/// \param decoder is the stream decoder
|
||||
void PcodeEmit::decodeOp(Decoder &decoder)
|
||||
void PcodeEmit::decodeOp(const Address &addr,Decoder &decoder)
|
||||
|
||||
{
|
||||
int4 opcode;
|
||||
int4 isize;
|
||||
VarnodeData outvar;
|
||||
VarnodeData invar[30];
|
||||
VarnodeData invar[16];
|
||||
VarnodeData *outptr;
|
||||
|
||||
uint4 elemId = decoder.openElement(ELEM_OP);
|
||||
opcode = decoder.readSignedInteger(ATTRIB_CODE);
|
||||
Address pc = Address::decode(decoder);
|
||||
uint4 subId = decoder.peekElement();
|
||||
if (subId == ELEM_VOID) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(subId);
|
||||
outptr = (VarnodeData *)0;
|
||||
}
|
||||
isize = decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
outptr = &outvar;
|
||||
if (isize <= 16)
|
||||
opcode = PcodeOpRaw::decode(decoder, isize, invar, &outptr);
|
||||
else {
|
||||
outvar.decode(decoder);
|
||||
outptr = &outvar;
|
||||
}
|
||||
int4 isize = 0;
|
||||
while(isize < 30) {
|
||||
subId = decoder.peekElement();
|
||||
if (subId == 0) break;
|
||||
if (subId == ELEM_SPACEID) {
|
||||
decoder.openElement();
|
||||
invar[isize].space = decoder.getAddrSpaceManager()->getConstantSpace();
|
||||
invar[isize].offset = (uintb)(uintp)decoder.readSpace(ATTRIB_NAME);
|
||||
invar[isize].size = sizeof(void *);
|
||||
decoder.closeElement(subId);
|
||||
}
|
||||
else
|
||||
invar[isize].decode(decoder);
|
||||
isize += 1;
|
||||
vector<VarnodeData> varStorage(isize,VarnodeData());
|
||||
opcode = PcodeOpRaw::decode(decoder, isize, varStorage.data(), &outptr);
|
||||
}
|
||||
decoder.closeElement(elemId);
|
||||
dump(pc,(OpCode)opcode,outptr,invar,isize);
|
||||
}
|
||||
|
||||
/// A Helper function for PcodeEmit::restorePackedOp that reads an unsigned offset from a packed stream
|
||||
/// \param ptr is a pointer into a packed byte stream
|
||||
/// \param off is where the offset read from the stream is stored
|
||||
/// \return a pointer to the next unconsumed byte of the stream
|
||||
const uint1 *PcodeEmit::unpackOffset(const uint1 *ptr,uintb &off)
|
||||
|
||||
{
|
||||
uintb res = 0;
|
||||
int4 shift;
|
||||
for(shift=0;shift<67;shift+=6) {
|
||||
uint1 val = *ptr++;
|
||||
if (val == end_tag) {
|
||||
off = res;
|
||||
return ptr;
|
||||
}
|
||||
uintb bits = ((uintb)(val-0x20))<<shift;
|
||||
res |= bits;
|
||||
}
|
||||
throw LowlevelError("Bad packed offset");
|
||||
}
|
||||
|
||||
/// A Helper function for PcodeEmit::restorePackedOp that reads a varnode from a packed stream
|
||||
/// \param ptr is a pointer into a packed byte stream
|
||||
/// \param v is the VarnodeData object being filled in by the stream
|
||||
/// \param manage is the AddrSpace manager object of the associated processor
|
||||
/// \return a pointer to the next unconsumed byte of the stream
|
||||
const uint1 *PcodeEmit::unpackVarnodeData(const uint1 *ptr,VarnodeData &v,const AddrSpaceManager *manage)
|
||||
|
||||
{
|
||||
uint1 tag = *ptr++;
|
||||
if (tag == addrsz_tag) {
|
||||
int4 spcindex = (int4)(*ptr++ - 0x20);
|
||||
v.space = manage->getSpace(spcindex);
|
||||
ptr = unpackOffset(ptr,v.offset);
|
||||
v.size = (uint4)(*ptr++ - 0x20);
|
||||
}
|
||||
else if (tag == spaceid_tag) {
|
||||
v.space = manage->getConstantSpace();
|
||||
int4 spcindex = (int4)(*ptr++ - 0x20);
|
||||
v.offset = (uintb)(uintp)manage->getSpace( spcindex );
|
||||
v.size = sizeof(void *);
|
||||
}
|
||||
else
|
||||
throw LowlevelError("Bad packed VarnodeData");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// A convenience method for passing around pcode operations via a special packed format.
|
||||
/// A single pcode operation is parsed from a byte stream and returned to the application
|
||||
/// via the PcodeEmit::dump method.
|
||||
/// \param addr is the address of the instruction that generated this pcode
|
||||
/// \param ptr is a pointer into a packed byte stream
|
||||
/// \param manage is the AddrSpace manager object of the associated processor
|
||||
/// \return a pointer to the next unconsumed byte of the stream
|
||||
const uint1 *PcodeEmit::restorePackedOp(const Address &addr,const uint1 *ptr,const AddrSpaceManager *manage)
|
||||
|
||||
{
|
||||
int4 opcode;
|
||||
VarnodeData outvar;
|
||||
VarnodeData invar[30];
|
||||
VarnodeData *outptr;
|
||||
|
||||
ptr += 1; // Consume the -op- tag
|
||||
opcode = (int4)(*ptr++ - 0x20); // Opcode
|
||||
if (*ptr == void_tag) {
|
||||
ptr += 1;
|
||||
outptr = (VarnodeData *)0;
|
||||
}
|
||||
else {
|
||||
ptr = unpackVarnodeData(ptr,outvar,manage);
|
||||
outptr = &outvar;
|
||||
}
|
||||
int4 isize = 0;
|
||||
while(*ptr != end_tag) {
|
||||
ptr = unpackVarnodeData(ptr,invar[isize],manage);
|
||||
isize += 1;
|
||||
}
|
||||
ptr += 1; // Consume the end tag
|
||||
dump(addr,(OpCode)opcode,outptr,invar,isize);
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
@ -108,23 +108,7 @@ public:
|
|||
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)=0;
|
||||
|
||||
/// Emit pcode directly from an \<op> element
|
||||
void decodeOp(Decoder &decoder);
|
||||
|
||||
enum { // Tags for packed pcode format
|
||||
unimpl_tag = 0x20,
|
||||
inst_tag = 0x21,
|
||||
op_tag = 0x22,
|
||||
void_tag = 0x23,
|
||||
spaceid_tag = 0x24,
|
||||
addrsz_tag = 0x25,
|
||||
end_tag = 0x60
|
||||
};
|
||||
/// Helper function for unpacking an offset from a pcode byte stream
|
||||
static const uint1 *unpackOffset(const uint1 *ptr,uintb &off);
|
||||
/// Helper function for unpacking a varnode from a pcode byte stream
|
||||
static const uint1 *unpackVarnodeData(const uint1 *ptr,VarnodeData &v,const AddrSpaceManager *trans);
|
||||
/// Emit pcode directly from a packed byte stream
|
||||
const uint1 *restorePackedOp(const Address &addr,const uint1 *ptr,const AddrSpaceManager *trans);
|
||||
void decodeOp(const Address &addr,Decoder &decoder);
|
||||
};
|
||||
|
||||
/// \brief Abstract class for emitting disassembly to an application
|
||||
|
@ -192,7 +176,7 @@ class SpacebaseSpace : public AddrSpace {
|
|||
VarnodeData baseOrig; ///< Original base register before any truncation
|
||||
void setBaseRegister(const VarnodeData &data,int4 origSize,bool stackGrowth); ///< Set the base register at time space is created
|
||||
public:
|
||||
SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,AddrSpace *base,int4 dl);
|
||||
SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,AddrSpace *base,int4 dl,bool isFormal);
|
||||
SpacebaseSpace(AddrSpaceManager *m,const Translate *t); ///< For use with decode
|
||||
virtual int4 numSpacebase(void) const;
|
||||
virtual const VarnodeData &getSpacebase(int4 i) const;
|
||||
|
|
|
@ -20,13 +20,14 @@ Datatype *TypeFactoryGhidra::findById(const string &n,uint8 id,int4 sz)
|
|||
{
|
||||
Datatype *ct = TypeFactory::findById(n,id,sz); // Try internal find
|
||||
if (ct != (Datatype *)0) return ct;
|
||||
XmlDecode decoder(glb);
|
||||
ArchitectureGhidra *ghidra = (ArchitectureGhidra *)glb;
|
||||
PackedDecode decoder(ghidra);
|
||||
try {
|
||||
if (!((ArchitectureGhidra *)glb)->getType(n,id,decoder)) // See if ghidra knows about type
|
||||
if (!ghidra->getDataType(n,id,decoder)) // See if ghidra knows about type
|
||||
return (Datatype *)0;
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
throw LowlevelError("XML error: "+err.explain);
|
||||
catch(DecoderError &err) {
|
||||
throw LowlevelError("Decoder error: "+err.explain);
|
||||
}
|
||||
ct = decodeType(decoder); // Parse ghidra's type
|
||||
return ct;
|
||||
|
|
|
@ -2287,7 +2287,7 @@ const string &Element::getAttributeValue(const string &nm) const
|
|||
for(uint4 i=0;i<attr.size();++i)
|
||||
if (attr[i] == nm)
|
||||
return value[i];
|
||||
throw XmlError("Unknown attribute: "+nm);
|
||||
throw DecoderError("Unknown attribute: "+nm);
|
||||
}
|
||||
|
||||
DocumentStorage::~DocumentStorage(void)
|
||||
|
@ -2312,7 +2312,7 @@ Document *DocumentStorage::openDocument(const string &filename)
|
|||
{
|
||||
ifstream s(filename.c_str());
|
||||
if (!s)
|
||||
throw XmlError("Unable to open xml document "+filename);
|
||||
throw DecoderError("Unable to open xml document "+filename);
|
||||
Document *res = parseDocument(s);
|
||||
s.close();
|
||||
return res;
|
||||
|
@ -2342,7 +2342,7 @@ Document *xml_tree(istream &i)
|
|||
TreeHandler handle(doc);
|
||||
if (0!=xml_parse(i,&handle)) {
|
||||
delete doc;
|
||||
throw XmlError(handle.getError());
|
||||
throw DecoderError(handle.getError());
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
|
|
@ -285,9 +285,9 @@ public:
|
|||
///
|
||||
/// This object holds the error message as passed to the SAX interface callback
|
||||
/// and is thrown as a formal exception.
|
||||
struct XmlError {
|
||||
struct DecoderError {
|
||||
string explain; ///< Explanatory string
|
||||
XmlError(const string &s) { explain = s; } ///< Constructor
|
||||
DecoderError(const string &s) { explain = s; } ///< Constructor
|
||||
};
|
||||
|
||||
/// \brief Start-up the XML parser given a stream and a handler
|
||||
|
|
|
@ -565,7 +565,7 @@ const string &Element::getAttributeValue(const string &nm) const
|
|||
for(uint4 i=0;i<attr.size();++i)
|
||||
if (attr[i] == nm)
|
||||
return value[i];
|
||||
throw XmlError("Unknown attribute: "+nm);
|
||||
throw DecoderError("Unknown attribute: "+nm);
|
||||
}
|
||||
|
||||
DocumentStorage::~DocumentStorage(void)
|
||||
|
@ -590,7 +590,7 @@ Document *DocumentStorage::openDocument(const string &filename)
|
|||
{
|
||||
ifstream s(filename.c_str());
|
||||
if (!s)
|
||||
throw XmlError("Unable to open xml document "+filename);
|
||||
throw DecoderError("Unable to open xml document "+filename);
|
||||
Document *res = parseDocument(s);
|
||||
s.close();
|
||||
return res;
|
||||
|
@ -620,7 +620,7 @@ Document *xml_tree(istream &i)
|
|||
TreeHandler handle(doc);
|
||||
if (0!=xml_parse(i,&handle)) {
|
||||
delete doc;
|
||||
throw XmlError(handle.getError());
|
||||
throw DecoderError(handle.getError());
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue