mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-4285 Compressed SLEIGH
This commit is contained in:
parent
b380fd5fa6
commit
8fbd171cdf
207 changed files with 15233 additions and 6055 deletions
|
@ -24,6 +24,9 @@ unordered_map<string,uint4> AttributeId::lookupAttributeId;
|
|||
|
||||
const int4 PackedDecode::BUFFER_SIZE = 1024;
|
||||
|
||||
const char XmlEncode::spaces[] = "\n ";
|
||||
const int4 XmlEncode::MAX_SPACES = 24+1;
|
||||
|
||||
/// 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
|
||||
|
@ -38,11 +41,13 @@ vector<AttributeId *> &AttributeId::getList(void)
|
|||
/// in the global hashtable.
|
||||
/// \param nm is the name of the attribute
|
||||
/// \param i is an id to associate with the attribute
|
||||
AttributeId::AttributeId(const string &nm,uint4 i)
|
||||
/// \param scope is an id for the scope of this attribute
|
||||
AttributeId::AttributeId(const string &nm,uint4 i,int4 scope)
|
||||
: name(nm)
|
||||
{
|
||||
id = i;
|
||||
getList().push_back(this);
|
||||
if (scope == 0)
|
||||
getList().push_back(this);
|
||||
}
|
||||
|
||||
/// Fill the hashtable mapping attribute names to their id, from registered attribute objects
|
||||
|
@ -78,11 +83,13 @@ vector<ElementId *> &ElementId::getList(void)
|
|||
/// in the global hashtable.
|
||||
/// \param nm is the name of the element
|
||||
/// \param i is an id to associate with the element
|
||||
ElementId::ElementId(const string &nm,uint4 i)
|
||||
/// \param scope is an id for the scope of this element
|
||||
ElementId::ElementId(const string &nm,uint4 i,int4 scope)
|
||||
: name(nm)
|
||||
{
|
||||
id = i;
|
||||
getList().push_back(this);
|
||||
if (scope == 0)
|
||||
getList().push_back(this);
|
||||
}
|
||||
|
||||
/// Fill the hashtable mapping element names to their id, from registered element objects
|
||||
|
@ -132,7 +139,7 @@ uint4 XmlDecode::peekElement(void)
|
|||
return 0;
|
||||
el = *iter;
|
||||
}
|
||||
return ElementId::find(el->getName());
|
||||
return ElementId::find(el->getName(),scope);
|
||||
}
|
||||
|
||||
uint4 XmlDecode::openElement(void)
|
||||
|
@ -156,7 +163,7 @@ uint4 XmlDecode::openElement(void)
|
|||
elStack.push_back(el);
|
||||
iterStack.push_back(el->getChildren().begin());
|
||||
attributeIndex = -1;
|
||||
return ElementId::find(el->getName());
|
||||
return ElementId::find(el->getName(),scope);
|
||||
}
|
||||
|
||||
uint4 XmlDecode::openElement(const ElementId &elemId)
|
||||
|
@ -194,7 +201,7 @@ void XmlDecode::closeElement(uint4 id)
|
|||
const Element *el = elStack.back();
|
||||
if (iterStack.back() != el->getChildren().end())
|
||||
throw DecoderError("Closing element <" + el->getName() + "> with additional children");
|
||||
if (ElementId::find(el->getName()) != id)
|
||||
if (ElementId::find(el->getName(), scope) != id)
|
||||
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
|
@ -207,7 +214,7 @@ void XmlDecode::closeElementSkipping(uint4 id)
|
|||
{
|
||||
#ifdef CPUI_DEBUG
|
||||
const Element *el = elStack.back();
|
||||
if (ElementId::find(el->getName()) != id)
|
||||
if (ElementId::find(el->getName(), scope) != id)
|
||||
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
|
@ -228,7 +235,7 @@ uint4 XmlDecode::getNextAttributeId(void)
|
|||
int4 nextIndex = attributeIndex + 1;
|
||||
if (nextIndex < el->getNumAttributes()) {
|
||||
attributeIndex = nextIndex;
|
||||
return AttributeId::find(el->getAttributeName(attributeIndex));
|
||||
return AttributeId::find(el->getAttributeName(attributeIndex),scope);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -419,40 +426,89 @@ AddrSpace *XmlDecode::readSpace(const AttributeId &attribId)
|
|||
return res;
|
||||
}
|
||||
|
||||
OpCode XmlDecode::readOpcode(void)
|
||||
|
||||
{
|
||||
const Element *el = elStack.back();
|
||||
string nm = el->getAttributeValue(attributeIndex);
|
||||
OpCode opc = get_opcode(nm);
|
||||
if (opc == (OpCode)0)
|
||||
throw DecoderError("Bad encoded OpCode");
|
||||
return opc;
|
||||
}
|
||||
|
||||
OpCode XmlDecode::readOpcode(AttributeId &attribId)
|
||||
|
||||
{
|
||||
const Element *el = elStack.back();
|
||||
string nm;
|
||||
if (attribId == ATTRIB_CONTENT) {
|
||||
nm = el->getContent();
|
||||
}
|
||||
else {
|
||||
int4 index = findMatchingAttribute(el, attribId.getName());
|
||||
nm = el->getAttributeValue(index);
|
||||
}
|
||||
OpCode opc = get_opcode(nm);
|
||||
if (opc == (OpCode)0)
|
||||
throw DecoderError("Bad encoded OpCode");
|
||||
return opc;
|
||||
}
|
||||
|
||||
void XmlEncode::newLine(void)
|
||||
|
||||
{
|
||||
if (!doFormatting)
|
||||
return;
|
||||
|
||||
int numSpaces = depth * 2 + 1;
|
||||
if (numSpaces > MAX_SPACES) {
|
||||
numSpaces = MAX_SPACES;
|
||||
}
|
||||
outStream.write(spaces,numSpaces);
|
||||
}
|
||||
|
||||
void XmlEncode::openElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
if (elementTagIsOpen)
|
||||
if (tagStatus == tag_start)
|
||||
outStream << '>';
|
||||
else
|
||||
elementTagIsOpen = true;
|
||||
tagStatus = tag_start;
|
||||
newLine();
|
||||
outStream << '<' << elemId.getName();
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
void XmlEncode::closeElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
if (elementTagIsOpen) {
|
||||
depth -= 1;
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << "/>";
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
else {
|
||||
outStream << "</" << elemId.getName() << '>';
|
||||
tagStatus = tag_stop;
|
||||
return;
|
||||
}
|
||||
if (tagStatus != tag_content)
|
||||
newLine();
|
||||
else
|
||||
tagStatus = tag_stop;
|
||||
|
||||
outStream << "</" << elemId.getName() << '>';
|
||||
}
|
||||
|
||||
void XmlEncode::writeBool(const AttributeId &attribId,bool val)
|
||||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
if (val)
|
||||
outStream << "true";
|
||||
else
|
||||
outStream << "false";
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
a_v_b(outStream, attribId.getName(), val);
|
||||
|
@ -462,11 +518,11 @@ void XmlEncode::writeSignedInteger(const AttributeId &attribId,intb val)
|
|||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
outStream << dec << val;
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
a_v_i(outStream, attribId.getName(), val);
|
||||
|
@ -476,11 +532,11 @@ void XmlEncode::writeUnsignedInteger(const AttributeId &attribId,uintb val)
|
|||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
outStream << hex << "0x" << val;
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
a_v_u(outStream, attribId.getName(), val);
|
||||
|
@ -490,11 +546,11 @@ void XmlEncode::writeString(const AttributeId &attribId,const string &val)
|
|||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
xml_escape(outStream, val.c_str());
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
a_v(outStream,attribId.getName(),val);
|
||||
|
@ -514,16 +570,33 @@ void XmlEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
|
|||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
xml_escape(outStream, spc->getName().c_str());
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
a_v(outStream,attribId.getName(),spc->getName());
|
||||
}
|
||||
|
||||
void XmlEncode::writeOpcode(const AttributeId &attribId,OpCode opc)
|
||||
|
||||
{
|
||||
const char *name = get_opname(opc);
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
}
|
||||
outStream << name;
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
outStream << ' ' << attribId.getName() << "=\"";
|
||||
outStream << name;
|
||||
outStream << "\"";
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -598,6 +671,27 @@ void PackedDecode::skipAttributeRemaining(uint1 typeByte)
|
|||
advancePosition(curPos, length); // Skip -length- data
|
||||
}
|
||||
|
||||
/// Set decoder to beginning of the stream. Add padding to end of the stream.
|
||||
/// \param bufPos is the number of bytes used by the last input buffer
|
||||
void PackedDecode::endIngest(int4 bufPos)
|
||||
|
||||
{
|
||||
endPos.seqIter = inStream.begin(); // Set position to beginning of stream
|
||||
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 (bufPos == BUFFER_SIZE) {
|
||||
// Last buffer was entirely filled
|
||||
uint1 *endbuf = new uint1[1]; // Add one more buffer
|
||||
inStream.emplace_back(endbuf,endbuf + 1);
|
||||
bufPos = 0;
|
||||
}
|
||||
uint1 *buf = inStream.back().start;
|
||||
buf[bufPos] = ELEMENT_END;
|
||||
}
|
||||
}
|
||||
|
||||
PackedDecode::~PackedDecode(void)
|
||||
|
||||
{
|
||||
|
@ -612,25 +706,11 @@ 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);
|
||||
uint1 *buf = allocateNextInputBuffer(1);
|
||||
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;
|
||||
}
|
||||
endIngest(gcount);
|
||||
}
|
||||
|
||||
uint4 PackedDecode::peekElement(void)
|
||||
|
@ -959,6 +1039,24 @@ AddrSpace *PackedDecode::readSpace(const AttributeId &attribId)
|
|||
return res;
|
||||
}
|
||||
|
||||
OpCode PackedDecode::readOpcode(void)
|
||||
|
||||
{
|
||||
int4 val = (int4)readSignedInteger();
|
||||
if (val < 0 || val >= CPUI_MAX)
|
||||
throw DecoderError("Bad encoded OpCode");
|
||||
return (OpCode)val;
|
||||
}
|
||||
|
||||
OpCode PackedDecode::readOpcode(AttributeId &attribId)
|
||||
|
||||
{
|
||||
findMatchingAttribute(attribId);
|
||||
OpCode opc = readOpcode();
|
||||
curPos = startPos;
|
||||
return opc;
|
||||
}
|
||||
|
||||
/// The value is either an unsigned integer, an address space index, or (the absolute value of) a signed integer.
|
||||
/// A type header is passed in with the particular type code for the value already filled in.
|
||||
/// This method then fills in the length code, outputs the full type header and the encoded bytes of the integer.
|
||||
|
@ -973,7 +1071,7 @@ void PackedEncode::writeInteger(uint1 typeByte,uint8 val)
|
|||
lenCode = 0;
|
||||
sa = -1;
|
||||
}
|
||||
if (val < 0x800000000) {
|
||||
else if (val < 0x800000000) {
|
||||
if (val < 0x200000) {
|
||||
if (val < 0x80) {
|
||||
lenCode = 1; // 7-bits
|
||||
|
@ -1119,6 +1217,13 @@ void PackedEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
|
|||
}
|
||||
}
|
||||
|
||||
void PackedEncode::writeOpcode(const AttributeId &attribId,OpCode opc)
|
||||
|
||||
{
|
||||
writeHeader(ATTRIBUTE, attribId.getId());
|
||||
writeInteger((TYPECODE_SIGNEDINT_POSITIVE << TYPECODE_SHIFT), opc);
|
||||
}
|
||||
|
||||
// Common attributes. Attributes with multiple uses
|
||||
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
|
||||
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue