Merge remote-tracking branch 'origin/GP-3174_PieceMarshaling'

This commit is contained in:
Ryan Kurtz 2023-03-14 06:26:22 -04:00
commit 67625f5b9c
16 changed files with 162 additions and 66 deletions

View file

@ -45,6 +45,8 @@ import ghidra.xml.XmlParseException;
* The static restoreXML methods read an \<addr> tag and produce a general AddressXML object.
*/
public class AddressXML {
public static int MAX_PIECES = 64; // Maximum pieces that can be marshaled in one join address
private AddressSpace space; // Address space containing the memory range
private long offset; // Starting offset of the range
private long size; // Number of bytes in the size
@ -596,32 +598,13 @@ public class AddressXML {
AddressXML.encode(encoder, varnodes[0].getAddress(), varnodes[0].getSize());
return;
}
if (varnodes.length > MAX_PIECES) {
throw new IOException("Exceeded maximum pieces in one join address");
}
encoder.openElement(ELEM_ADDR);
encoder.writeSpace(ATTRIB_SPACE, AddressSpace.VARIABLE_SPACE);
encoder.writeString(ATTRIB_PIECE1, varnodes[0].encodePiece());
if (varnodes.length > 1) {
encoder.writeString(ATTRIB_PIECE2, varnodes[1].encodePiece());
}
if (varnodes.length > 2) {
encoder.writeString(ATTRIB_PIECE3, varnodes[2].encodePiece());
}
if (varnodes.length > 3) {
encoder.writeString(ATTRIB_PIECE4, varnodes[3].encodePiece());
}
if (varnodes.length > 4) {
encoder.writeString(ATTRIB_PIECE5, varnodes[4].encodePiece());
}
if (varnodes.length > 5) {
encoder.writeString(ATTRIB_PIECE6, varnodes[5].encodePiece());
}
if (varnodes.length > 6) {
encoder.writeString(ATTRIB_PIECE7, varnodes[6].encodePiece());
}
if (varnodes.length > 7) {
encoder.writeString(ATTRIB_PIECE8, varnodes[7].encodePiece());
}
if (varnodes.length > 8) {
encoder.writeString(ATTRIB_PIECE9, varnodes[8].encodePiece());
for (int i = 0; i < varnodes.length; ++i) {
encoder.writeStringIndexed(ATTRIB_PIECE, i, varnodes[i].encodePiece());
}
if (logicalsize != 0) {
encoder.writeUnsignedInteger(ATTRIB_LOGICALSIZE, logicalsize);

View file

@ -175,15 +175,7 @@ public record AttributeId(String name, int id) {
public static final AttributeId ATTRIB_DELAY = new AttributeId("delay", 91);
public static final AttributeId ATTRIB_LOGICALSIZE = new AttributeId("logicalsize", 92);
public static final AttributeId ATTRIB_PHYSICAL = new AttributeId("physical", 93);
public static final AttributeId ATTRIB_PIECE1 = new AttributeId("piece1", 94); // piece attributes must have sequential ids
public static final AttributeId ATTRIB_PIECE2 = new AttributeId("piece2", 95);
public static final AttributeId ATTRIB_PIECE3 = new AttributeId("piece3", 96);
public static final AttributeId ATTRIB_PIECE4 = new AttributeId("piece4", 97);
public static final AttributeId ATTRIB_PIECE5 = new AttributeId("piece5", 98);
public static final AttributeId ATTRIB_PIECE6 = new AttributeId("piece6", 99);
public static final AttributeId ATTRIB_PIECE7 = new AttributeId("piece7", 100);
public static final AttributeId ATTRIB_PIECE8 = new AttributeId("piece8", 101);
public static final AttributeId ATTRIB_PIECE9 = new AttributeId("piece9", 102);
public static final AttributeId ATTRIB_PIECE = new AttributeId("piece", 94);
// architecture
public static final AttributeId ATTRIB_ADJUSTVMA = new AttributeId("adjustvma", 103);

View file

@ -92,6 +92,17 @@ public interface Decoder extends ByteIngest {
*/
public int getNextAttributeId() throws DecoderException;
/**
* Get the id for the (current) attribute, assuming it is indexed.
* Assuming the previous call to getNextAttributeId() returned the id of ATTRIB_UNKNOWN,
* reinterpret the attribute as being an indexed form of the given attribute. If the attribute
* matches, return this indexed id, otherwise return ATTRIB_UNKNOWN.
* @param attribId is the attribute being indexed
* @return the indexed id or ATTRIB_UNKNOWN
* @throws DecoderException for unexpected end of stream
*/
public int getIndexedAttributeId(AttributeId attribId) throws DecoderException;
/**
* Reset attribute traversal for the current element
* Attributes for a single element can be traversed more than once using the getNextAttributeId

View file

@ -93,6 +93,19 @@ public interface Encoder {
*/
void writeString(AttributeId attribId, String val) throws IOException;
/**
* Write an annotated string, using an indexed attribute, into the encoding.
* Multiple attributes with a shared name can be written to the same element by calling this
* method multiple times with a different index value. The encoding will use attribute ids up
* to the base id plus the maximum index passed in. Implementors must be careful to not use
* other attributes with ids bigger than the base id within the element taking the indexed attribute.
* @param attribId is the shared AttributeId
* @param index is the unique index to associated with the string
* @param val is the string to encode
* @throws IOException for errors in the underlying stream
*/
void writeStringIndexed(AttributeId attribId, int index, String val) throws IOException;
/**
* Write an address space reference into the encoding
* The address space is associated with the given AttributeId annotation and the current open element.

View file

@ -310,6 +310,11 @@ public class PackedDecode implements Decoder {
return id;
}
@Override
public int getIndexedAttributeId(AttributeId attribId) throws DecoderException {
return AttributeId.ATTRIB_UNKNOWN.id();
}
@Override
public void rewindAttributes() {
curPos.copy(startPos);

View file

@ -165,6 +165,14 @@ public class PackedEncode implements PatchEncoder {
outStream.write(bytes);
}
@Override
public void writeStringIndexed(AttributeId attribId, int index, String val) throws IOException {
byte[] bytes = val.getBytes();
writeHeader(ATTRIBUTE, attribId.id() + index);
writeInteger((TYPECODE_STRING << TYPECODE_SHIFT), bytes.length);
outStream.write(bytes);
}
@Override
public void writeSpace(AttributeId attribId, AddressSpace spc) throws IOException {
writeHeader(ATTRIBUTE, attribId.id());

View file

@ -497,8 +497,15 @@ public class Varnode {
if (attribId == 0) {
break;
}
else if (attribId >= ATTRIB_PIECE1.id() && attribId <= ATTRIB_PIECE9.id()) {
int index = attribId - ATTRIB_PIECE1.id();
else if (attribId == ATTRIB_UNKNOWN.id()) {
attribId = decoder.getIndexedAttributeId(ATTRIB_PIECE);
}
if (attribId >= ATTRIB_PIECE.id()) {
int index = attribId - ATTRIB_PIECE.id();
if (index > AddressXML.MAX_PIECES) {
continue;
}
if (index != list.size()) {
throw new DecoderException("\"piece\" attributes must be in order");
}

View file

@ -144,6 +144,16 @@ public class XmlEncode implements Encoder {
buffer.append("\"");
}
@Override
public void writeStringIndexed(AttributeId attribId, int index, String val) throws IOException {
buffer.append(' ');
buffer.append(attribId.name());
buffer.append(index + 1);
buffer.append("=\"");
SpecXmlUtils.xmlEscape(buffer, val);
buffer.append("\"");
}
@Override
public void writeSpace(AttributeId attribId, AddressSpace spc) throws IOException {
String spcName;