GP-2262 Encoder

This commit is contained in:
caheckman 2022-07-12 19:07:37 -04:00
parent ae79857b42
commit aa038c3636
96 changed files with 2701 additions and 2484 deletions

View file

@ -29,46 +29,48 @@ vector<ArchitectureCapability *> ArchitectureCapability::thelist;
const uint4 ArchitectureCapability::majorversion = 4; const uint4 ArchitectureCapability::majorversion = 4;
const uint4 ArchitectureCapability::minorversion = 1; const uint4 ArchitectureCapability::minorversion = 1;
AttributeId ATTRIB_ADJUSTVMA = AttributeId("adjustvma",30); AttributeId ATTRIB_ADJUSTVMA = AttributeId("adjustvma",103);
AttributeId ATTRIB_ENABLE = AttributeId("enable",31); AttributeId ATTRIB_ENABLE = AttributeId("enable",104);
AttributeId ATTRIB_GROUP = AttributeId("group",32); AttributeId ATTRIB_GROUP = AttributeId("group",105);
AttributeId ATTRIB_GROWTH = AttributeId("growth",33); AttributeId ATTRIB_GROWTH = AttributeId("growth",106);
AttributeId ATTRIB_LOADERSYMBOLS = AttributeId("loadersymbols",34); AttributeId ATTRIB_KEY = AttributeId("key",107);
AttributeId ATTRIB_PARENT = AttributeId("parent",35); AttributeId ATTRIB_LOADERSYMBOLS = AttributeId("loadersymbols",108);
AttributeId ATTRIB_REGISTER = AttributeId("register",36); AttributeId ATTRIB_PARENT = AttributeId("parent",109);
AttributeId ATTRIB_REVERSEJUSTIFY = AttributeId("reversejustify",37); AttributeId ATTRIB_REGISTER = AttributeId("register",110);
AttributeId ATTRIB_SIGNEXT = AttributeId("signext",38); AttributeId ATTRIB_REVERSEJUSTIFY = AttributeId("reversejustify",111);
AttributeId ATTRIB_STYLE = AttributeId("style",39); AttributeId ATTRIB_SIGNEXT = AttributeId("signext",112);
AttributeId ATTRIB_STYLE = AttributeId("style",113);
ElementId ELEM_ADDRESS_SHIFT_AMOUNT = ElementId("address_shift_amount",17); ElementId ELEM_ADDRESS_SHIFT_AMOUNT = ElementId("address_shift_amount",130);
ElementId ELEM_AGGRESSIVETRIM = ElementId("aggressivetrim",18); ElementId ELEM_AGGRESSIVETRIM = ElementId("aggressivetrim",131);
ElementId ELEM_COMPILER_SPEC = ElementId("compiler_spec",19); ElementId ELEM_COMPILER_SPEC = ElementId("compiler_spec",132);
ElementId ELEM_DATA_SPACE = ElementId("data_space",20); ElementId ELEM_DATA_SPACE = ElementId("data_space",133);
ElementId ELEM_DEFAULT_MEMORY_BLOCKS = ElementId("default_memory_blocks",21); ElementId ELEM_DEFAULT_MEMORY_BLOCKS = ElementId("default_memory_blocks",134);
ElementId ELEM_DEFAULT_PROTO = ElementId("default_proto",22); ElementId ELEM_DEFAULT_PROTO = ElementId("default_proto",135);
ElementId ELEM_DEFAULT_SYMBOLS = ElementId("default_symbols",23); ElementId ELEM_DEFAULT_SYMBOLS = ElementId("default_symbols",136);
ElementId ELEM_EVAL_CALLED_PROTOTYPE = ElementId("eval_called_prototype",24); ElementId ELEM_EVAL_CALLED_PROTOTYPE = ElementId("eval_called_prototype",137);
ElementId ELEM_EVAL_CURRENT_PROTOTYPE = ElementId("eval_current_prototype",25); ElementId ELEM_EVAL_CURRENT_PROTOTYPE = ElementId("eval_current_prototype",138);
ElementId ELEM_EXPERIMENTAL_RULES = ElementId("experimental_rules",26); ElementId ELEM_EXPERIMENTAL_RULES = ElementId("experimental_rules",139);
ElementId ELEM_FLOWOVERRIDELIST = ElementId("flowoverridelist",27); ElementId ELEM_FLOWOVERRIDELIST = ElementId("flowoverridelist",140);
ElementId ELEM_FUNCPTR = ElementId("funcptr",28); ElementId ELEM_FUNCPTR = ElementId("funcptr",141);
ElementId ELEM_GLOBAL = ElementId("global",29); ElementId ELEM_GLOBAL = ElementId("global",142);
ElementId ELEM_INCIDENTALCOPY = ElementId("incidentalcopy",30); ElementId ELEM_INCIDENTALCOPY = ElementId("incidentalcopy",143);
ElementId ELEM_INFERPTRBOUNDS = ElementId("inferptrbounds",31); ElementId ELEM_INFERPTRBOUNDS = ElementId("inferptrbounds",144);
ElementId ELEM_MODELALIAS = ElementId("modelalias",32); ElementId ELEM_MODELALIAS = ElementId("modelalias",145);
ElementId ELEM_NOHIGHPTR = ElementId("nohighptr",33); ElementId ELEM_NOHIGHPTR = ElementId("nohighptr",146);
ElementId ELEM_PROCESSOR_SPEC = ElementId("processor_spec",34); ElementId ELEM_PROCESSOR_SPEC = ElementId("processor_spec",147);
ElementId ELEM_PROGRAMCOUNTER = ElementId("programcounter",35); ElementId ELEM_PROGRAMCOUNTER = ElementId("programcounter",148);
ElementId ELEM_PROPERTIES = ElementId("properties",36); ElementId ELEM_PROPERTIES = ElementId("properties",149);
ElementId ELEM_READONLY = ElementId("readonly",37); ElementId ELEM_PROPERTY = ElementId("property",150);
ElementId ELEM_REGISTER_DATA = ElementId("register_data",38); ElementId ELEM_READONLY = ElementId("readonly",151);
ElementId ELEM_RULE = ElementId("rule",39); ElementId ELEM_REGISTER_DATA = ElementId("register_data",152);
ElementId ELEM_SAVE_STATE = ElementId("save_state",40); ElementId ELEM_RULE = ElementId("rule",153);
ElementId ELEM_SEGMENTED_ADDRESS = ElementId("segmented_address",41); ElementId ELEM_SAVE_STATE = ElementId("save_state",154);
ElementId ELEM_SPACEBASE = ElementId("spacebase",42); ElementId ELEM_SEGMENTED_ADDRESS = ElementId("segmented_address",155);
ElementId ELEM_SPECEXTENSIONS = ElementId("specextensions",43); ElementId ELEM_SPACEBASE = ElementId("spacebase",156);
ElementId ELEM_STACKPOINTER = ElementId("stackpointer",44); ElementId ELEM_SPECEXTENSIONS = ElementId("specextensions",157);
ElementId ELEM_VOLATILE = ElementId("volatile",45); ElementId ELEM_STACKPOINTER = ElementId("stackpointer",158);
ElementId ELEM_VOLATILE = ElementId("volatile",159);
/// This builds a list of just the ArchitectureCapability extensions /// This builds a list of just the ArchitectureCapability extensions
void ArchitectureCapability::initialize(void) void ArchitectureCapability::initialize(void)

View file

@ -65,6 +65,7 @@ extern AttributeId ATTRIB_ADJUSTVMA; ///< Marshaling attribute "adjustvma"
extern AttributeId ATTRIB_ENABLE; ///< Marshaling attribute "enable" extern AttributeId ATTRIB_ENABLE; ///< Marshaling attribute "enable"
extern AttributeId ATTRIB_GROUP; ///< Marshaling attribute "group" extern AttributeId ATTRIB_GROUP; ///< Marshaling attribute "group"
extern AttributeId ATTRIB_GROWTH; ///< Marshaling attribute "growth" extern AttributeId ATTRIB_GROWTH; ///< Marshaling attribute "growth"
extern AttributeId ATTRIB_KEY; ///< Marshaling attribute "key"
extern AttributeId ATTRIB_LOADERSYMBOLS; ///< Marshaling attribute "loadersymbols" extern AttributeId ATTRIB_LOADERSYMBOLS; ///< Marshaling attribute "loadersymbols"
extern AttributeId ATTRIB_PARENT; ///< Marshaling attribute "parent" extern AttributeId ATTRIB_PARENT; ///< Marshaling attribute "parent"
extern AttributeId ATTRIB_REGISTER; ///< Marshaling attribute "register" extern AttributeId ATTRIB_REGISTER; ///< Marshaling attribute "register"
@ -92,6 +93,7 @@ extern ElementId ELEM_NOHIGHPTR; ///< Marshaling element \<nohighptr>
extern ElementId ELEM_PROCESSOR_SPEC; ///< Marshaling element \<processor_spec> extern ElementId ELEM_PROCESSOR_SPEC; ///< Marshaling element \<processor_spec>
extern ElementId ELEM_PROGRAMCOUNTER; ///< Marshaling element \<programcounter> extern ElementId ELEM_PROGRAMCOUNTER; ///< Marshaling element \<programcounter>
extern ElementId ELEM_PROPERTIES; ///< Marshaling element \<properties> extern ElementId ELEM_PROPERTIES; ///< Marshaling element \<properties>
extern ElementId ELEM_PROPERTY; ///< Marshaling element \<property>
extern ElementId ELEM_READONLY; ///< Marshaling element \<readonly> extern ElementId ELEM_READONLY; ///< Marshaling element \<readonly>
extern ElementId ELEM_REGISTER_DATA; ///< Marshaling element \<register_data> extern ElementId ELEM_REGISTER_DATA; ///< Marshaling element \<register_data>
extern ElementId ELEM_RULE; ///< Marshaling element \<rule> extern ElementId ELEM_RULE; ///< Marshaling element \<rule>

View file

@ -19,7 +19,7 @@
// Constructing this object registers capability // Constructing this object registers capability
BfdArchitectureCapability BfdArchitectureCapability::bfdArchitectureCapability; BfdArchitectureCapability BfdArchitectureCapability::bfdArchitectureCapability;
ElementId ELEM_BFD_SAVEFILE = ElementId("bfd_savefile",46); ElementId ELEM_BFD_SAVEFILE = ElementId("bfd_savefile",238);
BfdArchitectureCapability::BfdArchitectureCapability(void) BfdArchitectureCapability::BfdArchitectureCapability(void)

View file

@ -17,16 +17,16 @@
#include "block.hh" #include "block.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_ALTINDEX = AttributeId("altindex",40); AttributeId ATTRIB_ALTINDEX = AttributeId("altindex",75);
AttributeId ATTRIB_DEPTH = AttributeId("depth",41); AttributeId ATTRIB_DEPTH = AttributeId("depth",76);
AttributeId ATTRIB_END = AttributeId("end",42); AttributeId ATTRIB_END = AttributeId("end",77);
AttributeId ATTRIB_OPCODE = AttributeId("opcode",43); AttributeId ATTRIB_OPCODE = AttributeId("opcode",78);
AttributeId ATTRIB_REV = AttributeId("rev",44); AttributeId ATTRIB_REV = AttributeId("rev",79);
ElementId ELEM_BHEAD = ElementId("bhead",47); ElementId ELEM_BHEAD = ElementId("bhead",102);
ElementId ELEM_BLOCK = ElementId("block",48); ElementId ELEM_BLOCK = ElementId("block",103);
ElementId ELEM_BLOCKEDGE = ElementId("blockedge",49); ElementId ELEM_BLOCKEDGE = ElementId("blockedge",104);
ElementId ELEM_EDGE = ElementId("edge",50); ElementId ELEM_EDGE = ElementId("edge",105);
/// The edge is saved assuming we already know what block we are in. /// The edge is saved assuming we already know what block we are in.
/// \param encoder is the stream encoder /// \param encoder is the stream encoder

View file

@ -16,8 +16,8 @@
#include "callgraph.hh" #include "callgraph.hh"
#include "funcdata.hh" #include "funcdata.hh"
ElementId ELEM_CALLGRAPH = ElementId("callgraph",51); ElementId ELEM_CALLGRAPH = ElementId("callgraph",226);
ElementId ELEM_NODE = ElementId("node",52); ElementId ELEM_NODE = ElementId("node",227);
void CallGraphEdge::encode(Encoder &encoder) const void CallGraphEdge::encode(Encoder &encoder) const

View file

@ -16,9 +16,9 @@
#include "comment.hh" #include "comment.hh"
#include "funcdata.hh" #include "funcdata.hh"
ElementId ELEM_COMMENT = ElementId("comment",53); ElementId ELEM_COMMENT = ElementId("comment",86);
ElementId ELEM_COMMENTDB = ElementId("commentdb",54); ElementId ELEM_COMMENTDB = ElementId("commentdb",87);
ElementId ELEM_TEXT = ElementId("text",55); ElementId ELEM_TEXT = ElementId("text",88);
/// \param tp is the set of properties to associate with the comment (or 0 for no properties) /// \param tp is the set of properties to associate with the comment (or 0 for no properties)
/// \param fad is the Address of the function containing the comment /// \param fad is the Address of the function containing the comment

View file

@ -15,15 +15,15 @@
*/ */
#include "cpool.hh" #include "cpool.hh"
AttributeId ATTRIB_A = AttributeId("a",45); AttributeId ATTRIB_A = AttributeId("a",80);
AttributeId ATTRIB_B = AttributeId("b",46); AttributeId ATTRIB_B = AttributeId("b",81);
AttributeId ATTRIB_LENGTH = AttributeId("length",47); AttributeId ATTRIB_LENGTH = AttributeId("length",82);
AttributeId ATTRIB_TAG = AttributeId("tag",48); AttributeId ATTRIB_TAG = AttributeId("tag",83);
ElementId ELEM_CONSTANTPOOL = ElementId("constantpool",56); ElementId ELEM_CONSTANTPOOL = ElementId("constantpool",109);
ElementId ELEM_CPOOLREC = ElementId("cpoolrec",57); ElementId ELEM_CPOOLREC = ElementId("cpoolrec",110);
ElementId ELEM_REF = ElementId("ref",58); ElementId ELEM_REF = ElementId("ref",111);
ElementId ELEM_TOKEN = ElementId("token",59); ElementId ELEM_TOKEN = ElementId("token",112);
/// Encode the constant pool object description as a \<cpoolrec> element. /// Encode the constant pool object description as a \<cpoolrec> element.
/// \param encoder is the stream encoder /// \param encoder is the stream encoder

View file

@ -18,27 +18,27 @@
#include "crc32.hh" #include "crc32.hh"
#include <ctype.h> #include <ctype.h>
AttributeId ATTRIB_CAT = AttributeId("cat",49); AttributeId ATTRIB_CAT = AttributeId("cat",61);
AttributeId ATTRIB_FIELD = AttributeId("field",50); AttributeId ATTRIB_FIELD = AttributeId("field",62);
AttributeId ATTRIB_MERGE = AttributeId("merge",51); AttributeId ATTRIB_MERGE = AttributeId("merge",63);
AttributeId ATTRIB_SCOPEIDBYNAME = AttributeId("scopeidbyname",52); AttributeId ATTRIB_SCOPEIDBYNAME = AttributeId("scopeidbyname",64);
AttributeId ATTRIB_VOLATILE = AttributeId("volatile",53); AttributeId ATTRIB_VOLATILE = AttributeId("volatile",65);
ElementId ELEM_COLLISION = ElementId("collision",60); ElementId ELEM_COLLISION = ElementId("collision",67);
ElementId ELEM_DB = ElementId("db",61); ElementId ELEM_DB = ElementId("db",68);
ElementId ELEM_EQUATESYMBOL = ElementId("equatesymbol",62); ElementId ELEM_EQUATESYMBOL = ElementId("equatesymbol",69);
ElementId ELEM_EXTERNREFSYMBOL = ElementId("externrefsymbol",63); ElementId ELEM_EXTERNREFSYMBOL = ElementId("externrefsymbol",70);
ElementId ELEM_FACETSYMBOL = ElementId("facetsymbol",64); ElementId ELEM_FACETSYMBOL = ElementId("facetsymbol",71);
ElementId ELEM_FUNCTIONSHELL = ElementId("functionshell",65); ElementId ELEM_FUNCTIONSHELL = ElementId("functionshell",72);
ElementId ELEM_HASH = ElementId("hash",66); ElementId ELEM_HASH = ElementId("hash",73);
ElementId ELEM_HOLE = ElementId("hole",67); ElementId ELEM_HOLE = ElementId("hole",74);
ElementId ELEM_LABELSYM = ElementId("labelsym",68); ElementId ELEM_LABELSYM = ElementId("labelsym",75);
ElementId ELEM_MAPSYM = ElementId("mapsym",69); ElementId ELEM_MAPSYM = ElementId("mapsym",76);
ElementId ELEM_PARENT = ElementId("parent",70); ElementId ELEM_PARENT = ElementId("parent",77);
ElementId ELEM_PROPERTY_CHANGEPOINT = ElementId("property_changepoint",71); ElementId ELEM_PROPERTY_CHANGEPOINT = ElementId("property_changepoint",78);
ElementId ELEM_RANGEEQUALSSYMBOLS = ElementId("rangeequalssymbols",72); ElementId ELEM_RANGEEQUALSSYMBOLS = ElementId("rangeequalssymbols",79);
ElementId ELEM_SCOPE = ElementId("scope",73); ElementId ELEM_SCOPE = ElementId("scope",80);
ElementId ELEM_SYMBOLLIST = ElementId("symbollist",74); ElementId ELEM_SYMBOLLIST = ElementId("symbollist",81);
uint8 Symbol::ID_BASE = 0x4000000000000000L; uint8 Symbol::ID_BASE = 0x4000000000000000L;

View file

@ -16,37 +16,37 @@
#include "fspec.hh" #include "fspec.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_CUSTOM = AttributeId("custom",54); AttributeId ATTRIB_CUSTOM = AttributeId("custom",114);
AttributeId ATTRIB_DOTDOTDOT = AttributeId("dotdotdot",55); AttributeId ATTRIB_DOTDOTDOT = AttributeId("dotdotdot",115);
AttributeId ATTRIB_EXTENSION = AttributeId("extension",56); AttributeId ATTRIB_EXTENSION = AttributeId("extension",116);
AttributeId ATTRIB_HASTHIS = AttributeId("hasthis",57); AttributeId ATTRIB_HASTHIS = AttributeId("hasthis",117);
AttributeId ATTRIB_INLINE = AttributeId("inline",58); AttributeId ATTRIB_INLINE = AttributeId("inline",118);
AttributeId ATTRIB_KILLEDBYCALL = AttributeId("killedbycall",59); AttributeId ATTRIB_KILLEDBYCALL = AttributeId("killedbycall",119);
AttributeId ATTRIB_MAXSIZE = AttributeId("maxsize",60); AttributeId ATTRIB_MAXSIZE = AttributeId("maxsize",120);
AttributeId ATTRIB_MINSIZE = AttributeId("minsize",61); AttributeId ATTRIB_MINSIZE = AttributeId("minsize",121);
AttributeId ATTRIB_MODELLOCK = AttributeId("modellock",62); AttributeId ATTRIB_MODELLOCK = AttributeId("modellock",122);
AttributeId ATTRIB_NORETURN = AttributeId("noreturn",63); AttributeId ATTRIB_NORETURN = AttributeId("noreturn",123);
AttributeId ATTRIB_POINTERMAX = AttributeId("pointermax",64); AttributeId ATTRIB_POINTERMAX = AttributeId("pointermax",124);
AttributeId ATTRIB_SEPARATEFLOAT = AttributeId("separatefloat",65); AttributeId ATTRIB_SEPARATEFLOAT = AttributeId("separatefloat",125);
AttributeId ATTRIB_STACKSHIFT = AttributeId("stackshift",66); AttributeId ATTRIB_STACKSHIFT = AttributeId("stackshift",126);
AttributeId ATTRIB_STRATEGY = AttributeId("strategy",67); AttributeId ATTRIB_STRATEGY = AttributeId("strategy",127);
AttributeId ATTRIB_THISBEFORERETPOINTER = AttributeId("thisbeforeretpointer",68); AttributeId ATTRIB_THISBEFORERETPOINTER = AttributeId("thisbeforeretpointer",128);
AttributeId ATTRIB_VOIDLOCK = AttributeId("voidlock",69); AttributeId ATTRIB_VOIDLOCK = AttributeId("voidlock",129);
ElementId ELEM_GROUP = ElementId("group",75); ElementId ELEM_GROUP = ElementId("group",160);
ElementId ELEM_INTERNALLIST = ElementId("internallist",76); ElementId ELEM_INTERNALLIST = ElementId("internallist",161);
ElementId ELEM_KILLEDBYCALL = ElementId("killedbycall",77); ElementId ELEM_KILLEDBYCALL = ElementId("killedbycall",162);
ElementId ELEM_LIKELYTRASH = ElementId("likelytrash",78); ElementId ELEM_LIKELYTRASH = ElementId("likelytrash",163);
ElementId ELEM_LOCALRANGE = ElementId("localrange",79); ElementId ELEM_LOCALRANGE = ElementId("localrange",164);
ElementId ELEM_MODEL = ElementId("model",80); ElementId ELEM_MODEL = ElementId("model",165);
ElementId ELEM_PARAM = ElementId("param",81); ElementId ELEM_PARAM = ElementId("param",166);
ElementId ELEM_PARAMRANGE = ElementId("paramrange",82); ElementId ELEM_PARAMRANGE = ElementId("paramrange",167);
ElementId ELEM_PENTRY = ElementId("pentry",83); ElementId ELEM_PENTRY = ElementId("pentry",168);
ElementId ELEM_PROTOTYPE = ElementId("prototype",84); ElementId ELEM_PROTOTYPE = ElementId("prototype",169);
ElementId ELEM_RESOLVEPROTOTYPE = ElementId("resolveprototype",85); ElementId ELEM_RESOLVEPROTOTYPE = ElementId("resolveprototype",170);
ElementId ELEM_RETPARAM = ElementId("retparam",86); ElementId ELEM_RETPARAM = ElementId("retparam",171);
ElementId ELEM_RETURNSYM = ElementId("returnsym",87); ElementId ELEM_RETURNSYM = ElementId("returnsym",172);
ElementId ELEM_UNAFFECTED = ElementId("unaffected",88); ElementId ELEM_UNAFFECTED = ElementId("unaffected",173);
/// \brief Find a ParamEntry matching the given storage Varnode /// \brief Find a ParamEntry matching the given storage Varnode
/// ///

View file

@ -15,13 +15,13 @@
*/ */
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_NOCODE = AttributeId("nocode",70); AttributeId ATTRIB_NOCODE = AttributeId("nocode",84);
ElementId ELEM_AST = ElementId("ast",89); ElementId ELEM_AST = ElementId("ast",115);
ElementId ELEM_FUNCTION = ElementId("function",90); ElementId ELEM_FUNCTION = ElementId("function",116);
ElementId ELEM_HIGHLIST = ElementId("highlist",91); ElementId ELEM_HIGHLIST = ElementId("highlist",117);
ElementId ELEM_JUMPTABLELIST = ElementId("jumptablelist",92); ElementId ELEM_JUMPTABLELIST = ElementId("jumptablelist",118);
ElementId ELEM_VARNODES = ElementId("varnodes",93); ElementId ELEM_VARNODES = ElementId("varnodes",119);
/// \param nm is the (base) name of the function /// \param nm is the (base) name of the function
/// \param scope is Symbol scope associated with the function /// \param scope is Symbol scope associated with the function

View file

@ -63,7 +63,7 @@ void connect_to_console(Funcdata *fd)
#endif #endif
ElementId ELEM_DOC = ElementId("doc",218); ElementId ELEM_DOC = ElementId("doc",229);
vector<ArchitectureGhidra *> archlist; // List of architectures currently running vector<ArchitectureGhidra *> archlist; // List of architectures currently running

View file

@ -15,13 +15,13 @@
*/ */
#include "globalcontext.hh" #include "globalcontext.hh"
ElementId ELEM_CONTEXT_DATA = ElementId("context_data",94); ElementId ELEM_CONTEXT_DATA = ElementId("context_data",120);
ElementId ELEM_CONTEXT_POINTS = ElementId("context_points",95); ElementId ELEM_CONTEXT_POINTS = ElementId("context_points",121);
ElementId ELEM_CONTEXT_POINTSET = ElementId("context_pointset",96); ElementId ELEM_CONTEXT_POINTSET = ElementId("context_pointset",122);
ElementId ELEM_CONTEXT_SET = ElementId("context_set",97); ElementId ELEM_CONTEXT_SET = ElementId("context_set",123);
ElementId ELEM_SET = ElementId("set",98); ElementId ELEM_SET = ElementId("set",124);
ElementId ELEM_TRACKED_POINTSET = ElementId("tracked_pointset",99); ElementId ELEM_TRACKED_POINTSET = ElementId("tracked_pointset",125);
ElementId ELEM_TRACKED_SET = ElementId("tracked_set",100); ElementId ELEM_TRACKED_SET = ElementId("tracked_set",126);
/// Bits within the whole context blob are labeled starting with 0 as the most significant bit /// Bits within the whole context blob are labeled starting with 0 as the most significant bit
/// in the first word in the sequence. The new context value must be contained within a single /// in the first word in the sequence. The new context value must be contained within a single

View file

@ -17,16 +17,16 @@
#include "emulate.hh" #include "emulate.hh"
#include "flow.hh" #include "flow.hh"
AttributeId ATTRIB_LABEL = AttributeId("label",71); AttributeId ATTRIB_LABEL = AttributeId("label",131);
AttributeId ATTRIB_NUM = AttributeId("num",72); AttributeId ATTRIB_NUM = AttributeId("num",132);
ElementId ELEM_BASICOVERRIDE = ElementId("basicoverride",101); ElementId ELEM_BASICOVERRIDE = ElementId("basicoverride",211);
ElementId ELEM_DEST = ElementId("dest",102); ElementId ELEM_DEST = ElementId("dest",212);
ElementId ELEM_JUMPTABLE = ElementId("jumptable",103); ElementId ELEM_JUMPTABLE = ElementId("jumptable",213);
ElementId ELEM_LOADTABLE = ElementId("loadtable",104); ElementId ELEM_LOADTABLE = ElementId("loadtable",214);
ElementId ELEM_NORMADDR = ElementId("normaddr",105); ElementId ELEM_NORMADDR = ElementId("normaddr",215);
ElementId ELEM_NORMHASH = ElementId("normhash",106); ElementId ELEM_NORMHASH = ElementId("normhash",216);
ElementId ELEM_STARTVAL = ElementId("startval",107); ElementId ELEM_STARTVAL = ElementId("startval",217);
/// \param encoder is the stream encoder /// \param encoder is the stream encoder
void LoadTable::encode(Encoder &encoder) const void LoadTable::encode(Encoder &encoder) const

View file

@ -16,10 +16,10 @@
#include "loadimage_xml.hh" #include "loadimage_xml.hh"
#include "translate.hh" #include "translate.hh"
AttributeId ATTRIB_ARCH = AttributeId("arch",73); AttributeId ATTRIB_ARCH = AttributeId("arch",135);
ElementId ELEM_BINARYIMAGE = ElementId("binaryimage",108); ElementId ELEM_BINARYIMAGE = ElementId("binaryimage",230);
ElementId ELEM_BYTECHUNK = ElementId("bytechunk",109); ElementId ELEM_BYTECHUNK = ElementId("bytechunk",231);
/// \param f is the (path to the) underlying XML file /// \param f is the (path to the) underlying XML file
/// \param el is the parsed form of the file /// \param el is the parsed form of the file

View file

@ -500,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
AttributeId ATTRIB_VALUE = AttributeId("value",25); AttributeId ATTRIB_VALUE = AttributeId("value",25);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26); AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",147); // Number serves as next open index AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",148); // Number serves as next open index
ElementId ELEM_DATA = ElementId("data",1); ElementId ELEM_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2); ElementId ELEM_INPUT = ElementId("input",2);
@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
ElementId ELEM_VALUE = ElementId("value",9); ElementId ELEM_VALUE = ElementId("value",9);
ElementId ELEM_VOID = ElementId("void",10); ElementId ELEM_VOID = ElementId("void",10);
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",231); // Number serves as next open index ElementId ELEM_UNKNOWN = ElementId("XMLunknown",251); // Number serves as next open index

View file

@ -16,7 +16,8 @@
#include "op.hh" #include "op.hh"
#include "funcdata.hh" #include "funcdata.hh"
ElementId ELEM_IOP = ElementId("iop",110); ElementId ELEM_IOP = ElementId("iop",113);
ElementId ELEM_UNIMPL = ElementId("unimpl",114);
const string IopSpace::NAME = "iop"; const string IopSpace::NAME = "iop";

View file

@ -21,6 +21,7 @@
#include "typeop.hh" #include "typeop.hh"
extern ElementId ELEM_IOP; ///< Marshaling element \<iop> extern ElementId ELEM_IOP; ///< Marshaling element \<iop>
extern ElementId ELEM_UNIMPL; ///< Marshaling element \<unimpl>
/// \brief Space for storing internal PcodeOp pointers as addresses /// \brief Space for storing internal PcodeOp pointers as addresses
/// ///

View file

@ -18,43 +18,43 @@
#include "flow.hh" #include "flow.hh"
#include "printc.hh" #include "printc.hh"
ElementId ELEM_ALIASBLOCK = ElementId("aliasblock",111); ElementId ELEM_ALIASBLOCK = ElementId("aliasblock",174);
ElementId ELEM_ALLOWCONTEXTSET = ElementId("allowcontextset",112); ElementId ELEM_ALLOWCONTEXTSET = ElementId("allowcontextset",175);
ElementId ELEM_ANALYZEFORLOOPS = ElementId("analyzeforloops",113); ElementId ELEM_ANALYZEFORLOOPS = ElementId("analyzeforloops",176);
ElementId ELEM_COMMENTHEADER = ElementId("commentheader",114); ElementId ELEM_COMMENTHEADER = ElementId("commentheader",177);
ElementId ELEM_COMMENTINDENT = ElementId("commentindent",115); ElementId ELEM_COMMENTINDENT = ElementId("commentindent",178);
ElementId ELEM_COMMENTINSTRUCTION = ElementId("commentinstruction",116); ElementId ELEM_COMMENTINSTRUCTION = ElementId("commentinstruction",179);
ElementId ELEM_COMMENTSTYLE = ElementId("commentstyle",117); ElementId ELEM_COMMENTSTYLE = ElementId("commentstyle",180);
ElementId ELEM_CONVENTIONPRINTING = ElementId("conventionprinting",118); ElementId ELEM_CONVENTIONPRINTING = ElementId("conventionprinting",181);
ElementId ELEM_CURRENTACTION = ElementId("currentaction",119); ElementId ELEM_CURRENTACTION = ElementId("currentaction",182);
ElementId ELEM_DEFAULTPROTOTYPE = ElementId("defaultprototype",120); ElementId ELEM_DEFAULTPROTOTYPE = ElementId("defaultprototype",183);
ElementId ELEM_ERRORREINTERPRETED = ElementId("errorreinterpreted",121); ElementId ELEM_ERRORREINTERPRETED = ElementId("errorreinterpreted",184);
ElementId ELEM_ERRORTOOMANYINSTRUCTIONS = ElementId("errortoomanyinstructions",122); ElementId ELEM_ERRORTOOMANYINSTRUCTIONS = ElementId("errortoomanyinstructions",185);
ElementId ELEM_ERRORUNIMPLEMENTED = ElementId("errorunimplemented",123); ElementId ELEM_ERRORUNIMPLEMENTED = ElementId("errorunimplemented",186);
ElementId ELEM_EXTRAPOP = ElementId("extrapop",124); ElementId ELEM_EXTRAPOP = ElementId("extrapop",187);
ElementId ELEM_IGNOREUNIMPLEMENTED = ElementId("ignoreunimplemented",125); ElementId ELEM_IGNOREUNIMPLEMENTED = ElementId("ignoreunimplemented",188);
ElementId ELEM_INDENTINCREMENT = ElementId("indentincrement",126); ElementId ELEM_INDENTINCREMENT = ElementId("indentincrement",189);
ElementId ELEM_INFERCONSTPTR = ElementId("inferconstptr",127); ElementId ELEM_INFERCONSTPTR = ElementId("inferconstptr",190);
ElementId ELEM_INLINE = ElementId("inline",128); ElementId ELEM_INLINE = ElementId("inline",191);
ElementId ELEM_INPLACEOPS = ElementId("inplaceops",129); ElementId ELEM_INPLACEOPS = ElementId("inplaceops",192);
ElementId ELEM_INTEGERFORMAT = ElementId("integerformat",130); ElementId ELEM_INTEGERFORMAT = ElementId("integerformat",193);
ElementId ELEM_JUMPLOAD = ElementId("jumpload",131); ElementId ELEM_JUMPLOAD = ElementId("jumpload",194);
ElementId ELEM_MAXINSTRUCTION = ElementId("maxinstruction",132); ElementId ELEM_MAXINSTRUCTION = ElementId("maxinstruction",195);
ElementId ELEM_MAXLINEWIDTH = ElementId("maxlinewidth",133); ElementId ELEM_MAXLINEWIDTH = ElementId("maxlinewidth",196);
ElementId ELEM_NAMESPACESTRATEGY = ElementId("namespacestrategy",134); ElementId ELEM_NAMESPACESTRATEGY = ElementId("namespacestrategy",197);
ElementId ELEM_NOCASTPRINTING = ElementId("nocastprinting",135); ElementId ELEM_NOCASTPRINTING = ElementId("nocastprinting",198);
ElementId ELEM_NORETURN = ElementId("noreturn",136); ElementId ELEM_NORETURN = ElementId("noreturn",199);
ElementId ELEM_NULLPRINTING = ElementId("nullprinting",137); ElementId ELEM_NULLPRINTING = ElementId("nullprinting",200);
ElementId ELEM_OPTIONSLIST = ElementId("optionslist",138); ElementId ELEM_OPTIONSLIST = ElementId("optionslist",201);
ElementId ELEM_PARAM1 = ElementId("param1",139); ElementId ELEM_PARAM1 = ElementId("param1",202);
ElementId ELEM_PARAM2 = ElementId("param2",140); ElementId ELEM_PARAM2 = ElementId("param2",203);
ElementId ELEM_PARAM3 = ElementId("param3",141); ElementId ELEM_PARAM3 = ElementId("param3",204);
ElementId ELEM_PROTOEVAL = ElementId("protoeval",142); ElementId ELEM_PROTOEVAL = ElementId("protoeval",205);
ElementId ELEM_SETACTION = ElementId("setaction",143); ElementId ELEM_SETACTION = ElementId("setaction",206);
ElementId ELEM_SETLANGUAGE = ElementId("setlanguage",144); ElementId ELEM_SETLANGUAGE = ElementId("setlanguage",207);
ElementId ELEM_STRUCTALIGN = ElementId("structalign",145); ElementId ELEM_STRUCTALIGN = ElementId("structalign",208);
ElementId ELEM_TOGGLERULE = ElementId("togglerule",146); ElementId ELEM_TOGGLERULE = ElementId("togglerule",209);
ElementId ELEM_WARNING = ElementId("warning",147); ElementId ELEM_WARNING = ElementId("warning",210);
/// If the parameter is "on" return \b true, if "off" return \b false. /// If the parameter is "on" return \b true, if "off" return \b false.
/// Any other value causes an exception. /// Any other value causes an exception.

View file

@ -16,13 +16,13 @@
#include "override.hh" #include "override.hh"
#include "funcdata.hh" #include "funcdata.hh"
ElementId ELEM_DEADCODEDELAY = ElementId("deadcodedelay",148); ElementId ELEM_DEADCODEDELAY = ElementId("deadcodedelay",218);
ElementId ELEM_FLOW = ElementId("flow",149); ElementId ELEM_FLOW = ElementId("flow",219);
ElementId ELEM_FORCEGOTO = ElementId("forcegoto",150); ElementId ELEM_FORCEGOTO = ElementId("forcegoto",220);
ElementId ELEM_INDIRECTOVERRIDE = ElementId("indirectoverride",151); ElementId ELEM_INDIRECTOVERRIDE = ElementId("indirectoverride",221);
ElementId ELEM_MULTISTAGEJUMP = ElementId("multistagejump",152); ElementId ELEM_MULTISTAGEJUMP = ElementId("multistagejump",222);
ElementId ELEM_OVERRIDE = ElementId("override",153); ElementId ELEM_OVERRIDE = ElementId("override",223);
ElementId ELEM_PROTOOVERRIDE = ElementId("protooverride",154); ElementId ELEM_PROTOOVERRIDE = ElementId("protooverride",224);
void Override::clear(void) void Override::clear(void)

View file

@ -15,9 +15,9 @@
*/ */
#include "paramid.hh" #include "paramid.hh"
ElementId ELEM_PARAMMEASURES = ElementId("parammeasures",155); ElementId ELEM_PARAMMEASURES = ElementId("parammeasures",106);
ElementId ELEM_PROTO = ElementId("proto",156); ElementId ELEM_PROTO = ElementId("proto",107);
ElementId ELEM_RANK = ElementId("rank",157); ElementId ELEM_RANK = ElementId("rank",108);
// NOTES FROM 20121206 W/Decompiler-Man // NOTES FROM 20121206 W/Decompiler-Man
// direct reads is for all opcodes, with special for these: // direct reads is for all opcodes, with special for these:

View file

@ -16,25 +16,25 @@
#include "pcodeinject.hh" #include "pcodeinject.hh"
#include "architecture.hh" #include "architecture.hh"
AttributeId ATTRIB_DYNAMIC = AttributeId("dynamic",74); AttributeId ATTRIB_DYNAMIC = AttributeId("dynamic",70);
AttributeId ATTRIB_INCIDENTALCOPY = AttributeId("incidentalcopy",75); AttributeId ATTRIB_INCIDENTALCOPY = AttributeId("incidentalcopy",71);
AttributeId ATTRIB_INJECT = AttributeId("inject",76); AttributeId ATTRIB_INJECT = AttributeId("inject",72);
AttributeId ATTRIB_PARAMSHIFT = AttributeId("paramshift",77); AttributeId ATTRIB_PARAMSHIFT = AttributeId("paramshift",73);
AttributeId ATTRIB_TARGETOP = AttributeId("targetop",78); AttributeId ATTRIB_TARGETOP = AttributeId("targetop",74);
ElementId ELEM_ADDR_PCODE = ElementId("addr_pcode",158); ElementId ELEM_ADDR_PCODE = ElementId("addr_pcode",89);
ElementId ELEM_BODY = ElementId("body",159); ElementId ELEM_BODY = ElementId("body",90);
ElementId ELEM_CALLFIXUP = ElementId("callfixup",160); ElementId ELEM_CALLFIXUP = ElementId("callfixup",91);
ElementId ELEM_CALLOTHERFIXUP = ElementId("callotherfixup",161); ElementId ELEM_CALLOTHERFIXUP = ElementId("callotherfixup",92);
ElementId ELEM_CASE_PCODE = ElementId("case_pcode",162); ElementId ELEM_CASE_PCODE = ElementId("case_pcode",93);
ElementId ELEM_CONTEXT = ElementId("context",163); ElementId ELEM_CONTEXT = ElementId("context",94);
ElementId ELEM_DEFAULT_PCODE = ElementId("default_pcode",164); ElementId ELEM_DEFAULT_PCODE = ElementId("default_pcode",95);
ElementId ELEM_INJECT = ElementId("inject",165); ElementId ELEM_INJECT = ElementId("inject",96);
ElementId ELEM_INJECTDEBUG = ElementId("injectdebug",166); ElementId ELEM_INJECTDEBUG = ElementId("injectdebug",97);
ElementId ELEM_INST = ElementId("inst",167); ElementId ELEM_INST = ElementId("inst",98);
ElementId ELEM_PAYLOAD = ElementId("payload",168); ElementId ELEM_PAYLOAD = ElementId("payload",99);
ElementId ELEM_PCODE = ElementId("pcode",169); ElementId ELEM_PCODE = ElementId("pcode",100);
ElementId ELEM_SIZE_PCODE = ElementId("size_pcode",170); ElementId ELEM_SIZE_PCODE = ElementId("size_pcode",101);
/// \brief Parse an \<input> or \<output> element describing an injection parameter /// \brief Parse an \<input> or \<output> element describing an injection parameter
/// ///

View file

@ -16,7 +16,7 @@
#include "prefersplit.hh" #include "prefersplit.hh"
#include "funcdata.hh" #include "funcdata.hh"
ElementId ELEM_PREFERSPLIT = ElementId("prefersplit",171); ElementId ELEM_PREFERSPLIT = ElementId("prefersplit",225);
bool PreferSplitRecord::operator<(const PreferSplitRecord &op2) const bool PreferSplitRecord::operator<(const PreferSplitRecord &op2) const

View file

@ -16,24 +16,24 @@
#include "prettyprint.hh" #include "prettyprint.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",136); AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",35);
AttributeId ATTRIB_CLOSE = AttributeId("close",137); AttributeId ATTRIB_CLOSE = AttributeId("close",36);
AttributeId ATTRIB_COLOR = AttributeId("color",138); AttributeId ATTRIB_COLOR = AttributeId("color",37);
AttributeId ATTRIB_INDENT = AttributeId("indent",139); AttributeId ATTRIB_INDENT = AttributeId("indent",38);
AttributeId ATTRIB_OFF = AttributeId("off",140); AttributeId ATTRIB_OFF = AttributeId("off",39);
AttributeId ATTRIB_OPEN = AttributeId("open",141); AttributeId ATTRIB_OPEN = AttributeId("open",40);
AttributeId ATTRIB_OPREF = AttributeId("opref",142); AttributeId ATTRIB_OPREF = AttributeId("opref",41);
AttributeId ATTRIB_VARREF = AttributeId("varref",143); AttributeId ATTRIB_VARREF = AttributeId("varref",42);
ElementId ELEM_BREAK = ElementId("break",208); ElementId ELEM_BREAK = ElementId("break",17);
ElementId ELEM_CLANG_DOCUMENT = ElementId("clang_document",209); ElementId ELEM_CLANG_DOCUMENT = ElementId("clang_document",18);
ElementId ELEM_FUNCNAME = ElementId("funcname",210); ElementId ELEM_FUNCNAME = ElementId("funcname",19);
ElementId ELEM_FUNCPROTO = ElementId("funcproto",211); ElementId ELEM_FUNCPROTO = ElementId("funcproto",20);
ElementId ELEM_LABEL = ElementId("label",212); ElementId ELEM_LABEL = ElementId("label",21);
ElementId ELEM_RETURN_TYPE = ElementId("return_type",213); ElementId ELEM_RETURN_TYPE = ElementId("return_type",22);
ElementId ELEM_STATEMENT = ElementId("statement",214); ElementId ELEM_STATEMENT = ElementId("statement",23);
ElementId ELEM_SYNTAX = ElementId("syntax",215); ElementId ELEM_SYNTAX = ElementId("syntax",24);
ElementId ELEM_VARDECL = ElementId("vardecl",216); ElementId ELEM_VARDECL = ElementId("vardecl",25);
ElementId ELEM_VARIABLE = ElementId("variable",217); ElementId ELEM_VARIABLE = ElementId("variable",26);
const string Emit::EMPTY_STRING = ""; const string Emit::EMPTY_STRING = "";

View file

@ -15,7 +15,7 @@
*/ */
#include "raw_arch.hh" #include "raw_arch.hh"
ElementId ELEM_RAW_SAVEFILE = ElementId("raw_savefile",172); ElementId ELEM_RAW_SAVEFILE = ElementId("raw_savefile",237);
// Constructing this object registers the capability // Constructing this object registers the capability
RawBinaryArchitectureCapability RawBinaryArchitectureCapability::rawBinaryArchitectureCapability; RawBinaryArchitectureCapability RawBinaryArchitectureCapability::rawBinaryArchitectureCapability;

View file

@ -16,20 +16,20 @@
#include "sleigh_arch.hh" #include "sleigh_arch.hh"
#include "inject_sleigh.hh" #include "inject_sleigh.hh"
AttributeId ATTRIB_DEPRECATED = AttributeId("deprecated",79); AttributeId ATTRIB_DEPRECATED = AttributeId("deprecated",136);
AttributeId ATTRIB_ENDIAN = AttributeId("endian",80); AttributeId ATTRIB_ENDIAN = AttributeId("endian",137);
AttributeId ATTRIB_PROCESSOR = AttributeId("processor",81); AttributeId ATTRIB_PROCESSOR = AttributeId("processor",138);
AttributeId ATTRIB_PROCESSORSPEC = AttributeId("processorspec",82); AttributeId ATTRIB_PROCESSORSPEC = AttributeId("processorspec",139);
AttributeId ATTRIB_SLAFILE = AttributeId("slafile",83); AttributeId ATTRIB_SLAFILE = AttributeId("slafile",140);
AttributeId ATTRIB_SPEC = AttributeId("spec",84); AttributeId ATTRIB_SPEC = AttributeId("spec",141);
AttributeId ATTRIB_TARGET = AttributeId("target",85); AttributeId ATTRIB_TARGET = AttributeId("target",142);
AttributeId ATTRIB_VARIANT = AttributeId("variant",86); AttributeId ATTRIB_VARIANT = AttributeId("variant",143);
AttributeId ATTRIB_VERSION = AttributeId("version",87); AttributeId ATTRIB_VERSION = AttributeId("version",144);
ElementId ELEM_COMPILER = ElementId("compiler",173); ElementId ELEM_COMPILER = ElementId("compiler",232);
ElementId ELEM_DESCRIPTION = ElementId("description",174); ElementId ELEM_DESCRIPTION = ElementId("description",233);
ElementId ELEM_LANGUAGE = ElementId("language",175); ElementId ELEM_LANGUAGE = ElementId("language",234);
ElementId ELEM_LANGUAGE_DEFINITIONS = ElementId("language_definitions",176); ElementId ELEM_LANGUAGE_DEFINITIONS = ElementId("language_definitions",235);
map<int4,Sleigh *> SleighArchitecture::translators; map<int4,Sleigh *> SleighArchitecture::translators;
vector<LanguageDescription> SleighArchitecture::description; vector<LanguageDescription> SleighArchitecture::description;

View file

@ -16,20 +16,20 @@
#include "space.hh" #include "space.hh"
#include "translate.hh" #include "translate.hh"
AttributeId ATTRIB_BASE = AttributeId("base",88); AttributeId ATTRIB_BASE = AttributeId("base",89);
AttributeId ATTRIB_DEADCODEDELAY = AttributeId("deadcodedelay",89); AttributeId ATTRIB_DEADCODEDELAY = AttributeId("deadcodedelay",90);
AttributeId ATTRIB_DELAY = AttributeId("delay", 90); AttributeId ATTRIB_DELAY = AttributeId("delay", 91);
AttributeId ATTRIB_LOGICALSIZE = AttributeId("logicalsize",91); AttributeId ATTRIB_LOGICALSIZE = AttributeId("logicalsize",92);
AttributeId ATTRIB_PHYSICAL = AttributeId("physical",92); AttributeId ATTRIB_PHYSICAL = AttributeId("physical",93);
AttributeId ATTRIB_PIECE1 = AttributeId("piece1",93); // piece attributes must have sequential ids AttributeId ATTRIB_PIECE1 = AttributeId("piece1",94); // piece attributes must have sequential ids
AttributeId ATTRIB_PIECE2 = AttributeId("piece2",94); AttributeId ATTRIB_PIECE2 = AttributeId("piece2",95);
AttributeId ATTRIB_PIECE3 = AttributeId("piece3",95); AttributeId ATTRIB_PIECE3 = AttributeId("piece3",96);
AttributeId ATTRIB_PIECE4 = AttributeId("piece4",96); AttributeId ATTRIB_PIECE4 = AttributeId("piece4",97);
AttributeId ATTRIB_PIECE5 = AttributeId("piece5",97); AttributeId ATTRIB_PIECE5 = AttributeId("piece5",98);
AttributeId ATTRIB_PIECE6 = AttributeId("piece6",98); AttributeId ATTRIB_PIECE6 = AttributeId("piece6",99);
AttributeId ATTRIB_PIECE7 = AttributeId("piece7",99); AttributeId ATTRIB_PIECE7 = AttributeId("piece7",100);
AttributeId ATTRIB_PIECE8 = AttributeId("piece8",100); AttributeId ATTRIB_PIECE8 = AttributeId("piece8",101);
AttributeId ATTRIB_PIECE9 = AttributeId("piece9",101); AttributeId ATTRIB_PIECE9 = AttributeId("piece9",102);
/// Calculate \e highest based on \e addressSize, and \e wordsize. /// Calculate \e highest based on \e addressSize, and \e wordsize.
/// This also calculates the default pointerLowerBound /// This also calculates the default pointerLowerBound

View file

@ -16,11 +16,11 @@
#include "stringmanage.hh" #include "stringmanage.hh"
#include "architecture.hh" #include "architecture.hh"
AttributeId ATTRIB_TRUNC = AttributeId("trunc",102); AttributeId ATTRIB_TRUNC = AttributeId("trunc",69);
ElementId ELEM_BYTES = ElementId("bytes",177); ElementId ELEM_BYTES = ElementId("bytes",83);
ElementId ELEM_STRING = ElementId("string",178); ElementId ELEM_STRING = ElementId("string",84);
ElementId ELEM_STRINGMANAGE = ElementId("stringmanage",179); ElementId ELEM_STRINGMANAGE = ElementId("stringmanage",85);
/// \param max is the maximum number of characters to allow before truncating string /// \param max is the maximum number of characters to allow before truncating string
StringManager::StringManager(int4 max) StringManager::StringManager(int4 max)

View file

@ -16,7 +16,7 @@
#include "transform.hh" #include "transform.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_VECTOR_LANE_SIZES = AttributeId("vector_lane_sizes",103); AttributeId ATTRIB_VECTOR_LANE_SIZES = AttributeId("vector_lane_sizes",130);
/// \param op2 is the lane description to copy from /// \param op2 is the lane description to copy from
LaneDescription::LaneDescription(const LaneDescription &op2) LaneDescription::LaneDescription(const LaneDescription &op2)

View file

@ -15,21 +15,21 @@
*/ */
#include "translate.hh" #include "translate.hh"
AttributeId ATTRIB_CODE = AttributeId("code",104); AttributeId ATTRIB_CODE = AttributeId("code",43);
AttributeId ATTRIB_CONTAIN = AttributeId("contain",105); AttributeId ATTRIB_CONTAIN = AttributeId("contain",44);
AttributeId ATTRIB_DEFAULTSPACE = AttributeId("defaultspace",106); AttributeId ATTRIB_DEFAULTSPACE = AttributeId("defaultspace",45);
AttributeId ATTRIB_UNIQBASE = AttributeId("uniqbase",107); AttributeId ATTRIB_UNIQBASE = AttributeId("uniqbase",46);
ElementId ELEM_OP = ElementId("op",180); ElementId ELEM_OP = ElementId("op",27);
ElementId ELEM_SLEIGH = ElementId("sleigh",181); ElementId ELEM_SLEIGH = ElementId("sleigh",28);
ElementId ELEM_SPACE = ElementId("space",182); ElementId ELEM_SPACE = ElementId("space",29);
ElementId ELEM_SPACEID = ElementId("spaceid",183); ElementId ELEM_SPACEID = ElementId("spaceid",30);
ElementId ELEM_SPACES = ElementId("spaces",184); ElementId ELEM_SPACES = ElementId("spaces",31);
ElementId ELEM_SPACE_BASE = ElementId("space_base",185); ElementId ELEM_SPACE_BASE = ElementId("space_base",32);
ElementId ELEM_SPACE_OTHER = ElementId("space_other",186); ElementId ELEM_SPACE_OTHER = ElementId("space_other",33);
ElementId ELEM_SPACE_OVERLAY = ElementId("space_overlay",187); ElementId ELEM_SPACE_OVERLAY = ElementId("space_overlay",34);
ElementId ELEM_SPACE_UNIQUE = ElementId("space_unique",188); ElementId ELEM_SPACE_UNIQUE = ElementId("space_unique",35);
ElementId ELEM_TRUNCATE_SPACE = ElementId("truncate_space",189); ElementId ELEM_TRUNCATE_SPACE = ElementId("truncate_space",36);
/// Parse a \<truncate_space> element to configure \b this object /// Parse a \<truncate_space> element to configure \b this object
/// \param decoder is the stream decoder /// \param decoder is the stream decoder

View file

@ -23,33 +23,51 @@ sub_metatype Datatype::base2sub[14] = {
SUB_UINT_PLAIN, SUB_INT_PLAIN, SUB_UNKNOWN, SUB_SPACEBASE, SUB_VOID SUB_UINT_PLAIN, SUB_INT_PLAIN, SUB_UNKNOWN, SUB_SPACEBASE, SUB_VOID
}; };
AttributeId ATTRIB_ALIGNMENT = AttributeId("alignment",108); AttributeId ATTRIB_ALIGNMENT = AttributeId("alignment",47);
AttributeId ATTRIB_ARRAYSIZE = AttributeId("arraysize",109); AttributeId ATTRIB_ARRAYSIZE = AttributeId("arraysize",48);
AttributeId ATTRIB_CHAR = AttributeId("char",110); AttributeId ATTRIB_CHAR = AttributeId("char",49);
AttributeId ATTRIB_CORE = AttributeId("core",111); AttributeId ATTRIB_CORE = AttributeId("core",50);
AttributeId ATTRIB_ENUM = AttributeId("enum",112); AttributeId ATTRIB_ENUM = AttributeId("enum",51);
AttributeId ATTRIB_ENUMSIGNED = AttributeId("enumsigned",113); AttributeId ATTRIB_ENUMSIGNED = AttributeId("enumsigned",52);
AttributeId ATTRIB_ENUMSIZE = AttributeId("enumsize",114); AttributeId ATTRIB_ENUMSIZE = AttributeId("enumsize",53);
AttributeId ATTRIB_INTSIZE = AttributeId("intsize",115); AttributeId ATTRIB_INTSIZE = AttributeId("intsize",54);
AttributeId ATTRIB_LONGSIZE = AttributeId("longsize",116); AttributeId ATTRIB_LONGSIZE = AttributeId("longsize",55);
AttributeId ATTRIB_OPAQUESTRING = AttributeId("opaquestring",117); AttributeId ATTRIB_OPAQUESTRING = AttributeId("opaquestring",56);
AttributeId ATTRIB_SIGNED = AttributeId("signed",118); AttributeId ATTRIB_SIGNED = AttributeId("signed",57);
AttributeId ATTRIB_STRUCTALIGN = AttributeId("structalign",119); AttributeId ATTRIB_STRUCTALIGN = AttributeId("structalign",58);
AttributeId ATTRIB_UTF = AttributeId("utf",120); AttributeId ATTRIB_UTF = AttributeId("utf",59);
AttributeId ATTRIB_VARLENGTH = AttributeId("varlength",121); AttributeId ATTRIB_VARLENGTH = AttributeId("varlength",60);
ElementId ELEM_CORETYPES = ElementId("coretypes",190); //ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT = ElementId("absolute_max_alignment", 37);
ElementId ELEM_DATA_ORGANIZATION = ElementId("data_organization",191); //ElementId ELEM_BITFIELD_PACKING = ElementId("bitfield_packing", 38);
ElementId ELEM_DEF = ElementId("def",192); //ElementId ELEM_CHAR_SIZE = ElementId("char_size", 39);
ElementId ELEM_ENTRY = ElementId("entry",193); //ElementId ELEM_CHAR_TYPE = ElementId("char_type", 40);
ElementId ELEM_ENUM = ElementId("enum",194); ElementId ELEM_CORETYPES = ElementId("coretypes",41);
ElementId ELEM_FIELD = ElementId("field",195); ElementId ELEM_DATA_ORGANIZATION = ElementId("data_organization", 42);
ElementId ELEM_INTEGER_SIZE = ElementId("integer_size",196); ElementId ELEM_DEF = ElementId("def",43);
ElementId ELEM_LONG_SIZE = ElementId("long_size",197); //ElementId ELEM_DEFAULT_ALIGNMENT = ElementId("default_alignment", 44);
ElementId ELEM_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map",198); //ElementId ELEM_DEFAULT_POINTER_ALIGNMENT = ElementId("default_pointer_alignment", 45);
ElementId ELEM_TYPE = ElementId("type",199); //ElementId ELEM_DOUBLE_SIZE = ElementId("double_size", 46);
ElementId ELEM_TYPEGRP = ElementId("typegrp",200); ElementId ELEM_ENTRY = ElementId("entry",47);
ElementId ELEM_TYPEREF = ElementId("typeref",201); ElementId ELEM_ENUM = ElementId("enum",48);
ElementId ELEM_FIELD = ElementId("field",49);
//ElementId ELEM_FLOAT_SIZE = ElementId("float_size", 50);
ElementId ELEM_INTEGER_SIZE = ElementId("integer_size",51);
//ElementId ELEM_LONG_DOUBLE_SIZE = ElementId("long_double_size", 52);
//ElementId ELEM_LONG_LONG_SIZE = ElementId("long_long_size", 53);
ElementId ELEM_LONG_SIZE = ElementId("long_size", 54);
//ElementId ELEM_MACHINE_ALIGNMENT = ElementId("machine_alignment", 55);
//ElementId ELEM_POINTER_SHIFT = ElementId("pointer_shift", 56);
//ElementId ELEM_POINTER_SIZE = ElementId("pointer_size", 57);
//ElementId ELEM_SHORT_SIZE = ElementId("short_size", 58);
ElementId ELEM_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map", 59);
ElementId ELEM_TYPE = ElementId("type",60);
//ElementId ELEM_TYPE_ALIGNMENT_ENABLED = ElementId("type_alignment_enabled", 61);
ElementId ELEM_TYPEGRP = ElementId("typegrp",62);
ElementId ELEM_TYPEREF = ElementId("typeref",63);
//ElementId ELEM_USE_MS_CONVENTION = ElementId("use_MS_convention", 64);
//ElementId ELEM_WCHAR_SIZE = ElementId("wchar_size", 65);
//ElementId ELEM_ZERO_LENGTH_BOUNDARY = ElementId("zero_length_boundary", 66);
// Some default routines for displaying data // Some default routines for displaying data
@ -3344,7 +3362,7 @@ Datatype *TypeFactory::decodeType(Decoder &decoder)
if (attribId == ATTRIB_ID) { if (attribId == ATTRIB_ID) {
newid = decoder.readUnsignedInteger(); newid = decoder.readUnsignedInteger();
} }
else if (attribId == ATTRIB_ID) { // A "size" attribute indicates a "variable length" base else if (attribId == ATTRIB_SIZE) { // A "size" attribute indicates a "variable length" base
size = decoder.readSignedInteger(); size = decoder.readSignedInteger();
} }
} }

View file

@ -36,18 +36,36 @@ extern AttributeId ATTRIB_STRUCTALIGN; ///< Marshaling attribute "structalign"
extern AttributeId ATTRIB_UTF; ///< Marshaling attribute "utf" extern AttributeId ATTRIB_UTF; ///< Marshaling attribute "utf"
extern AttributeId ATTRIB_VARLENGTH; ///< Marshaling attribute "varlength" extern AttributeId ATTRIB_VARLENGTH; ///< Marshaling attribute "varlength"
//extern ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT; ///< Marshaling element \<absolute_max_alignment>
//extern ElementId ELEM_BITFIELD_PACKING; ///< Marshaling element \<bitfield_packing>
//extern ElementId ELEM_CHAR_SIZE; ///< Marshaling element \<char_size>
//extern ElementId ELEM_CHAR_TYPE; ///< Marshaling element \<char_type>
extern ElementId ELEM_CORETYPES; ///< Marshaling element \<coretypes> extern ElementId ELEM_CORETYPES; ///< Marshaling element \<coretypes>
extern ElementId ELEM_DATA_ORGANIZATION; ///< Marshaling element \<data_organization> extern ElementId ELEM_DATA_ORGANIZATION; ///< Marshaling element \<data_organization>
extern ElementId ELEM_DEF; ///< Marshaling element \<def> extern ElementId ELEM_DEF; ///< Marshaling element \<def>
//extern ElementId ELEM_DEFAULT_ALIGNMENT; ///< Marshaling element \<default_alignment>
//extern ElementId ELEM_DEFAULT_POINTER_ALIGNMENT; ///< Marshaling element \<default_pointer_alignment>
//extern ElementId ELEM_DOUBLE_SIZE; ///< Marshaling element \<double_size>
extern ElementId ELEM_ENTRY; ///< Marshaling element \<entry> extern ElementId ELEM_ENTRY; ///< Marshaling element \<entry>
extern ElementId ELEM_ENUM; ///< Marshaling element \<enum> extern ElementId ELEM_ENUM; ///< Marshaling element \<enum>
extern ElementId ELEM_FIELD; ///< Marshaling element \<field> extern ElementId ELEM_FIELD; ///< Marshaling element \<field>
//extern ElementId ELEM_FLOAT_SIZE; ///< Marshaling element \<float_size>
extern ElementId ELEM_INTEGER_SIZE; ///< Marshaling element \<integer_size> extern ElementId ELEM_INTEGER_SIZE; ///< Marshaling element \<integer_size>
//extern ElementId ELEM_LONG_DOUBLE_SIZE; ///< Marshaling element \<long_double_size>
//extern ElementId ELEM_LONG_LONG_SIZE; ///< Marshaling element \<long_long_size>
extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \<long_size> extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \<long_size>
//extern ElementId ELEM_MACHINE_ALIGNMENT; ///< Marshaling element \<machine_alignment>
//extern ElementId ELEM_POINTER_SHIFT; ///< Marshaling element \<pointer_shift>
//extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \<pointer_size>
//extern ElementId ELEM_SHORT_SIZE; ///< Marshaling element \<short_size>
extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \<size_alignment_map> extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \<size_alignment_map>
extern ElementId ELEM_TYPE; ///< Marshaling element \<type> extern ElementId ELEM_TYPE; ///< Marshaling element \<type>
//extern ElementId ELEM_TYPE_ALIGNMENT_ENABLED; ///< Marshaling element \<type_alignment_enabled>
extern ElementId ELEM_TYPEGRP; ///< Marshaling element \<typegrp> extern ElementId ELEM_TYPEGRP; ///< Marshaling element \<typegrp>
extern ElementId ELEM_TYPEREF; ///< Marshaling element \<typeref> extern ElementId ELEM_TYPEREF; ///< Marshaling element \<typeref>
//extern ElementId ELEM_USE_MS_CONVENTION; ///< Marshaling element \<use_MS_convention>
//extern ElementId ELEM_WCHAR_SIZE; ///< Marshaling element \<wchar_size>
//extern ElementId ELEM_ZERO_LENGTH_BOUNDARY; ///< Marshaling element \<zero_length_boundary>
/// Print a hex dump of a data buffer to stream /// Print a hex dump of a data buffer to stream
extern void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr); extern void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr);

View file

@ -16,14 +16,14 @@
#include "userop.hh" #include "userop.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_FARPOINTER = AttributeId("farpointer",122); AttributeId ATTRIB_FARPOINTER = AttributeId("farpointer",85);
AttributeId ATTRIB_INPUTOP = AttributeId("inputop",123); AttributeId ATTRIB_INPUTOP = AttributeId("inputop",86);
AttributeId ATTRIB_OUTPUTOP = AttributeId("outputop",124); AttributeId ATTRIB_OUTPUTOP = AttributeId("outputop",87);
AttributeId ATTRIB_USEROP = AttributeId("userop",125); AttributeId ATTRIB_USEROP = AttributeId("userop",88);
ElementId ELEM_CONSTRESOLVE = ElementId("constresolve",202); ElementId ELEM_CONSTRESOLVE = ElementId("constresolve",127);
ElementId ELEM_JUMPASSIST = ElementId("jumpassist",203); ElementId ELEM_JUMPASSIST = ElementId("jumpassist",128);
ElementId ELEM_SEGMENTOP = ElementId("segmentop",204); ElementId ELEM_SEGMENTOP = ElementId("segmentop",129);
void InjectedUserOp::decode(Decoder &decoder) void InjectedUserOp::decode(Decoder &decoder)

View file

@ -17,11 +17,11 @@
#include "op.hh" #include "op.hh"
#include "database.hh" #include "database.hh"
AttributeId ATTRIB_CLASS = AttributeId("class",126); AttributeId ATTRIB_CLASS = AttributeId("class",66);
AttributeId ATTRIB_REPREF = AttributeId("repref",127); AttributeId ATTRIB_REPREF = AttributeId("repref",67);
AttributeId ATTRIB_SYMREF = AttributeId("symref",128); AttributeId ATTRIB_SYMREF = AttributeId("symref",68);
ElementId ELEM_HIGH = ElementId("high",205); ElementId ELEM_HIGH = ElementId("high",82);
/// The new instance starts off with no associate Symbol and all properties marked as \e dirty. /// The new instance starts off with no associate Symbol and all properties marked as \e dirty.
/// \param vn is the single Varnode member /// \param vn is the single Varnode member

View file

@ -16,10 +16,10 @@
#include "varmap.hh" #include "varmap.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_LOCK = AttributeId("lock",129); AttributeId ATTRIB_LOCK = AttributeId("lock",133);
AttributeId ATTRIB_MAIN = AttributeId("main",130); AttributeId ATTRIB_MAIN = AttributeId("main",134);
ElementId ELEM_LOCALDB = ElementId("localdb",206); ElementId ELEM_LOCALDB = ElementId("localdb",228);
/// \brief Can the given intersecting RangeHint coexist with \b this at their given offsets /// \brief Can the given intersecting RangeHint coexist with \b this at their given offsets
/// ///

View file

@ -16,11 +16,11 @@
#include "varnode.hh" #include "varnode.hh"
#include "funcdata.hh" #include "funcdata.hh"
AttributeId ATTRIB_ADDRTIED = AttributeId("addrtied",131); AttributeId ATTRIB_ADDRTIED = AttributeId("addrtied",30);
AttributeId ATTRIB_GRP = AttributeId("grp",132); AttributeId ATTRIB_GRP = AttributeId("grp",31);
AttributeId ATTRIB_INPUT = AttributeId("input",133); AttributeId ATTRIB_INPUT = AttributeId("input",32);
AttributeId ATTRIB_PERSISTS = AttributeId("persists",134); AttributeId ATTRIB_PERSISTS = AttributeId("persists",33);
AttributeId ATTRIB_UNAFF = AttributeId("unaff",135); AttributeId ATTRIB_UNAFF = AttributeId("unaff",34);
/// Compare by location then by definition. /// Compare by location then by definition.
/// This is the same as the normal varnode compare, but we distinguish identical frees by their /// This is the same as the normal varnode compare, but we distinguish identical frees by their

View file

@ -15,7 +15,7 @@
*/ */
#include "xml_arch.hh" #include "xml_arch.hh"
ElementId ELEM_XML_SAVEFILE = ElementId("xml_savefile",207); ElementId ELEM_XML_SAVEFILE = ElementId("xml_savefile",236);
// Constructing the singleton registers the capability // Constructing the singleton registers the capability
XmlArchitectureCapability XmlArchitectureCapability::xmlArchitectureCapability; XmlArchitectureCapability XmlArchitectureCapability::xmlArchitectureCapability;

View file

@ -88,6 +88,7 @@ public class DecompInterface {
protected CompilerSpec compilerSpec; protected CompilerSpec compilerSpec;
protected DecompileProcess decompProcess; protected DecompileProcess decompProcess;
protected DecompileCallback decompCallback; protected DecompileCallback decompCallback;
protected Encoder encoder;
private DecompileDebug debug; private DecompileDebug debug;
protected CancelledListener monitorListener = new CancelledListener() { protected CancelledListener monitorListener = new CancelledListener() {
@Override @Override
@ -110,6 +111,7 @@ public class DecompInterface {
dtmanage = null; dtmanage = null;
decompCallback = null; decompCallback = null;
xmlOptions = null; xmlOptions = null;
encoder = null;
debug = null; debug = null;
decompileMessage = ""; decompileMessage = "";
compilerSpec = null; compilerSpec = null;
@ -213,16 +215,19 @@ public class DecompInterface {
decompProcess = DecompileProcessFactory.get(); decompProcess = DecompileProcessFactory.get();
} }
long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage); long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage);
String tspec = encoder.clear();
pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null); pcodelanguage.encodeTranslator(encoder, program.getAddressFactory(), uniqueBase);
String coretypes = dtmanage.buildCoreTypes(); String tspec = encoder.toString();
encoder.clear();
dtmanage.encodeCoreTypes(encoder);
String coretypes = encoder.toString();
SleighLanguageDescription sleighdescription = SleighLanguageDescription sleighdescription =
(SleighLanguageDescription) pcodelanguage.getLanguageDescription(); (SleighLanguageDescription) pcodelanguage.getLanguageDescription();
ResourceFile pspecfile = sleighdescription.getSpecFile(); ResourceFile pspecfile = sleighdescription.getSpecFile();
String pspecxml = fileToString(pspecfile); String pspecxml = fileToString(pspecfile);
StringBuilder buffer = new StringBuilder(); XmlEncode xmlEncode = new XmlEncode();
compilerSpec.saveXml(buffer); compilerSpec.encode(xmlEncode);
String cspecxml = buffer.toString(); String cspecxml = xmlEncode.toString();
decompCallback.setNativeMessage(null); decompCallback.setNativeMessage(null);
decompProcess.registerProgram(decompCallback, pspecxml, cspecxml, tspec, coretypes); decompProcess.registerProgram(decompCallback, pspecxml, cspecxml, tspec, coretypes);
@ -317,6 +322,7 @@ public class DecompInterface {
compilerSpec = spec; compilerSpec = spec;
dtmanage = new PcodeDataTypeManager(prog); dtmanage = new PcodeDataTypeManager(prog);
encoder = new XmlEncode();
try { try {
decompCallback = decompCallback =
new DecompileCallback(prog, pcodelanguage, program.getCompilerSpec(), dtmanage); new DecompileCallback(prog, pcodelanguage, program.getCompilerSpec(), dtmanage);
@ -338,6 +344,7 @@ public class DecompInterface {
} }
program = null; program = null;
decompCallback = null; decompCallback = null;
encoder = null;
return false; return false;
} }
@ -353,6 +360,7 @@ public class DecompInterface {
if (program != null) { if (program != null) {
program = null; program = null;
decompCallback = null; decompCallback = null;
encoder = null;
try { try {
if ((decompProcess != null) && decompProcess.isReady()) { if ((decompProcess != null) && decompProcess.isReady()) {
decompProcess.deregisterProgram(); decompProcess.deregisterProgram();
@ -661,17 +669,17 @@ public class DecompInterface {
LimitedByteBuffer res = null; LimitedByteBuffer res = null;
BlockGraph resgraph = null; BlockGraph resgraph = null;
try { try {
StringWriter writer = new StringWriter(); encoder.clear();
ingraph.saveXml(writer); ingraph.encode(encoder);
verifyProcess(); verifyProcess();
res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(), res = decompProcess.sendCommand1ParamTimeout("structureGraph", encoder.toString(),
timeoutSecs); timeoutSecs);
decompileMessage = decompCallback.getNativeMessage(); decompileMessage = decompCallback.getNativeMessage();
if (res != null) { if (res != null) {
XmlDecode decoder = new XmlDecode(factory); XmlDecode decoder = new XmlDecode(factory);
decoder.ingestStream(res.getInputStream(), "structureGraph results"); decoder.ingestStream(res.getInputStream(), "structureGraph results");
resgraph = new BlockGraph(); resgraph = new BlockGraph();
resgraph.restoreXml(decoder); resgraph.decode(decoder);
resgraph.transferObjectRef(ingraph); resgraph.transferObjectRef(ingraph);
} }
} }
@ -718,10 +726,10 @@ public class DecompInterface {
debug.setFunction(func); debug.setFunction(func);
} }
decompCallback.setFunction(func, funcEntry, debug); decompCallback.setFunction(func, funcEntry, debug);
StringBuilder addrBuf = new StringBuilder(); encoder.clear();
AddressXML.buildXML(addrBuf, funcEntry); AddressXML.encode(encoder, funcEntry);
verifyProcess(); verifyProcess();
res = decompProcess.sendCommand1ParamTimeout("decompileAt", addrBuf.toString(), res = decompProcess.sendCommand1ParamTimeout("decompileAt", encoder.toString(),
timeoutSecs); timeoutSecs);
decompileMessage = decompCallback.getNativeMessage(); decompileMessage = decompCallback.getNativeMessage();
} }

View file

@ -16,16 +16,8 @@
package ghidra.app.decompiler; package ghidra.app.decompiler;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import ghidra.app.cmd.function.CallDepthChangeInfo; import ghidra.app.cmd.function.CallDepthChangeInfo;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -44,7 +36,6 @@ import ghidra.util.UndefinedFunction;
import ghidra.util.exception.UsrException; import ghidra.util.exception.UsrException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.util.xml.XmlUtilities;
/** /**
* *
@ -55,6 +46,7 @@ import ghidra.util.xml.XmlUtilities;
public class DecompileCallback { public class DecompileCallback {
public final static int MAX_SYMBOL_COUNT = 16; public final static int MAX_SYMBOL_COUNT = 16;
public final static byte[] EMPTY_BYTE_ARRAY = new byte[0];
/** /**
* Data returned for a query about strings * Data returned for a query about strings
@ -81,6 +73,7 @@ public class DecompileCallback {
private String nativeMessage; private String nativeMessage;
private XmlDecodeLight lightDecoder; private XmlDecodeLight lightDecoder;
private XmlEncode resultEncode;
private InstructionBlock lastPseudoInstructionBlock; private InstructionBlock lastPseudoInstructionBlock;
private Disassembler pseudoDisassembler; private Disassembler pseudoDisassembler;
@ -98,19 +91,7 @@ public class DecompileCallback {
debug = null; debug = null;
utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8); utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8);
lightDecoder = new XmlDecodeLight(addrfactory); lightDecoder = new XmlDecodeLight(addrfactory);
} resultEncode = new XmlEncode();
private static SAXParser getSAXParser() throws PcodeXMLException {
try {
SAXParserFactory saxParserFactory = XmlUtilities.createSecureSAXParserFactory(false);
saxParserFactory.setFeature("http://xml.org/sax/features/namespaces", false);
saxParserFactory.setFeature("http://xml.org/sax/features/validation", false);
return saxParserFactory.newSAXParser();
}
catch (Exception e) {
Msg.error(DecompileCallback.class, e.getMessage());
throw new PcodeXMLException("Failed to instantiate XML parser", e);
}
} }
/** /**
@ -156,20 +137,6 @@ public class DecompileCallback {
nativeMessage = msg; nativeMessage = msg;
} }
public synchronized ArrayList<String> readXMLNameList(String xml) throws PcodeXMLException {
try {
NameListHandler nmHandler = new NameListHandler();
getSAXParser().parse(new InputSource(new StringReader(xml)), nmHandler);
return nmHandler.getList();
}
catch (SAXException e1) {
throw new PcodeXMLException("Problem parsing list string " + xml, e1);
}
catch (IOException e1) {
throw new PcodeXMLException("Problem parsing list string " + xml, e1);
}
}
public byte[] getBytes(String addrxml) { public byte[] getBytes(String addrxml) {
try { try {
lightDecoder.ingestString(addrxml); lightDecoder.ingestString(addrxml);
@ -218,9 +185,10 @@ public class DecompileCallback {
* *
* @param addrstring is the XML rep of function address * @param addrstring is the XML rep of function address
* @param types is the string encoding of the comment type flags * @param types is the string encoding of the comment type flags
* @return XML document describing comments * @return Encoded description of comments
* @throws IOException for errors in the underlying stream
*/ */
public String getComments(String addrstring, String types) { public byte[] getComments(String addrstring, String types) throws IOException {
Address addr; Address addr;
int flags; int flags;
try { try {
@ -232,37 +200,21 @@ public class DecompileCallback {
} }
catch (PcodeXMLException e) { catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
return null; return EMPTY_BYTE_ARRAY;
} }
flags = SpecXmlUtils.decodeInt(types); flags = SpecXmlUtils.decodeInt(types);
Function func = getFunctionAt(addr); Function func = getFunctionAt(addr);
if (func == null) { if (func == null) {
return null; return EMPTY_BYTE_ARRAY;
} }
AddressSetView addrset = func.getBody(); resultEncode.clear();
StringBuilder buf = new StringBuilder(); encodeComments(resultEncode, addr, func, flags);
buf.append("<commentdb>\n");
if ((flags & 8) != 0) {
generateHeaderCommentXML(func, buf);
}
if ((flags & 1) != 0) {
generateCommentXML(addrset, addr, buf, CodeUnit.EOL_COMMENT);
}
if ((flags & 2) != 0) {
generateCommentXML(addrset, addr, buf, CodeUnit.PRE_COMMENT);
}
if ((flags & 4) != 0) {
generateCommentXML(addrset, addr, buf, CodeUnit.POST_COMMENT);
}
if ((flags & 8) != 0) {
generateCommentXML(addrset, addr, buf, CodeUnit.PLATE_COMMENT);
}
buf.append("</commentdb>\n");
String res = buf.toString();
if (debug != null) { if (debug != null) {
debug.getComments(res); XmlEncode xmlEncode = new XmlEncode();
encodeComments(xmlEncode, addr, func, flags);
debug.getComments(xmlEncode.toString());
} }
return res; return resultEncode.getBytes();
} }
public PackedBytes getPcodePacked(String addrstring) { public PackedBytes getPcodePacked(String addrstring) {
@ -314,45 +266,42 @@ public class DecompileCallback {
} }
/** /**
* Build an XML representation of all the pcode op's a given Instruction is * Encode a list of pcode, representing an entire Instruction, to the stream
* defined to perform.
* *
* @param encoder is the stream encoder
* @param ops pcode ops * @param ops pcode ops
* @param fallthruoffset number of bytes after instruction start that pcode * @param fallthruoffset number of bytes after instruction start that pcode
* flow falls into * flow falls into
* @param paramshift special instructions for injection use * @param paramshift special instructions for injection use
* @param addrFactory is the address factory for recovering address space names * @param addrFactory is the address factory for recovering address space names
* @return XML document as string representing all the p-code * @throws IOException for errors in the underlying stream
*/ */
public static String buildInstruction(PcodeOp[] ops, int fallthruoffset, int paramshift, public static void encodeInstruction(Encoder encoder, PcodeOp[] ops, int fallthruoffset,
AddressFactory addrFactory) { int paramshift, AddressFactory addrFactory) throws IOException {
StringBuilder resBuf = new StringBuilder();
if ((ops.length == 1) && (ops[0].getOpcode() == PcodeOp.UNIMPLEMENTED)) { if ((ops.length == 1) && (ops[0].getOpcode() == PcodeOp.UNIMPLEMENTED)) {
resBuf.append("<unimpl"); encoder.openElement(ElementId.ELEM_UNIMPL);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", fallthruoffset); encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, fallthruoffset);
resBuf.append("/>\n"); encoder.closeElement(ElementId.ELEM_UNIMPL);
return resBuf.toString(); return;
} }
resBuf.append("<inst"); encoder.openElement(ElementId.ELEM_INST);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", fallthruoffset); encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, fallthruoffset);
if (paramshift != 0) { if (paramshift != 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "paramshift", paramshift); encoder.writeSignedInteger(AttributeId.ATTRIB_PARAMSHIFT, paramshift);
} }
resBuf.append('>');
for (PcodeOp op : ops) { for (PcodeOp op : ops) {
op.buildXML(resBuf, addrFactory); op.encode(encoder, addrFactory);
} }
resBuf.append("</inst>\n"); encoder.closeElement(ElementId.ELEM_INST);
return resBuf.toString();
} }
public String getPcodeInject(String nm, String context, int type) { public byte[] getPcodeInject(String nm, String context, int type) {
PcodeInjectLibrary snippetLibrary = pcodecompilerspec.getPcodeInjectLibrary(); PcodeInjectLibrary snippetLibrary = pcodecompilerspec.getPcodeInjectLibrary();
InjectPayload payload = snippetLibrary.getPayload(type, nm); InjectPayload payload = snippetLibrary.getPayload(type, nm);
if (payload == null) { if (payload == null) {
Msg.warn(this, "Decompiling " + funcEntry + ", no pcode inject with name: " + nm); Msg.warn(this, "Decompiling " + funcEntry + ", no pcode inject with name: " + nm);
return null; // No fixup associated with this name return EMPTY_BYTE_ARRAY; // No fixup associated with this name
} }
InjectContext con = snippetLibrary.buildInjectContext(); InjectContext con = snippetLibrary.buildInjectContext();
PcodeOp[] pcode; PcodeOp[] pcode;
@ -362,7 +311,7 @@ public class DecompileCallback {
} }
catch (PcodeXMLException e) { catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
return null; return EMPTY_BYTE_ARRAY;
} }
try { try {
int fallThruOffset; int fallThruOffset;
@ -377,7 +326,7 @@ public class DecompileCallback {
if (instr == null) { if (instr == null) {
Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " +
con.baseAddr + ": instruction not found"); con.baseAddr + ": instruction not found");
return null; return EMPTY_BYTE_ARRAY;
} }
// get next inst addr for inst_next pcode variable // get next inst addr for inst_next pcode variable
@ -395,14 +344,18 @@ public class DecompileCallback {
} }
pcode = payload.getPcode(program, con); pcode = payload.getPcode(program, con);
if (pcode == null) { if (pcode == null) {
return null; // Just return a null string, which should let the decompiler exit gracefully return EMPTY_BYTE_ARRAY; // Return without result, which should let the decompiler exit gracefully
} }
String finalPayload = resultEncode.clear();
buildInstruction(pcode, fallThruOffset, payload.getParamShift(), addrfactory); encodeInstruction(resultEncode, pcode, fallThruOffset, payload.getParamShift(),
addrfactory);
if (debug != null) { if (debug != null) {
debug.addInject(con.baseAddr, nm, type, finalPayload); XmlEncode xmlEncode = new XmlEncode();
encodeInstruction(xmlEncode, pcode, fallThruOffset, payload.getParamShift(),
addrfactory);
debug.addInject(con.baseAddr, nm, type, xmlEncode.toString());
} }
return finalPayload; return resultEncode.getBytes();
} }
catch (UnknownInstructionException e) { catch (UnknownInstructionException e) {
Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr + Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr +
@ -412,19 +365,22 @@ public class DecompileCallback {
Msg.error(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr + Msg.error(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr +
": " + e.getMessage(), e); ": " + e.getMessage(), e);
} }
return null; return EMPTY_BYTE_ARRAY;
} }
public String getCPoolRef(long[] refs) throws IOException { public byte[] getCPoolRef(long[] refs) throws IOException {
if (cpool == null) { if (cpool == null) {
cpool = pcodecompilerspec.getPcodeInjectLibrary().getConstantPool(program); cpool = pcodecompilerspec.getPcodeInjectLibrary().getConstantPool(program);
} }
Record record = cpool.getRecord(refs); Record record = cpool.getRecord(refs);
String res = record.build(refs[0], dtmanage).toString(); resultEncode.clear();
record.encode(resultEncode, refs[0], dtmanage);
if (debug != null) { if (debug != null) {
debug.getCPoolRef(res, refs); XmlEncode xmlEncode = new XmlEncode();
record.encode(xmlEncode, refs[0], dtmanage);
debug.getCPoolRef(xmlEncode.toString(), refs);
} }
return res; return resultEncode.getBytes();
} }
private Instruction getInstruction(Address addr) throws UnknownInstructionException { private Instruction getInstruction(Address addr) throws UnknownInstructionException {
@ -614,46 +570,50 @@ public class DecompileCallback {
} }
/** /**
* Return an XML description of the formal namespace path to the given namespace * Write a description of the formal namespace path to the given namespace
* @param id is the ID of the given namespace * @param id is the ID of the given namespace
* @return a parent XML tag * @return the encoded result
* @throws IOException for errors in the underlying stream
*/ */
public String getNamespacePath(long id) { public byte[] getNamespacePath(long id) throws IOException {
Namespace namespace = getNameSpaceByID(id); Namespace namespace = getNameSpaceByID(id);
StringBuilder buf = new StringBuilder(); resultEncode.clear();
HighFunction.createNamespaceTag(buf, namespace); HighFunction.encodeNamespace(resultEncode, namespace);
if (debug != null) { if (debug != null) {
debug.getNamespacePath(namespace); debug.getNamespacePath(namespace);
} }
return buf.toString(); return resultEncode.getBytes();
} }
private void generateHeaderCommentXML(Function func, StringBuilder buf) { private void encodeHeaderComment(Encoder encoder, Function func) throws IOException {
Address addr = func.getEntryPoint(); Address addr = func.getEntryPoint();
String text = listing.getComment(CodeUnit.PLATE_COMMENT, addr); String text = listing.getComment(CodeUnit.PLATE_COMMENT, addr);
if (text != null) { if (text != null) {
buf.append("<comment"); encoder.openElement(ElementId.ELEM_COMMENT);
SpecXmlUtils.encodeStringAttribute(buf, "type", "header"); encoder.writeString(AttributeId.ATTRIB_TYPE, "header");
buf.append(">\n"); AddressXML.encode(encoder, addr);
AddressXML.buildXML(buf, addr); AddressXML.encode(encoder, addr);
AddressXML.buildXML(buf, addr); encoder.openElement(ElementId.ELEM_TEXT);
buf.append("\n<text>"); encoder.writeString(AttributeId.ATTRIB_CONTENT, text);
SpecXmlUtils.xmlEscape(buf, text); encoder.closeElement(ElementId.ELEM_TEXT);
buf.append("</text>\n"); encoder.closeElement(ElementId.ELEM_COMMENT);
buf.append("</comment>\n");
} }
} }
/** /**
* Generate XML for comments of a certain type * Encode comments of a specific type to stream for a given address set. Comments are
* collected from the listing. The encoding associates the comment both with the address where
* it was placed, but also with the (entry point) address of the function containing it.
* Plate comments whose address matches the function entry point are not encoded.
* *
* @param addrset = addresses over which to search for comments * @param encoder is the stream encoder
* @param buf = StringBuilder where XML should be written * @param addrset is the address set over which to search
* @param commenttype = type of comment * @param addr is the entry point of the function
* @param commenttype is the type of comment
* @throws IOException for errors in the underlying stream
*/ */
private void generateCommentXML(AddressSetView addrset, Address addr, StringBuilder buf, private void encodeCommentsType(Encoder encoder, AddressSetView addrset, Address addr,
int commenttype) { int commenttype) throws IOException {
String typename; String typename;
switch (commenttype) { switch (commenttype) {
case CodeUnit.EOL_COMMENT: case CodeUnit.EOL_COMMENT:
@ -684,29 +644,50 @@ public class DecompileCallback {
continue; continue;
} }
} }
encoder.openElement(ElementId.ELEM_COMMENT);
buf.append("<comment"); encoder.writeString(AttributeId.ATTRIB_TYPE, typename);
SpecXmlUtils.encodeStringAttribute(buf, "type", typename); AddressXML.encode(encoder, addr);
buf.append(">\n"); AddressXML.encode(encoder, commaddr);
AddressXML.buildXML(buf, addr); encoder.openElement(ElementId.ELEM_TEXT);
AddressXML.buildXML(buf, commaddr); encoder.writeString(AttributeId.ATTRIB_CONTENT, text);
buf.append("\n<text>"); encoder.closeElement(ElementId.ELEM_TEXT);
SpecXmlUtils.xmlEscape(buf, text); encoder.closeElement(ElementId.ELEM_COMMENT);
buf.append("</text>\n");
buf.append("</comment>\n");
} }
} }
} }
private void encodeComments(Encoder encoder, Address addr, Function func, int flags)
throws IOException {
AddressSetView addrset = func.getBody();
encoder.openElement(ElementId.ELEM_COMMENTDB);
if ((flags & 8) != 0) {
encodeHeaderComment(encoder, func);
}
if ((flags & 1) != 0) {
encodeCommentsType(encoder, addrset, addr, CodeUnit.EOL_COMMENT);
}
if ((flags & 2) != 0) {
encodeCommentsType(encoder, addrset, addr, CodeUnit.PRE_COMMENT);
}
if ((flags & 4) != 0) {
encodeCommentsType(encoder, addrset, addr, CodeUnit.POST_COMMENT);
}
if ((flags & 8) != 0) {
encodeCommentsType(encoder, addrset, addr, CodeUnit.PLATE_COMMENT);
}
encoder.closeElement(ElementId.ELEM_COMMENTDB);
}
/** /**
* Describe data or functions at addr.
* Called by the native decompiler to query the GHIDRA database about any * Called by the native decompiler to query the GHIDRA database about any
* symbols at the given address. * symbols at the given address.
* *
* @param addrstring XML encoded address to query * @param addrstring XML encoded address to query
* @return XML encoded result. Either function, reference, datatype, or hole * @return an encoded description, either function, reference, datatype, or hole
*/ */
public String getMappedSymbolsXML(String addrstring) { // Return XML describing data or functions at addr public byte[] getMappedSymbolsXML(String addrstring) {
Address addr; Address addr;
try { try {
lightDecoder.ingestString(addrstring); lightDecoder.ingestString(addrstring);
@ -716,43 +697,50 @@ public class DecompileCallback {
} }
if (addr == Address.NO_ADDRESS) { if (addr == Address.NO_ADDRESS) {
// Unknown spaces may result from "spacebase" registers defined in cspec // Unknown spaces may result from "spacebase" registers defined in cspec
return null; return EMPTY_BYTE_ARRAY;
} }
} }
catch (PcodeXMLException e) { catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
return null; return EMPTY_BYTE_ARRAY;
} }
try { try {
String res = null;
Object obj = lookupSymbol(addr); Object obj = lookupSymbol(addr);
resultEncode.clear();
if (obj instanceof Function) { if (obj instanceof Function) {
boolean includeDefaults = addr.equals(funcEntry); boolean includeDefaults = addr.equals(funcEntry);
res = buildFunctionXML((Function) obj, addr, includeDefaults); encodeFunction(resultEncode, (Function) obj, addr, includeDefaults);
} }
else if (obj instanceof Data) { else if (obj instanceof Data) {
res = buildData((Data) obj); if (!encodeData(resultEncode, (Data) obj)) {
encodeHole(resultEncode, addr);
}
} }
else if (obj instanceof ExternalReference) { else if (obj instanceof ExternalReference) {
res = buildExternalRef(addr, (ExternalReference) obj); encodeExternalRef(resultEncode, addr, (ExternalReference) obj);
} }
else if (obj instanceof Symbol) { else if (obj instanceof Symbol) {
res = buildLabel((Symbol) obj, addr); encodeLabel(resultEncode, (Symbol) obj, addr);
} }
if (res == null) { // There is a hole, describe the extent of the hole else {
res = buildHole(addr).toString(); encodeHole(resultEncode, addr); // There is a hole, describe the extent of the hole
} }
return res; return resultEncode.getBytes();
} }
catch (Exception e) { catch (Exception e) {
Msg.error(this, "Decompiling " + funcEntry + ", mapped symbol error for " + addrstring + Msg.error(this, "Decompiling " + funcEntry + ", mapped symbol error for " + addrstring +
": " + e.getMessage(), e); ": " + e.getMessage(), e);
} }
return null; return EMPTY_BYTE_ARRAY;
} }
public String getExternalRefXML(String addrstring) { // Return any external reference at addr /**
* Describe an external reference at the given address
* @param addrstring is the description of the address
* @return the encoded description
*/
public byte[] getExternalRefXML(String addrstring) {
Address addr; Address addr;
try { try {
lightDecoder.ingestString(addrstring); lightDecoder.ingestString(addrstring);
@ -763,7 +751,7 @@ public class DecompileCallback {
} }
catch (PcodeXMLException e) { catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
return null; return EMPTY_BYTE_ARRAY;
} }
try { try {
@ -787,7 +775,9 @@ public class DecompileCallback {
} }
HighSymbol shellSymbol = HighSymbol shellSymbol =
new HighFunctionShellSymbol(extId, extRef.getLabel(), addr, dtmanage); new HighFunctionShellSymbol(extId, extRef.getLabel(), addr, dtmanage);
return buildResult(shellSymbol, null); resultEncode.clear();
encodeResult(resultEncode, shellSymbol, null);
return resultEncode.getBytes();
} }
} }
else { else {
@ -796,7 +786,7 @@ public class DecompileCallback {
} }
if (func == null) { if (func == null) {
// Its conceivable we could have external data, but we aren't currently checking for it // Its conceivable we could have external data, but we aren't currently checking for it
return null; return EMPTY_BYTE_ARRAY;
} }
HighFunction hfunc = new HighFunction(func, pcodelanguage, pcodecompilerspec, dtmanage); HighFunction hfunc = new HighFunction(func, pcodelanguage, pcodecompilerspec, dtmanage);
@ -810,38 +800,38 @@ public class DecompileCallback {
debug.getFNTypes(hfunc); debug.getFNTypes(hfunc);
debug.addPossiblePrototypeExtension(func); debug.addPossiblePrototypeExtension(func);
} }
return buildResult(funcSymbol, namespc); resultEncode.clear();
encodeResult(resultEncode, funcSymbol, namespc);
return resultEncode.getBytes();
} }
catch (Exception e) { catch (Exception e) {
Msg.error(this, Msg.error(this,
"Decompiling " + funcEntry + ", error in getExternalRefXML: " + e.getMessage(), e); "Decompiling " + funcEntry + ", error in getExternalRefXML: " + e.getMessage(), e);
} }
return null; return EMPTY_BYTE_ARRAY;
} }
public String getType(String name, long id) { public byte[] getType(String name, long id) throws IOException {
DataType type = dtmanage.findBaseType(name, id); DataType type = dtmanage.findBaseType(name, id);
if (type == null) { if (type == null) {
return null; return EMPTY_BYTE_ARRAY;
} }
StringBuilder resBuf = new StringBuilder(); resultEncode.clear();
dtmanage.buildType(resBuf, type, 0); dtmanage.encodeType(resultEncode, type, 0);
resBuf.append("\n"); // Make into official XML document
String res = resBuf.toString();
if (debug != null) { if (debug != null) {
debug.getType(type); debug.getType(type);
} }
return res; return resultEncode.getBytes();
} }
public String getRegister(String name) { public byte[] getRegister(String name) throws IOException {
Register reg = pcodelanguage.getRegister(name); Register reg = pcodelanguage.getRegister(name);
if (reg == null) { if (reg == null) {
throw new RuntimeException("No Register Defined: " + name); throw new RuntimeException("No Register Defined: " + name);
} }
StringBuilder resBuf = buildRegister(reg); resultEncode.clear();
resBuf.append("\n"); encodeRegister(resultEncode, reg);
return resBuf.toString(); return resultEncode.getBytes();
} }
public String getRegisterName(String addrstring) { public String getRegisterName(String addrstring) {
@ -852,7 +842,7 @@ public class DecompileCallback {
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE); int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
Register reg = pcodelanguage.getRegister(addr, size); Register reg = pcodelanguage.getRegister(addr, size);
if (reg == null) { if (reg == null) {
return null; return "";
} }
return reg.getName(); return reg.getName();
} }
@ -860,10 +850,10 @@ public class DecompileCallback {
Msg.error(this, "Decompiling " + funcEntry + Msg.error(this, "Decompiling " + funcEntry +
", error while searching for register name: " + e.getMessage(), e); ", error while searching for register name: " + e.getMessage(), e);
} }
return null; return "";
} }
public String getTrackedRegisters(String addrstring) { public byte[] getTrackedRegisters(String addrstring) throws IOException {
Address addr; Address addr;
try { try {
lightDecoder.ingestString(addrstring); lightDecoder.ingestString(addrstring);
@ -874,30 +864,18 @@ public class DecompileCallback {
} }
catch (PcodeXMLException e) { catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
return null; return EMPTY_BYTE_ARRAY;
} }
ProgramContext context = program.getProgramContext(); ProgramContext context = program.getProgramContext();
StringBuilder stringBuf = new StringBuilder(); resultEncode.clear();
encodeTrackedPointSet(resultEncode, addr, context);
stringBuf.append("<tracked_pointset");
AddressXML.appendAttributes(stringBuf, addr);
stringBuf.append(">\n");
for (Register reg : context.getRegisters()) {
if (reg.isProcessorContext()) {
continue;
}
BigInteger val = context.getValue(reg, addr, false);
if (val != null) {
buildTrackSet(stringBuf, reg, val.longValue());
}
}
stringBuf.append("</tracked_pointset>\n");
String res = stringBuf.toString();
if (debug != null) { if (debug != null) {
debug.getTrackedRegisters(res); XmlEncode xmlEncode = new XmlEncode();
encodeTrackedPointSet(xmlEncode, addr, context);
debug.getTrackedRegisters(xmlEncode.toString());
} }
return res; return resultEncode.getBytes();
} }
public String getUserOpName(String indexStr) { public String getUserOpName(String indexStr) {
@ -906,7 +884,8 @@ public class DecompileCallback {
return name; return name;
} }
private String buildResult(HighSymbol highSymbol, Namespace namespc) { private void encodeResult(Encoder encoder, HighSymbol highSymbol, Namespace namespc)
throws IOException {
long namespaceId; long namespaceId;
if (namespc == null || namespc instanceof Library) { if (namespc == null || namespc instanceof Library) {
namespaceId = Namespace.GLOBAL_NAMESPACE_ID; namespaceId = Namespace.GLOBAL_NAMESPACE_ID;
@ -914,26 +893,26 @@ public class DecompileCallback {
else { else {
namespaceId = namespc.getID(); namespaceId = namespc.getID();
} }
StringBuilder res = new StringBuilder(); encoder.openElement(ElementId.ELEM_DOC);
res.append("<result"); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, namespaceId);
SpecXmlUtils.encodeUnsignedIntegerAttribute(res, "id", namespaceId);
res.append(">\n");
if (debug != null) { if (debug != null) {
StringBuilder res2 = new StringBuilder(); XmlEncode debugEncode = new XmlEncode();
HighSymbol.buildMapSymXML(res2, highSymbol); HighSymbol.encodeMapSym(debugEncode, highSymbol);
String res2string = res2.toString(); String res2string = debugEncode.toString();
debug.getMapped(namespc, res2string); debug.getMapped(namespc, res2string);
res.append(res2string);
} }
else { HighSymbol.encodeMapSym(encoder, highSymbol);
HighSymbol.buildMapSymXML(res, highSymbol); encoder.closeElement(ElementId.ELEM_DOC);
}
res.append("</result>\n");
return res.toString();
} }
private String buildData(Data data) { // Convert global variable to XML /**
* Encode a global variable to the stream
* @param encoder is the stream encoder
* @param data describes the global variable
* @return true if the variable is successfully encoded
* @throws IOException for errors in the underlying stream
*/
private boolean encodeData(Encoder encoder, Data data) throws IOException {
Symbol sym = data.getPrimarySymbol(); Symbol sym = data.getPrimarySymbol();
HighCodeSymbol highSymbol; HighCodeSymbol highSymbol;
if (sym != null) { if (sym != null) {
@ -945,36 +924,36 @@ public class DecompileCallback {
SymbolEntry entry = highSymbol.getFirstWholeMap(); SymbolEntry entry = highSymbol.getFirstWholeMap();
if (data.getDataType() == DataType.DEFAULT && !entry.isReadOnly() && if (data.getDataType() == DataType.DEFAULT && !entry.isReadOnly() &&
!entry.isVolatile()) { !entry.isVolatile()) {
return null; return false;
} }
} }
if (debug != null) { if (debug != null) {
debug.getType(highSymbol.getDataType()); debug.getType(highSymbol.getDataType());
} }
Namespace namespc = (sym != null) ? sym.getParentNamespace() : null; Namespace namespc = (sym != null) ? sym.getParentNamespace() : null;
return buildResult(highSymbol, namespc); encodeResult(encoder, highSymbol, namespc);
return true;
} }
private StringBuilder buildRegister(Register reg) { private static void encodeRegister(Encoder encoder, Register reg) throws IOException {
StringBuilder resBuf = new StringBuilder(); encoder.openElement(ElementId.ELEM_ADDR);
resBuf.append("<addr"); encoder.writeSpace(AttributeId.ATTRIB_SPACE, reg.getAddressSpace());
SpecXmlUtils.encodeStringAttribute(resBuf, "space", reg.getAddressSpace().getName()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, reg.getOffset());
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", reg.getOffset()); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, reg.getMinimumByteSize());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", reg.getMinimumByteSize()); encoder.closeElement(ElementId.ELEM_ADDR);
resBuf.append("/>");
return resBuf;
} }
/** /**
* Generate description of a non-data symbol, probably a code label * Encode a description of a non-data symbol, probably a code label, to the stream
* *
* @param encoder is the stream encoder
* @param sym is the symbol * @param sym is the symbol
* @return the XML description * @throws IOException for errors in the underlying stream
*/ */
private String buildLabel(Symbol sym, Address addr) { private void encodeLabel(Encoder encoder, Symbol sym, Address addr) throws IOException {
HighSymbol labelSymbol = new HighLabelSymbol(sym.getName(), addr, dtmanage); HighSymbol labelSymbol = new HighLabelSymbol(sym.getName(), addr, dtmanage);
Namespace namespc = sym.getParentNamespace(); Namespace namespc = sym.getParentNamespace();
return buildResult(labelSymbol, namespc); encodeResult(encoder, labelSymbol, namespc);
} }
/** /**
@ -1032,13 +1011,15 @@ public class DecompileCallback {
* contiguous block in the body of the function containing the queried * contiguous block in the body of the function containing the queried
* address * address
* *
* @param encoder is the stream encoder
* @param func Function whose body contains the address * @param func Function whose body contains the address
* @param addr The queried address * @param addr The queried address
* @param includeDefaultNames true if default parameter names should be * @param includeDefaultNames true if default parameter names should be
* included * included
* @return XML string describing the function or the hole * @throws IOException for errors in the underlying stream
*/ */
private String buildFunctionXML(Function func, Address addr, boolean includeDefaultNames) { private void encodeFunction(Encoder encoder, Function func, Address addr,
boolean includeDefaultNames) throws IOException {
Address entry = func.getEntryPoint(); Address entry = func.getEntryPoint();
if (entry.getAddressSpace().equals(addr.getAddressSpace())) { if (entry.getAddressSpace().equals(addr.getAddressSpace())) {
long diff = addr.getOffset() - entry.getOffset(); long diff = addr.getOffset() - entry.getOffset();
@ -1056,7 +1037,8 @@ public class DecompileCallback {
debug.getFNTypes(hfunc); debug.getFNTypes(hfunc);
debug.addPossiblePrototypeExtension(func); debug.addPossiblePrototypeExtension(func);
} }
return buildResult(functionSymbol, namespc); encodeResult(encoder, functionSymbol, namespc);
return;
} }
} }
@ -1067,14 +1049,15 @@ public class DecompileCallback {
Address first = range.getMinAddress(); Address first = range.getMinAddress();
Address last = range.getMaxAddress(); Address last = range.getMaxAddress();
boolean readonly = true; // Treat function body as readonly boolean readonly = true; // Treat function body as readonly
return buildHoleXML(first.getAddressSpace().getPhysicalSpace().getName(), encodeHole(encoder, first.getAddressSpace().getPhysicalSpace(),
first.getUnsignedOffset(), last.getUnsignedOffset(), readonly, false); first.getUnsignedOffset(), last.getUnsignedOffset(), readonly, false);
return;
} }
} }
// There is probably some sort of error, just return a block // There is probably some sort of error, just return a block
// containing the single queried address // containing the single queried address
return buildHoleXML(addr.getAddressSpace().getPhysicalSpace().getName(), encodeHole(encoder, addr.getAddressSpace().getPhysicalSpace(), addr.getUnsignedOffset(),
addr.getUnsignedOffset(), addr.getUnsignedOffset(), true, false); addr.getUnsignedOffset(), true, false);
} }
private int getExtraPopOverride(Function func, Address addr) { private int getExtraPopOverride(Function func, Address addr) {
@ -1110,17 +1093,15 @@ public class DecompileCallback {
return extrapop; return extrapop;
} }
private String buildHoleXML(String nm, long first, long last, boolean readonly, private void encodeHole(Encoder encoder, AddressSpace spc, long first, long last,
boolean isVolatile) { boolean readonly, boolean isVolatile) throws IOException {
StringBuilder resBuf = new StringBuilder(); encoder.openElement(ElementId.ELEM_HOLE);
resBuf.append("<hole"); encoder.writeBool(AttributeId.ATTRIB_READONLY, readonly);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "readonly", readonly); encoder.writeBool(AttributeId.ATTRIB_VOLATILE, isVolatile);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "volatile", isVolatile); encoder.writeSpace(AttributeId.ATTRIB_SPACE, spc);
SpecXmlUtils.encodeStringAttribute(resBuf, "space", nm); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first);
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "first", first); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last);
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "last", last); encoder.closeElement(ElementId.ELEM_HOLE);
resBuf.append("/>\n");
return resBuf.toString();
} }
/** /**
@ -1132,64 +1113,20 @@ public class DecompileCallback {
* readonly properties don't vary * readonly properties don't vary
* *
* So now we assume that biggest hole we can find is just 1 byte * So now we assume that biggest hole we can find is just 1 byte
* *
* @param addr = Address around which to find region * @param encoder is the stream encoder
* @return String <hole> tag * @param addr is the Address around which to find region
* @throws IOException for errors in the underlying stream
*/ */
private String buildHole(Address addr) { private void encodeHole(Encoder encoder, Address addr) throws IOException {
// AddressSpace addrspace = addr.getAddressSpace();
// Address before,after;
// MemoryBlock block = program.getMemory().getBlock(addr);
// boolean readonly;
// boolean isVolatile = isVolatileNoData(addr);
// if (block != null) {
// before = block.getStart();
// after = block.getEnd();
// readonly = !block.isWrite();
// }
// else {
// before = addrspace.getAddress(0);
// after = addrspace.getMaxAddress();
// readonly = false;
// }
// CodeUnit cubefore = listing.getDefinedCodeUnitBefore(addr);
// if (cubefore != null) {
// Address tmp = cubefore.getMaxAddress();
// if (tmp.getAddressSpace().getBaseSpaceID()==addrspace.getBaseSpaceID()) {
// tmp = tmp.add(1);
// if (tmp.getOffset()<=addr.getOffset()) {
// if (tmp.getOffset() > before.getOffset())
// before = tmp;
// }
// else { // Address is inside codeunit
// tmp = cubefore.getMaxAddress();
// if (tmp.getOffset()<after.getOffset())
// after = tmp;
// tmp = cubefore.getMinAddress();
// if (tmp.getOffset() > before.getOffset())
// before = tmp;
// }
// }
// }
// CodeUnit cuafter = listing.getDefinedCodeUnitAfter(addr);
// if (cuafter != null) {
// Address tmp = cuafter.getMinAddress();
// if ((tmp.getAddressSpace()==addrspace)) {
// tmp = tmp.subtract(1);
// if (tmp.getOffset()<after.getOffset()) {
// after = tmp;
// }
// }
// }
// return buildHoleXML(addrspace.getPhysicalSpace().getName(),before.getOffset(),
// after.getOffset(),readonly,isVolatile);
boolean readonly = isReadOnlyNoData(addr); boolean readonly = isReadOnlyNoData(addr);
boolean isvolatile = isVolatileNoData(addr); boolean isvolatile = isVolatileNoData(addr);
return buildHoleXML(addr.getAddressSpace().getPhysicalSpace().getName(), encodeHole(encoder, addr.getAddressSpace().getPhysicalSpace(), addr.getUnsignedOffset(),
addr.getUnsignedOffset(), addr.getUnsignedOffset(), readonly, isvolatile); addr.getUnsignedOffset(), readonly, isvolatile);
} }
private String buildExternalRef(Address addr, ExternalReference ref) { private void encodeExternalRef(Encoder encoder, Address addr, ExternalReference ref)
throws IOException {
// The decompiler model was to assume that the ExternalReference // The decompiler model was to assume that the ExternalReference
// object could resolve the physical address where the dll // object could resolve the physical address where the dll
// function was getting loaded, just as a linker would do. // function was getting loaded, just as a linker would do.
@ -1204,19 +1141,35 @@ public class DecompileCallback {
// no attempt to get a realistic linked address. This works because // no attempt to get a realistic linked address. This works because
// we never read bytes or look up code units at the address. // we never read bytes or look up code units at the address.
HighSymbol externSymbol = new HighExternalSymbol(ref.getLabel(), addr, addr, dtmanage); HighSymbol externSymbol = new HighExternalSymbol(ref.getLabel(), addr, addr, dtmanage);
return buildResult(externSymbol, null); encodeResult(encoder, externSymbol, null);
} }
private void buildTrackSet(StringBuilder buf, Register reg, long val) { private void encodeTrackSet(Encoder encoder, Register reg, long val) throws IOException {
AddressSpace spc = reg.getAddressSpace(); AddressSpace spc = reg.getAddressSpace();
long offset = reg.getOffset(); long offset = reg.getOffset();
int size = reg.getMinimumByteSize(); int size = reg.getMinimumByteSize();
buf.append("<set"); encoder.openElement(ElementId.ELEM_SET);
SpecXmlUtils.encodeStringAttribute(buf, "space", spc.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, spc);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", offset); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, offset);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "size", size); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "val", val); encoder.writeUnsignedInteger(AttributeId.ATTRIB_VAL, val);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_SET);
}
private void encodeTrackedPointSet(Encoder encoder, Address addr, ProgramContext context)
throws IOException {
encoder.openElement(ElementId.ELEM_TRACKED_POINTSET);
AddressXML.encodeAttributes(encoder, addr);
for (Register reg : context.getRegisters()) {
if (reg.isProcessorContext()) {
continue;
}
BigInteger val = context.getValue(reg, addr, false);
if (val != null) {
encodeTrackSet(encoder, reg, val.longValue());
}
}
encoder.closeElement(ElementId.ELEM_TRACKED_POINTSET);
} }
private ExternalReference getExternalReference(Address addr) { private ExternalReference getExternalReference(Address addr) {
@ -1422,46 +1375,4 @@ public class DecompileCallback {
} }
return stringData; return stringData;
} }
//==================================================================================================
// Inner Classes
//==================================================================================================
private class NameListHandler extends DefaultHandler {
private ArrayList<String> res;
private StringBuilder curbuffer;
NameListHandler() {
super();
res = new ArrayList<>();
curbuffer = null;
}
@Override
public void startElement(String uri, String localName, String rawName, Attributes attr)
throws SAXException {
if (localName.equals("val")) {
curbuffer = new StringBuilder();
}
}
@Override
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
if ((curbuffer != null) && (arg0 != null)) {
curbuffer.append(arg0, arg1, arg2);
}
}
@Override
public void endElement(String arg0, String arg1, String arg2) throws SAXException {
if (arg1.equals("val")) {
res.add(curbuffer.toString());
curbuffer = null;
}
}
public ArrayList<String> getList() {
return res;
}
}
} }

View file

@ -288,14 +288,14 @@ public class DecompileDebug {
if (stringmap.isEmpty()) { if (stringmap.isEmpty()) {
return; return;
} }
StringBuilder buf = new StringBuilder(); XmlEncode encoder = new XmlEncode();
buf.append("<stringmanage>\n"); encoder.openElement(ElementId.ELEM_STRINGMANAGE);
for (Map.Entry<Address, StringData> entry : stringmap.entrySet()) { for (Map.Entry<Address, StringData> entry : stringmap.entrySet()) {
buf.append("<string>\n"); encoder.openElement(ElementId.ELEM_STRING);
AddressXML.buildXML(buf, entry.getKey()); AddressXML.encode(encoder, entry.getKey());
buf.append("\n<bytes"); encoder.openElement(ElementId.ELEM_BYTES);
SpecXmlUtils.encodeBooleanAttribute(buf, "trunc", entry.getValue().isTruncated); encoder.writeBool(AttributeId.ATTRIB_TRUNC, entry.getValue().isTruncated);
buf.append(">\n "); StringBuilder buf = new StringBuilder();
int count = 0; int count = 0;
for (byte element : entry.getValue().byteData) { for (byte element : entry.getValue().byteData) {
int hi = (element >> 4) & 0xf; int hi = (element >> 4) & 0xf;
@ -318,46 +318,41 @@ public class DecompileDebug {
buf.append("\n "); buf.append("\n ");
} }
} }
buf.append("00\n</bytes>\n"); buf.append("00\n");
buf.append("</string>\n"); encoder.writeString(AttributeId.ATTRIB_CONTENT, buf.toString());
encoder.closeElement(ElementId.ELEM_BYTES);
encoder.closeElement(ElementId.ELEM_STRING);
} }
buf.append("</stringmanage>\n"); encoder.closeElement(ElementId.ELEM_STRINGMANAGE);
debugStream.write(buf.toString().getBytes()); debugStream.write(encoder.getBytes());
} }
private void dumpDataTypes(OutputStream debugStream) throws IOException { private void dumpDataTypes(OutputStream debugStream) throws IOException {
DataOrganization dataOrganization = program.getCompilerSpec().getDataOrganization(); DataOrganization dataOrganization = program.getCompilerSpec().getDataOrganization();
int intSize = dataOrganization.getIntegerSize(); int intSize = dataOrganization.getIntegerSize();
int longSize = dataOrganization.getLongSize(); int longSize = dataOrganization.getLongSize();
StringBuilder buf = new StringBuilder(); XmlEncode encoder = new XmlEncode();
buf.append("<typegrp"); encoder.openElement(ElementId.ELEM_TYPEGRP);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "intsize", intSize); encoder.writeSignedInteger(AttributeId.ATTRIB_INTSIZE, intSize);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "longsize", longSize); encoder.writeSignedInteger(AttributeId.ATTRIB_LONGSIZE, longSize);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "structalign", 4); encoder.writeSignedInteger(AttributeId.ATTRIB_STRUCTALIGN, 4);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "enumsize", 4); encoder.writeSignedInteger(AttributeId.ATTRIB_ENUMSIZE, 4);
SpecXmlUtils.encodeBooleanAttribute(buf, "enumsigned", false); encoder.writeBool(AttributeId.ATTRIB_ENUMSIGNED, false);
buf.append(">\n");
// structalign should come out of pcodelanguage.getCompilerSpec() // structalign should come out of pcodelanguage.getCompilerSpec()
debugStream.write(buf.toString().getBytes());
DataTypeDependencyOrderer TypeOrderer = DataTypeDependencyOrderer TypeOrderer =
new DataTypeDependencyOrderer(program.getDataTypeManager(), dtypes); new DataTypeDependencyOrderer(program.getDataTypeManager(), dtypes);
//First output all structures as zero size so to avoid any cyclic dependencies. //First output all structures as zero size so to avoid any cyclic dependencies.
for (DataType dataType : TypeOrderer.getCompositeList()) { for (DataType dataType : TypeOrderer.getCompositeList()) {
debugStream dtmanage.encodeCompositeZeroSizePlaceholder(encoder, dataType);
.write((dtmanage.buildCompositeZeroSizePlaceholder(dataType) + "\n").toString()
.getBytes());
} }
//Next, use the dependency stack to output types. //Next, use the dependency stack to output types.
for (DataType dataType : TypeOrderer.getDependencyList()) { for (DataType dataType : TypeOrderer.getDependencyList()) {
if (!(dataType instanceof BuiltIn)) { if (!(dataType instanceof BuiltIn)) {
StringBuilder typeBuf = new StringBuilder(); dtmanage.encodeType(encoder, dataType, dataType.getLength());
dtmanage.buildType(typeBuf, dataType, dataType.getLength());
typeBuf.append('\n');
debugStream.write(typeBuf.toString().getBytes());
} }
} }
debugStream.write("</typegrp>\n".getBytes()); encoder.closeElement(ElementId.ELEM_TYPEGRP);
debugStream.write(encoder.getBytes());
} }
private void dumpTrackedContext(OutputStream debugStream) throws IOException { private void dumpTrackedContext(OutputStream debugStream) throws IOException {
@ -428,7 +423,6 @@ public class DecompileDebug {
Address addr = iter.next(); Address addr = iter.next();
ProgramProcessorContext procctx = new ProgramProcessorContext(progctx, addr); ProgramProcessorContext procctx = new ProgramProcessorContext(progctx, addr);
ctxcache.getContext(procctx, buf); ctxcache.getContext(procctx, buf);
StringBuilder stringBuf = new StringBuilder();
if (lastbuf != null) { // Check to make sure we don't have identical context data if (lastbuf != null) { // Check to make sure we don't have identical context data
int i; int i;
for (i = 0; i < buf.length; ++i) { for (i = 0; i < buf.length; ++i) {
@ -447,9 +441,9 @@ public class DecompileDebug {
lastbuf[i] = buf[i]; lastbuf[i] = buf[i];
} }
stringBuf.append("<context_pointset"); XmlEncode encoder = new XmlEncode();
AddressXML.appendAttributes(stringBuf, addr); encoder.openElement(ElementId.ELEM_CONTEXT_POINTSET);
stringBuf.append(">\n"); AddressXML.encodeAttributes(encoder, addr);
for (ContextSymbol sym : ctxsymbols) { for (ContextSymbol sym : ctxsymbols) {
int sbit = sym.getInternalLow(); int sbit = sym.getInternalLow();
int ebit = sym.getInternalHigh(); int ebit = sym.getInternalHigh();
@ -459,14 +453,13 @@ public class DecompileDebug {
int shift = (8 * 4) - endbit - 1; int shift = (8 * 4) - endbit - 1;
int mask = -1 >>> (startbit + shift); int mask = -1 >>> (startbit + shift);
int val = (buf[word] >>> shift) & mask; int val = (buf[word] >>> shift) & mask;
stringBuf.append(" <set"); encoder.openElement(ElementId.ELEM_SET);
SpecXmlUtils.encodeStringAttribute(stringBuf, "name", sym.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, sym.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(stringBuf, "val", val); encoder.writeSignedInteger(AttributeId.ATTRIB_VAL, val);
stringBuf.append("/>\n"); encoder.closeElement(ElementId.ELEM_SET);
} }
stringBuf.append("</context_pointset>\n"); encoder.closeElement(ElementId.ELEM_CONTEXT_POINTSET);
String end = stringBuf.toString(); debugStream.write(encoder.getBytes());
debugStream.write(end.getBytes());
} }
} }
@ -606,28 +599,26 @@ public class DecompileDebug {
return; return;
} }
PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary(); PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary();
debugStream.write("<specextensions>\n".getBytes()); XmlEncode encoder = new XmlEncode();
encoder.openElement(ElementId.ELEM_SPECEXTENSIONS);
for (Object obj : specExtensions.values()) { for (Object obj : specExtensions.values()) {
if (obj instanceof PrototypeModel) { if (obj instanceof PrototypeModel) {
PrototypeModel model = (PrototypeModel) obj; PrototypeModel model = (PrototypeModel) obj;
StringBuilder buffer = new StringBuilder(); model.encode(encoder, library);
model.saveXml(buffer, library);
String modelString = buffer.toString();
debugStream.write(modelString.getBytes());
} }
else if (obj instanceof InjectPayload) { else if (obj instanceof InjectPayload) {
InjectPayload payload = (InjectPayload) obj; InjectPayload payload = (InjectPayload) obj;
StringBuilder buffer = new StringBuilder(); payload.encode(encoder);
payload.saveXml(buffer);
String payloadString = buffer.toString();
debugStream.write(payloadString.getBytes());
} }
} }
debugStream.write("</specextensions>\n".getBytes()); encoder.closeElement(ElementId.ELEM_SPECEXTENSIONS);
debugStream.write(encoder.getBytes());
} }
private void dumpCoretypes(OutputStream debugStream) throws IOException { private void dumpCoretypes(OutputStream debugStream) throws IOException {
debugStream.write(dtmanage.buildCoreTypes().getBytes()); XmlEncode encoder = new XmlEncode();
dtmanage.encodeCoreTypes(encoder);
debugStream.write(encoder.getBytes());
} }
public void getPcode(Address addr, Instruction instr) { public void getPcode(Address addr, Instruction instr) {
@ -694,17 +685,19 @@ public class DecompileDebug {
comments = comm; // Already in XML form comments = comm; // Already in XML form
} }
public void getCodeSymbol(Address addr, long id, String name, Namespace namespace) { public void getCodeSymbol(Address addr, long id, String name, Namespace namespace)
StringBuilder buf = new StringBuilder(); throws IOException {
buf.append("<mapsym>\n"); XmlEncode encoder = new XmlEncode();
buf.append(" <labelsym"); encoder.openElement(ElementId.ELEM_MAPSYM);
SpecXmlUtils.xmlEscapeAttribute(buf, "name", name); encoder.openElement(ElementId.ELEM_LABELSYM);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", id); encoder.writeString(AttributeId.ATTRIB_NAME, name);
buf.append("/>\n "); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id);
AddressXML.buildXML(buf, addr); encoder.closeElement(ElementId.ELEM_LABELSYM);
buf.append("\n <rangelist/>\n"); AddressXML.encode(encoder, addr);
buf.append("</mapsym>\n"); encoder.openElement(ElementId.ELEM_RANGELIST);
getMapped(namespace, buf.toString()); encoder.closeElement(ElementId.ELEM_RANGELIST);
encoder.closeElement(ElementId.ELEM_MAPSYM);
getMapped(namespace, encoder.toString());
} }
public void getNamespacePath(Namespace namespace) { public void getNamespacePath(Namespace namespace) {
@ -765,43 +758,42 @@ public class DecompileDebug {
getMapped(spc, buffer.toString()); getMapped(spc, buffer.toString());
} }
public void addFlowOverride(Address addr, FlowOverride fo) { public void addFlowOverride(Address addr, FlowOverride fo) throws IOException {
StringBuilder buf = new StringBuilder(); XmlEncode encoder = new XmlEncode();
buf.append("<flow type=\""); encoder.openElement(ElementId.ELEM_FLOW);
if (fo == FlowOverride.BRANCH) { if (fo == FlowOverride.BRANCH) {
buf.append("branch"); encoder.writeString(AttributeId.ATTRIB_TYPE, "branch");
} }
else if (fo == FlowOverride.CALL) { else if (fo == FlowOverride.CALL) {
buf.append("call"); encoder.writeString(AttributeId.ATTRIB_TYPE, "call");
} }
else if (fo == FlowOverride.CALL_RETURN) { else if (fo == FlowOverride.CALL_RETURN) {
buf.append("callreturn"); encoder.writeString(AttributeId.ATTRIB_TYPE, "callreturn");
} }
else if (fo == FlowOverride.RETURN) { else if (fo == FlowOverride.RETURN) {
buf.append("return"); encoder.writeString(AttributeId.ATTRIB_TYPE, "return");
} }
else { else {
buf.append("none"); encoder.writeString(AttributeId.ATTRIB_TYPE, "none");
} }
buf.append("\">"); AddressXML.encode(encoder, func.getEntryPoint());
AddressXML.buildXML(buf, func.getEntryPoint()); AddressXML.encode(encoder, addr);
AddressXML.buildXML(buf, addr); encoder.closeElement(ElementId.ELEM_FLOW);
buf.append("</flow>\n"); flowoverride.add(encoder.toString());
flowoverride.add(buf.toString());
} }
public void addInject(Address addr, String name, int injectType, String payload) { public void addInject(Address addr, String name, int injectType, String payload)
StringBuilder buf = new StringBuilder(); throws IOException {
buf.append("<inject name=\""); XmlEncode encoder = new XmlEncode();
buf.append(name); encoder.openElement(ElementId.ELEM_INJECT);
buf.append('"'); encoder.writeString(AttributeId.ATTRIB_NAME, name);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "type", injectType); encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, injectType);
buf.append(">\n "); AddressXML.encode(encoder, addr);
AddressXML.buildXML(buf, addr); encoder.openElement(ElementId.ELEM_PAYLOAD);
buf.append("\n <payload><![CDATA[\n"); encoder.writeString(AttributeId.ATTRIB_CONTENT, payload);
buf.append(payload); encoder.closeElement(ElementId.ELEM_PAYLOAD);
buf.append("\n]]></payload>\n</inject>\n"); encoder.closeElement(ElementId.ELEM_INJECT);
inject.add(buf.toString()); inject.add(encoder.toString());
PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary(); PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary();
if (library.hasProgramPayload(name, injectType)) { if (library.hasProgramPayload(name, injectType)) {

View file

@ -233,6 +233,12 @@ public class DecompileProcess {
write(string_end); write(string_end);
} }
private void writeBytes(byte[] msg) throws IOException {
write(string_start);
write(msg);
write(string_end);
}
/** /**
* Transfer bytes written to -out- to decompiler process * Transfer bytes written to -out- to decompiler process
* @param out has the collected byte for this write * @param out has the collected byte for this write
@ -628,10 +634,10 @@ public class DecompileProcess {
private void getRegister() throws IOException { private void getRegister() throws IOException {
String name = readQueryString(); String name = readQueryString();
String res = callback.getRegister(name); byte[] res = callback.getRegister(name);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -640,9 +646,6 @@ public class DecompileProcess {
String addr = readQueryString(); String addr = readQueryString();
String res = callback.getRegisterName(addr); String res = callback.getRegisterName(addr);
if (res == null) {
res = "";
}
write(query_response_start); write(query_response_start);
writeString(res); writeString(res);
write(query_response_end); write(query_response_end);
@ -650,12 +653,9 @@ public class DecompileProcess {
private void getTrackedRegisters() throws IOException { private void getTrackedRegisters() throws IOException {
String addr = readQueryString(); String addr = readQueryString();
String res = callback.getTrackedRegisters(addr); byte[] res = callback.getTrackedRegisters(addr);
if (res == null) {
res = "";
}
write(query_response_start); write(query_response_start);
writeString(res); writeBytes(res);
write(query_response_end); write(query_response_end);
} }
@ -683,10 +683,10 @@ public class DecompileProcess {
private void getPcodeInject(int type) throws IOException { private void getPcodeInject(int type) throws IOException {
String name = readQueryString(); String name = readQueryString();
String context = readQueryString(); String context = readQueryString();
String res = callback.getPcodeInject(name, context, type); byte[] res = callback.getPcodeInject(name, context, type);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -698,10 +698,10 @@ public class DecompileProcess {
for (int i = 0; i < split.length; ++i) { for (int i = 0; i < split.length; ++i) {
refs[i] = Long.parseUnsignedLong(split[i], 16); refs[i] = Long.parseUnsignedLong(split[i], 16);
} }
String res = callback.getCPoolRef(refs); byte[] res = callback.getCPoolRef(refs);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -709,10 +709,10 @@ public class DecompileProcess {
private void getMappedSymbolsXML() throws IOException { private void getMappedSymbolsXML() throws IOException {
String addr = readQueryString(); String addr = readQueryString();
String res = callback.getMappedSymbolsXML(addr); byte[] res = callback.getMappedSymbolsXML(addr);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -720,10 +720,10 @@ public class DecompileProcess {
private void getNamespacePath() throws IOException { private void getNamespacePath() throws IOException {
String idString = readQueryString(); String idString = readQueryString();
long id = Long.parseLong(idString, 16); long id = Long.parseLong(idString, 16);
String res = callback.getNamespacePath(id); byte[] res = callback.getNamespacePath(id);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -744,10 +744,10 @@ public class DecompileProcess {
private void getExternalRefXML() throws IOException { private void getExternalRefXML() throws IOException {
String refaddr = readQueryString(); String refaddr = readQueryString();
String res = callback.getExternalRefXML(refaddr); byte[] res = callback.getExternalRefXML(refaddr);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }
@ -767,32 +767,19 @@ public class DecompileProcess {
private void getComments() throws IOException { private void getComments() throws IOException {
String addr = readQueryString(); String addr = readQueryString();
String flags = readQueryString(); String flags = readQueryString();
String res = callback.getComments(addr, flags); byte[] res = callback.getComments(addr, flags);
if (res == null) {
res = "";
}
write(query_response_start); write(query_response_start);
writeString(res); writeBytes(res);
write(query_response_end); write(query_response_end);
} }
// private void getScope() throws IOException {
// String namepath = readQueryString();
// String res = callback.getScope(namepath);
// if (res==null)
// res = "";
// write(query_response_start);
// writeString(res);
// write(query_response_end);
// }
private void getType() throws IOException { private void getType() throws IOException {
String name = readQueryString(); String name = readQueryString();
long id = SpecXmlUtils.decodeLong(readQueryString()); long id = SpecXmlUtils.decodeLong(readQueryString());
String res = callback.getType(name, id); byte[] res = callback.getType(name, id);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if (res.length != 0) {
writeString(res); writeBytes(res);
} }
write(query_response_end); write(query_response_end);
} }

View file

@ -17,6 +17,7 @@ package ghidra.app.plugin.core.decompile;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.IOException;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -32,6 +33,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.lang.CompilerSpec.EvaluationModelType; import ghidra.program.model.lang.CompilerSpec.EvaluationModelType;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.pcode.XmlEncode;
import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
@ -125,15 +127,15 @@ public class SpecExtensionTest extends AbstractDecompilerTest {
} }
@Test @Test
public void test_PrototypeExtension() { public void test_PrototypeExtension() throws IOException {
decompile("100272e"); decompile("100272e");
ClangTextField line = getLineContaining("FUN_010026a7(pHVar1);"); ClangTextField line = getLineContaining("FUN_010026a7(pHVar1);");
assertNotNull(line); assertNotNull(line);
CompilerSpec cspec = program.getCompilerSpec(); CompilerSpec cspec = program.getCompilerSpec();
PrototypeModel defaultModel = cspec.getDefaultCallingConvention(); PrototypeModel defaultModel = cspec.getDefaultCallingConvention();
StringBuilder buffer = new StringBuilder(); XmlEncode encoder = new XmlEncode();
defaultModel.saveXml(buffer, cspec.getPcodeInjectLibrary()); defaultModel.encode(encoder, cspec.getPcodeInjectLibrary());
String defaultString = buffer.toString(); String defaultString = encoder.toString();
// Replace the output register EAX with ECX // Replace the output register EAX with ECX
defaultString = defaultString.replace("<addr space=\"register\" offset=\"0x0\"/>", defaultString = defaultString.replace("<addr space=\"register\" offset=\"0x0\"/>",
"<addr space=\"register\" offset=\"4\"/>"); "<addr space=\"register\" offset=\"4\"/>");

View file

@ -40,6 +40,7 @@ import ghidra.program.model.lang.*;
import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.listing.DefaultProgramContext;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.*;
import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.util.AddressLabelInfo; import ghidra.program.model.util.AddressLabelInfo;
import ghidra.program.model.util.ProcessorSymbolType; import ghidra.program.model.util.ProcessorSymbolType;
@ -1402,70 +1403,65 @@ public class SleighLanguage implements Language {
} }
/** /**
* Generates a limited translator XML tag for the specified address factory and optional register set. * Encode limited information to the stream about the SLEIGH translator for the specified
* @param factory address factory * address factory and optional register set.
* @param encoder is the stream encoder
* @param factory is the specified address factory
* @param uniqueOffset the initial offset within the unique address space to start assigning temporary registers * @param uniqueOffset the initial offset within the unique address space to start assigning temporary registers
* @param optionalSymTab optional symbol table to be passed (may be null to omit). Only non-context registers * @throws IOException for errors writing to the underlying stream
* and user-defined pcodeop's are included.
* @return the entire XML tag as a String
*/ */
public String buildTranslatorTag(AddressFactory factory, long uniqueOffset, public void encodeTranslator(Encoder encoder, AddressFactory factory, long uniqueOffset)
SymbolTable optionalSymTab) { throws IOException {
AddressSpace[] spclist = factory.getAllAddressSpaces(); AddressSpace[] spclist = factory.getAllAddressSpaces();
StringBuilder resBuf = new StringBuilder(); encoder.openElement(ElementId.ELEM_SLEIGH);
encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
resBuf.append("<sleigh"); encoder.writeUnsignedInteger(AttributeId.ATTRIB_UNIQBASE, uniqueOffset);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "bigendian", isBigEndian()); encoder.openElement(ElementId.ELEM_SPACES);
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniqbase", uniqueOffset); encoder.writeString(AttributeId.ATTRIB_DEFAULTSPACE,
resBuf.append(">\n");
resBuf.append("<spaces");
SpecXmlUtils.encodeStringAttribute(resBuf, "defaultspace",
factory.getDefaultAddressSpace().getName()); factory.getDefaultAddressSpace().getName());
resBuf.append(">\n");
String tag; ElementId tag;
int delay; int delay;
boolean physical; boolean physical;
for (AddressSpace element : spclist) { for (AddressSpace element : spclist) {
if ((element instanceof OverlayAddressSpace)) { if ((element instanceof OverlayAddressSpace)) {
OverlayAddressSpace ospace = (OverlayAddressSpace) element; OverlayAddressSpace ospace = (OverlayAddressSpace) element;
resBuf.append("<space_overlay"); encoder.openElement(ElementId.ELEM_SPACE_OVERLAY);
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", ospace.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, ospace.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", ospace.getUnique()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, ospace.getUnique());
SpecXmlUtils.encodeStringAttribute(resBuf, "base", encoder.writeSpace(AttributeId.ATTRIB_BASE, ospace.getOverlayedSpace());
ospace.getOverlayedSpace().getName()); encoder.closeElement(ElementId.ELEM_SPACE_OVERLAY);
resBuf.append("/>\n");
continue; continue;
} }
switch (element.getType()) { switch (element.getType()) {
case AddressSpace.TYPE_RAM: case AddressSpace.TYPE_RAM:
tag = "space"; tag = ElementId.ELEM_SPACE;
delay = 1; delay = 1;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_REGISTER: case AddressSpace.TYPE_REGISTER:
tag = "space"; tag = ElementId.ELEM_SPACE;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_UNIQUE: case AddressSpace.TYPE_UNIQUE:
tag = "space_unique"; tag = ElementId.ELEM_SPACE_UNIQUE;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_OTHER: case AddressSpace.TYPE_OTHER:
tag = "space_other"; tag = ElementId.ELEM_SPACE_OTHER;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
default: default:
continue; continue;
} }
resBuf.append("<").append(tag); encoder.openElement(tag);
SpecXmlUtils.encodeStringAttribute(resBuf, "name", element.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, element.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, element.getUnique());
int size = element.getSize(); // Size in bits int size = element.getSize(); // Size in bits
if (element instanceof SegmentedAddressSpace) { if (element instanceof SegmentedAddressSpace) {
@ -1476,20 +1472,19 @@ public class SleighLanguage implements Language {
size = 64; size = 64;
} }
int bytesize = (size + 7) / 8; // Convert bits to bytes int bytesize = (size + 7) / 8; // Convert bits to bytes
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", bytesize); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, bytesize);
if (element.getAddressableUnitSize() > 1) { if (element.getAddressableUnitSize() > 1) {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "wordsize", encoder.writeSignedInteger(AttributeId.ATTRIB_WORDSIZE,
element.getAddressableUnitSize()); element.getAddressableUnitSize());
} }
SpecXmlUtils.encodeBooleanAttribute(resBuf, "bigendian", isBigEndian()); encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "delay", delay); encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, delay);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "physical", physical); encoder.writeBool(AttributeId.ATTRIB_PHYSICAL, physical);
encoder.closeElement(tag);
resBuf.append("/>\n");
} }
resBuf.append("</spaces>\n"); encoder.closeElement(ElementId.ELEM_SPACES);
SleighLanguageDescription sleighDescription = SleighLanguageDescription sleighDescription =
(SleighLanguageDescription) getLanguageDescription(); (SleighLanguageDescription) getLanguageDescription();
@ -1497,75 +1492,13 @@ public class SleighLanguage implements Language {
if (!truncatedSpaceNames.isEmpty()) { if (!truncatedSpaceNames.isEmpty()) {
for (String spaceName : truncatedSpaceNames) { for (String spaceName : truncatedSpaceNames) {
int sz = sleighDescription.getTruncatedSpaceSize(spaceName); int sz = sleighDescription.getTruncatedSpaceSize(spaceName);
resBuf.append("<truncate_space"); encoder.openElement(ElementId.ELEM_TRUNCATE_SPACE);
SpecXmlUtils.encodeStringAttribute(resBuf, "space", spaceName); encoder.writeString(AttributeId.ATTRIB_SPACE, spaceName);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz);
resBuf.append("/>\n"); encoder.closeElement(ElementId.ELEM_TRUNCATE_SPACE);
} }
} }
if (optionalSymTab != null) { encoder.closeElement(ElementId.ELEM_SLEIGH);
resBuf.append(buildSymbolsXml(optionalSymTab));
}
resBuf.append("</sleigh>\n");
return resBuf.toString();
}
private static String buildSymbolsXml(SymbolTable symtab) {
ArrayList<Symbol> symList = new ArrayList<>();
for (Symbol sym : symtab.getSymbolList()) {
if (sym instanceof UseropSymbol) {
symList.add(sym);
}
else if (sym instanceof VarnodeSymbol) {
if ("contextreg".equals(sym.getName())) {
continue;
}
symList.add(sym);
}
}
int count = symList.size();
StringBuilder s = new StringBuilder();
s.append("<symbol_table scopesize=\"1\" symbolsize=\"");
s.append(count);
s.append("\">\n");
s.append("<scope id=\"0x0\" parent=\"0x0\"/>\n");
// First save the headers
for (int i = 0; i < count; ++i) {
Symbol sym = symList.get(i);
String type;
if (sym instanceof UseropSymbol) {
type = "userop_head";
}
else {
type = "varnode_sym_head";
}
s.append("<" + type + " name=\"" + sym.getName() + "\" id=\"0x" +
Integer.toHexString(i) + "\" scope=\"0x0\"/>\n");
}
// Now save the content of each symbol
for (int i = 0; i < count; ++i) {
Symbol sym = symList.get(i);
if (sym instanceof UseropSymbol) {
UseropSymbol opSym = (UseropSymbol) sym;
s.append("<userop name=\"" + sym.getName() + "\" id=\"0x" + Integer.toHexString(i) +
"\" scope=\"0x0\" index=\"" + opSym.getIndex() + "\"/>\n");
}
else {
VarnodeSymbol vnSym = (VarnodeSymbol) sym;
VarnodeData vn = vnSym.getFixedVarnode();
s.append(
"<varnode_sym name=\"" + sym.getName() + "\" id=\"0x" + Integer.toHexString(i) +
"\" scope=\"0x0\" space=\"" + vn.space.getName() + "\" offset=\"0x" +
Long.toHexString(vn.offset) + "\" size=\"" + vn.size + "\"/>\n");
}
}
s.append("</symbol_table>\n");
return s.toString();
} }
private void initParallelHelper() { private void initParallelHelper() {

View file

@ -38,6 +38,7 @@ import ghidra.program.database.ProgramDB;
import ghidra.program.database.SpecExtension; import ghidra.program.database.SpecExtension;
import ghidra.program.database.SpecExtension.DocInfo; import ghidra.program.database.SpecExtension.DocInfo;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.pcode.XmlEncode;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.Swing; import ghidra.util.Swing;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
@ -541,45 +542,45 @@ public class SpecExtensionPanel extends JPanel {
} }
} }
private String getXmlString(CompilerElement element) { private String getXmlString(CompilerElement element) throws IOException {
CompilerSpec compilerSpec = program.getCompilerSpec(); CompilerSpec compilerSpec = program.getCompilerSpec();
PcodeInjectLibrary injectLibrary = compilerSpec.getPcodeInjectLibrary(); PcodeInjectLibrary injectLibrary = compilerSpec.getPcodeInjectLibrary();
InjectPayload payload; InjectPayload payload;
PrototypeModel model; PrototypeModel model;
String resultString = null; String resultString;
if (element.status == Status.CORE) { if (element.status == Status.CORE) {
StringBuilder buffer = new StringBuilder(); XmlEncode encoder = new XmlEncode();
switch (element.type) { switch (element.type) {
case CALL_FIXUP: case CALL_FIXUP:
payload = injectLibrary.getPayload(InjectPayload.CALLFIXUP_TYPE, element.name); payload = injectLibrary.getPayload(InjectPayload.CALLFIXUP_TYPE, element.name);
if (payload != null) { if (payload != null) {
payload.saveXml(buffer); payload.encode(encoder);
} }
break; break;
case CALLOTHER_FIXUP: case CALLOTHER_FIXUP:
payload = payload =
injectLibrary.getPayload(InjectPayload.CALLOTHERFIXUP_TYPE, element.name); injectLibrary.getPayload(InjectPayload.CALLOTHERFIXUP_TYPE, element.name);
if (payload != null) { if (payload != null) {
payload.saveXml(buffer); payload.encode(encoder);
} }
break; break;
case PROTOTYPE_MODEL: case PROTOTYPE_MODEL:
case MERGE_MODEL: case MERGE_MODEL:
model = compilerSpec.getCallingConvention(element.name); model = compilerSpec.getCallingConvention(element.name);
if (model != null) { if (model != null) {
model.saveXml(buffer, injectLibrary); model.encode(encoder, injectLibrary);
} }
break; break;
} }
resultString = buffer.toString(); resultString = encoder.toString();
if (resultString.length() == 0) {
resultString = null;
}
} }
else { else {
resultString = resultString =
SpecExtension.getCompilerSpecExtension(program, element.type, element.name); SpecExtension.getCompilerSpecExtension(program, element.type, element.name);
} }
if (resultString == null || resultString.length() == 0) {
throw new IOException("Unable to build document for " + element.name);
}
return resultString; return resultString;
} }
@ -603,24 +604,16 @@ public class SpecExtensionPanel extends JPanel {
return; return;
} }
} }
String exportString = getXmlString(compilerElement); FileWriter writer = null;
String errMessage = null; try {
if (exportString == null) { String exportString = getXmlString(compilerElement);
errMessage = "Unable to build document for " + compilerElement.name; writer = new FileWriter(outputFile);
writer.write(exportString);
writer.close();
} }
else { catch (IOException ex) {
FileWriter writer = null; Msg.showError(this, this, "Export Failure",
try { "Failed to write to file: " + ex.getMessage());
writer = new FileWriter(outputFile);
writer.write(exportString);
writer.close();
}
catch (IOException ex) {
errMessage = "Failed to write to file: " + ex.getMessage();
}
}
if (errMessage != null) {
Msg.showError(this, this, "Export Failure", errMessage);
} }
} }

View file

@ -15,6 +15,9 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import java.io.IOException;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -70,26 +73,31 @@ public class BitFieldPackingImpl implements BitFieldPacking {
} }
/** /**
* Write configuration to a stream as an XML \<bitfield_packing> tag * Write configuration to a stream as a \<bitfield_packing> element
* @param buffer is the stream to write to * @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/ */
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
if (!useMSConvention && typeAlignmentEnabled && zeroLengthBoundary == 0) { if (!useMSConvention && typeAlignmentEnabled && zeroLengthBoundary == 0) {
return; // All defaults return; // All defaults
} }
buffer.append("<bitfield_packing>\n"); encoder.openElement(ElementId.ELEM_BITFIELD_PACKING);
if (useMSConvention) { if (useMSConvention) {
buffer.append("<use_MS_convention value=\"yes\"/>\n"); encoder.openElement(ElementId.ELEM_USE_MS_CONVENTION);
encoder.writeBool(AttributeId.ATTRIB_VALUE, true);
encoder.closeElement(ElementId.ELEM_USE_MS_CONVENTION);
} }
if (!typeAlignmentEnabled) { if (!typeAlignmentEnabled) {
buffer.append("<type_alignment_enabled value=\"no\"/>\n"); encoder.openElement(ElementId.ELEM_TYPE_ALIGNMENT_ENABLED);
encoder.writeBool(AttributeId.ATTRIB_VALUE, false);
encoder.closeElement(ElementId.ELEM_TYPE_ALIGNMENT_ENABLED);
} }
if (zeroLengthBoundary != 0) { if (zeroLengthBoundary != 0) {
buffer.append("<zero_length_boundary"); encoder.openElement(ElementId.ELEM_ZERO_LENGTH_BOUNDARY);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", zeroLengthBoundary); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, zeroLengthBoundary);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_ZERO_LENGTH_BOUNDARY);
} }
buffer.append("</bitfield_packing>\n"); encoder.closeElement(ElementId.ELEM_BITFIELD_PACKING);
} }
/** /**

View file

@ -15,9 +15,11 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.pcode.*;
import ghidra.util.exception.NoValueException; import ghidra.util.exception.NoValueException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
@ -551,99 +553,101 @@ public class DataOrganizationImpl implements DataOrganization {
return (value2 != 0) ? getGreatestCommonDenominator(value2, value1 % value2) : value1; return (value2 != 0) ? getGreatestCommonDenominator(value2, value1 % value2) : value1;
} }
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<data_organization>\n"); encoder.openElement(ElementId.ELEM_DATA_ORGANIZATION);
if (absoluteMaxAlignment != NO_MAXIMUM_ALIGNMENT) { if (absoluteMaxAlignment != NO_MAXIMUM_ALIGNMENT) {
buffer.append("<absolute_max_alignment"); encoder.openElement(ElementId.ELEM_ABSOLUTE_MAX_ALIGNMENT);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", absoluteMaxAlignment); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, absoluteMaxAlignment);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_ABSOLUTE_MAX_ALIGNMENT);
} }
if (machineAlignment != 8) { if (machineAlignment != 8) {
buffer.append("<machine_alignment"); encoder.openElement(ElementId.ELEM_MACHINE_ALIGNMENT);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", machineAlignment); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, machineAlignment);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_MACHINE_ALIGNMENT);
} }
if (defaultAlignment != 1) { if (defaultAlignment != 1) {
buffer.append("<default_alignment"); encoder.openElement(ElementId.ELEM_DEFAULT_ALIGNMENT);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", defaultAlignment); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, defaultAlignment);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_DEFAULT_ALIGNMENT);
} }
if (defaultPointerAlignment != 4) { if (defaultPointerAlignment != 4) {
buffer.append("<default_pointer_alignment"); encoder.openElement(ElementId.ELEM_DEFAULT_POINTER_ALIGNMENT);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", defaultPointerAlignment); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, defaultPointerAlignment);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_DEFAULT_POINTER_ALIGNMENT);
} }
if (pointerSize != 0) { if (pointerSize != 0) {
buffer.append("<pointer_size"); encoder.openElement(ElementId.ELEM_POINTER_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", pointerSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, pointerSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_POINTER_SIZE);
} }
if (pointerShift != 0) { if (pointerShift != 0) {
buffer.append("<pointer_shift"); encoder.openElement(ElementId.ELEM_POINTER_SHIFT);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", pointerShift); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, pointerShift);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_POINTER_SHIFT);
} }
if (!isSignedChar) { if (!isSignedChar) {
buffer.append("<char_type signed=\"no\"/>\n"); encoder.openElement(ElementId.ELEM_CHAR_TYPE);
encoder.writeBool(AttributeId.ATTRIB_SIGNED, false);
encoder.closeElement(ElementId.ELEM_CHAR_TYPE);
} }
if (charSize != 1) { if (charSize != 1) {
buffer.append("<char_size"); encoder.openElement(ElementId.ELEM_CHAR_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", charSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, charSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_CHAR_SIZE);
} }
if (wideCharSize != 2) { if (wideCharSize != 2) {
buffer.append("<wchar_size"); encoder.openElement(ElementId.ELEM_WCHAR_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", wideCharSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, wideCharSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_WCHAR_SIZE);
} }
if (shortSize != 2) { if (shortSize != 2) {
buffer.append("<short_size"); encoder.openElement(ElementId.ELEM_SHORT_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", shortSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, shortSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_SHORT_SIZE);
} }
if (integerSize != 4) { if (integerSize != 4) {
buffer.append("<integer_size"); encoder.openElement(ElementId.ELEM_INTEGER_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", integerSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, integerSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_INTEGER_SIZE);
} }
if (longSize != 4) { if (longSize != 4) {
buffer.append("<long_size"); encoder.openElement(ElementId.ELEM_LONG_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", longSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_LONG_SIZE);
} }
if (longLongSize != 8) { if (longLongSize != 8) {
buffer.append("<long_long_size"); encoder.openElement(ElementId.ELEM_LONG_LONG_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", longLongSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longLongSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_LONG_LONG_SIZE);
} }
if (floatSize != 4) { if (floatSize != 4) {
buffer.append("<float_size"); encoder.openElement(ElementId.ELEM_FLOAT_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", floatSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, floatSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_FLOAT_SIZE);
} }
if (doubleSize != 8) { if (doubleSize != 8) {
buffer.append("<double_size"); encoder.openElement(ElementId.ELEM_DOUBLE_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", doubleSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, doubleSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_DOUBLE_SIZE);
} }
if (longDoubleSize != 8) { if (longDoubleSize != 8) {
buffer.append("<long_double_size"); encoder.openElement(ElementId.ELEM_LONG_DOUBLE_SIZE);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "value", longDoubleSize); encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longDoubleSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_LONG_DOUBLE_SIZE);
} }
if (sizeAlignmentMap.size() != 0) { if (sizeAlignmentMap.size() != 0) {
buffer.append("<size_alignment_map>\n"); encoder.openElement(ElementId.ELEM_SIZE_ALIGNMENT_MAP);
for (int key : sizeAlignmentMap.keySet()) { for (int key : sizeAlignmentMap.keySet()) {
buffer.append("<entry"); encoder.openElement(ElementId.ELEM_ENTRY);
int value = sizeAlignmentMap.get(key); int value = sizeAlignmentMap.get(key);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "size", key); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, key);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "alignment", value); encoder.writeSignedInteger(AttributeId.ATTRIB_ALIGNMENT, value);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_ENTRY);
} }
buffer.append("</size_alignment_map>\n"); encoder.closeElement(ElementId.ELEM_SIZE_ALIGNMENT_MAP);
} }
bitFieldPacking.saveXml(buffer); bitFieldPacking.encode(encoder);
buffer.append("</data_organization>\n"); encoder.closeElement(ElementId.ELEM_DATA_ORGANIZATION);
} }
/** /**

View file

@ -32,8 +32,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.listing.DefaultProgramContext;
import ghidra.program.model.listing.Parameter; import ghidra.program.model.listing.Parameter;
import ghidra.program.model.pcode.AddressXML; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -508,64 +507,64 @@ public class BasicCompilerSpec implements CompilerSpec {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<compiler_spec>\n"); encoder.openElement(ElementId.ELEM_COMPILER_SPEC);
saveProperties(buffer); encodeProperties(encoder);
dataOrganization.saveXml(buffer); dataOrganization.encode(encoder);
ContextSetting.buildContextDataXml(buffer, ctxsetting); ContextSetting.encodeContextData(encoder, ctxsetting);
if (aggressiveTrim) { if (aggressiveTrim) {
buffer.append("<aggressivetrim"); encoder.openElement(ElementId.ELEM_AGGRESSIVETRIM);
SpecXmlUtils.encodeBooleanAttribute(buffer, "signext", aggressiveTrim); encoder.writeBool(AttributeId.ATTRIB_SIGNEXT, aggressiveTrim);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_AGGRESSIVETRIM);
} }
if (stackPointer != null) { if (stackPointer != null) {
buffer.append("<stackpointer"); encoder.openElement(ElementId.ELEM_STACKPOINTER);
SpecXmlUtils.encodeStringAttribute(buffer, "register", stackPointer.getName()); encoder.writeString(AttributeId.ATTRIB_REGISTER, stackPointer.getName());
SpecXmlUtils.encodeStringAttribute(buffer, "space", stackBaseSpace.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, stackBaseSpace);
if (reverseJustifyStack) { if (reverseJustifyStack) {
SpecXmlUtils.encodeBooleanAttribute(buffer, "reversejustify", reverseJustifyStack); encoder.writeBool(AttributeId.ATTRIB_REVERSEJUSTIFY, reverseJustifyStack);
} }
if (!stackGrowsNegative) { if (!stackGrowsNegative) {
SpecXmlUtils.encodeStringAttribute(buffer, "growth", "positive"); encoder.writeString(AttributeId.ATTRIB_GROWTH, "positive");
} }
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_STACKPOINTER);
} }
saveSpaceBases(buffer); encodeSpaceBases(encoder);
saveMemoryTags(buffer, "global", globalSet); encodeMemoryTags(encoder, ElementId.ELEM_GLOBAL, globalSet);
saveReturnAddress(buffer); // Must come before PrototypeModels encodeReturnAddress(encoder); // Must come before PrototypeModels
pcodeInject.saveCompilerSpecXml(buffer); pcodeInject.encodeCompilerSpec(encoder);
if (defaultModel != null) { if (defaultModel != null) {
buffer.append("<default_proto>\n"); encoder.openElement(ElementId.ELEM_DEFAULT_PROTO);
defaultModel.saveXml(buffer, pcodeInject); defaultModel.encode(encoder, pcodeInject);
buffer.append("</default_proto>\n"); encoder.closeElement(ElementId.ELEM_DEFAULT_PROTO);
} }
for (PrototypeModel model : allmodels) { for (PrototypeModel model : allmodels) {
if (model == defaultModel) { if (model == defaultModel) {
continue; // Already emitted continue; // Already emitted
} }
model.saveXml(buffer, pcodeInject); model.encode(encoder, pcodeInject);
} }
if (evalCurrentModel != null && evalCurrentModel != defaultModel) { if (evalCurrentModel != null && evalCurrentModel != defaultModel) {
buffer.append("<eval_current_prototype"); encoder.openElement(ElementId.ELEM_EVAL_CURRENT_PROTOTYPE);
SpecXmlUtils.encodeStringAttribute(buffer, "name", evalCurrentModel.name); encoder.writeString(AttributeId.ATTRIB_NAME, evalCurrentModel.name);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_EVAL_CURRENT_PROTOTYPE);
} }
if (evalCalledModel != null && evalCalledModel != defaultModel) { if (evalCalledModel != null && evalCalledModel != defaultModel) {
buffer.append("<eval_called_prototype"); encoder.openElement(ElementId.ELEM_EVAL_CALLED_PROTOTYPE);
SpecXmlUtils.encodeStringAttribute(buffer, "name", evalCalledModel.name); encoder.writeString(AttributeId.ATTRIB_NAME, evalCalledModel.name);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_EVAL_CALLED_PROTOTYPE);
} }
savePreferSplit(buffer); encodePreferSplit(encoder);
saveMemoryTags(buffer, "nohighptr", noHighPtr); encodeMemoryTags(encoder, ElementId.ELEM_NOHIGHPTR, noHighPtr);
saveMemoryTags(buffer, "readonly", readOnlySet); encodeMemoryTags(encoder, ElementId.ELEM_READONLY, readOnlySet);
if (funcPtrAlign != 0) { if (funcPtrAlign != 0) {
buffer.append("<funcptr"); encoder.openElement(ElementId.ELEM_FUNCPTR);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "align", funcPtrAlign); encoder.writeSignedInteger(AttributeId.ATTRIB_ALIGN, funcPtrAlign);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_FUNCPTR);
} }
saveDeadCodeDelay(buffer); encodeDeadCodeDelay(encoder);
saveInferPtrBounds(buffer); encodeInferPtrBounds(encoder);
buffer.append("</compiler_spec>"); encoder.closeElement(ElementId.ELEM_COMPILER_SPEC);
} }
/** /**
@ -712,18 +711,18 @@ public class BasicCompilerSpec implements CompilerSpec {
} }
} }
private void saveProperties(StringBuilder buffer) { private void encodeProperties(Encoder encoder) throws IOException {
if (properties.isEmpty()) { if (properties.isEmpty()) {
return; return;
} }
buffer.append("<properties>\n"); encoder.openElement(ElementId.ELEM_PROPERTIES);
for (Entry<String, String> property : properties.entrySet()) { for (Entry<String, String> property : properties.entrySet()) {
buffer.append("<property"); encoder.openElement(ElementId.ELEM_PROPERTY);
SpecXmlUtils.encodeStringAttribute(buffer, "key", property.getKey()); encoder.writeString(AttributeId.ATTRIB_KEY, property.getKey());
SpecXmlUtils.encodeStringAttribute(buffer, "value", property.getValue()); encoder.writeString(AttributeId.ATTRIB_VALUE, property.getValue());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_PROPERTY);
} }
buffer.append("</properties>\n"); encoder.closeElement(ElementId.ELEM_PROPERTIES);
} }
private void restoreProperties(XmlPullParser parser) { private void restoreProperties(XmlPullParser parser) {
@ -743,16 +742,16 @@ public class BasicCompilerSpec implements CompilerSpec {
parser.end(); parser.end();
} }
private void saveSpaceBases(StringBuilder buffer) { private void encodeSpaceBases(Encoder encoder) throws IOException {
if (spaceBases == null) { if (spaceBases == null) {
return; return;
} }
for (Entry<String, Pair<AddressSpace, String>> entry : spaceBases.entrySet()) { for (Entry<String, Pair<AddressSpace, String>> entry : spaceBases.entrySet()) {
buffer.append("<spacebase"); encoder.openElement(ElementId.ELEM_SPACEBASE);
SpecXmlUtils.encodeStringAttribute(buffer, "name", entry.getKey()); encoder.writeString(AttributeId.ATTRIB_NAME, entry.getKey());
SpecXmlUtils.encodeStringAttribute(buffer, "register", entry.getValue().second); encoder.writeString(AttributeId.ATTRIB_REGISTER, entry.getValue().second);
SpecXmlUtils.encodeStringAttribute(buffer, "space", entry.getValue().first.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, entry.getValue().first);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_SPACEBASE);
} }
} }
@ -776,15 +775,15 @@ public class BasicCompilerSpec implements CompilerSpec {
parser.end(el); parser.end(el);
} }
private void saveReturnAddress(StringBuilder buffer) { private void encodeReturnAddress(Encoder encoder) throws IOException {
if (returnAddress == null) { if (returnAddress == null) {
return; return;
} }
buffer.append("<returnaddress>\n"); encoder.openElement(ElementId.ELEM_RETURNADDRESS);
buffer.append("<varnode"); encoder.openElement(ElementId.ELEM_VARNODE);
AddressXML.appendAttributes(buffer, returnAddress.getAddress(), returnAddress.getSize()); AddressXML.encodeAttributes(encoder, returnAddress.getAddress(), returnAddress.getSize());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_VARNODE);
buffer.append("</returnaddress>\n"); encoder.closeElement(ElementId.ELEM_RETURNADDRESS);
} }
private void restoreReturnAddress(XmlPullParser parser) throws XmlParseException { private void restoreReturnAddress(XmlPullParser parser) throws XmlParseException {
@ -819,12 +818,12 @@ public class BasicCompilerSpec implements CompilerSpec {
extraRanges.add(new Pair<>(tagName + '_' + spcName, new Pair<>(first, last))); extraRanges.add(new Pair<>(tagName + '_' + spcName, new Pair<>(first, last)));
} }
private void saveExtraRanges(StringBuilder buffer, String tagName) { private void encodeExtraRanges(Encoder encoder, ElementId tag) throws IOException {
if (extraRanges == null) { if (extraRanges == null) {
return; return;
} }
for (Pair<String, Pair<Long, Long>> entry : extraRanges) { for (Pair<String, Pair<Long, Long>> entry : extraRanges) {
if (!entry.first.startsWith(tagName)) { if (!entry.first.startsWith(tag.getName())) {
continue; continue;
} }
String spcName = entry.first.substring(entry.first.indexOf('_') + 1); String spcName = entry.first.substring(entry.first.indexOf('_') + 1);
@ -832,32 +831,34 @@ public class BasicCompilerSpec implements CompilerSpec {
long last = entry.second.second; long last = entry.second.second;
boolean useFirst = (first != 0); boolean useFirst = (first != 0);
boolean useLast = (last != -1); boolean useLast = (last != -1);
buffer.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
SpecXmlUtils.encodeStringAttribute(buffer, "space", spcName); // Must use string encoding here, as address space may not exist
encoder.writeString(AttributeId.ATTRIB_SPACE, spcName);
if (useFirst) { if (useFirst) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first", first); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first);
} }
if (useLast) { if (useLast) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", last); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last);
} }
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_RANGE);
} }
} }
private void saveMemoryTags(StringBuilder buffer, String tagName, AddressSet addrSet) { private void encodeMemoryTags(Encoder encoder, ElementId tag, AddressSet addrSet)
throws IOException {
if (addrSet == null) { if (addrSet == null) {
return; return;
} }
buffer.append('<').append(tagName).append(">\n"); encoder.openElement(tag);
AddressRangeIterator iter = addrSet.getAddressRanges(); AddressRangeIterator iter = addrSet.getAddressRanges();
while (iter.hasNext()) { while (iter.hasNext()) {
AddressRange range = iter.next(); AddressRange range = iter.next();
buffer.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
AddressXML.appendAttributes(buffer, range.getMinAddress(), range.getMaxAddress()); AddressXML.encodeAttributes(encoder, range.getMinAddress(), range.getMaxAddress());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_RANGE);
} }
saveExtraRanges(buffer, tagName); encodeExtraRanges(encoder, tag);
buffer.append("</").append(tagName).append(">\n"); encoder.closeElement(tag);
} }
private void restoreMemoryTags(String tagName, XmlPullParser parser, AddressSet addrSet) private void restoreMemoryTags(String tagName, XmlPullParser parser, AddressSet addrSet)
@ -903,17 +904,18 @@ public class BasicCompilerSpec implements CompilerSpec {
parser.end(el); parser.end(el);
} }
private void savePreferSplit(StringBuilder buffer) { private void encodePreferSplit(Encoder encoder) throws IOException {
if (preferSplit == null || preferSplit.isEmpty()) { if (preferSplit == null || preferSplit.isEmpty()) {
return; return;
} }
buffer.append("<prefersplit style=\"inhalf\">\n"); encoder.openElement(ElementId.ELEM_PREFERSPLIT);
encoder.writeString(AttributeId.ATTRIB_STYLE, "inhalf");
for (Varnode varnode : preferSplit) { for (Varnode varnode : preferSplit) {
buffer.append("<varnode"); encoder.openElement(ElementId.ELEM_VARNODE);
AddressXML.appendAttributes(buffer, varnode.getAddress(), varnode.getSize()); AddressXML.encodeAttributes(encoder, varnode.getAddress(), varnode.getSize());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_VARNODE);
} }
buffer.append("</prefersplit>\n"); encoder.closeElement(ElementId.ELEM_PREFERSPLIT);
} }
private void restoreDeadCodeDelay(XmlPullParser parser) { private void restoreDeadCodeDelay(XmlPullParser parser) {
@ -927,15 +929,15 @@ public class BasicCompilerSpec implements CompilerSpec {
parser.end(el); parser.end(el);
} }
private void saveDeadCodeDelay(StringBuilder buffer) { private void encodeDeadCodeDelay(Encoder encoder) throws IOException {
if (deadCodeDelay == null) { if (deadCodeDelay == null) {
return; return;
} }
for (Pair<AddressSpace, Integer> pair : deadCodeDelay) { for (Pair<AddressSpace, Integer> pair : deadCodeDelay) {
buffer.append("<deadcodedelay"); encoder.openElement(ElementId.ELEM_DEADCODEDELAY);
SpecXmlUtils.encodeStringAttribute(buffer, "space", pair.first.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, pair.first);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "delay", pair.second.intValue()); encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, pair.second.intValue());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_DEADCODEDELAY);
} }
} }
@ -955,18 +957,18 @@ public class BasicCompilerSpec implements CompilerSpec {
parser.end(el); parser.end(el);
} }
private void saveInferPtrBounds(StringBuilder buffer) { private void encodeInferPtrBounds(Encoder encoder) throws IOException {
if (inferPtrBounds == null) { if (inferPtrBounds == null) {
return; return;
} }
buffer.append("<inferptrbounds>\n"); encoder.openElement(ElementId.ELEM_INFERPTRBOUNDS);
for (AddressRange addrRange : inferPtrBounds) { for (AddressRange addrRange : inferPtrBounds) {
buffer.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
AddressXML.appendAttributes(buffer, addrRange.getMinAddress(), AddressXML.encodeAttributes(encoder, addrRange.getMinAddress(),
addrRange.getMaxAddress()); addrRange.getMaxAddress());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_RANGE);
} }
buffer.append("</inferptrbounds>\n"); encoder.closeElement(ElementId.ELEM_INFERPTRBOUNDS);
} }
private void setStackPointer(XmlPullParser parser) { private void setStackPointer(XmlPullParser parser) {

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.Set; import java.util.Set;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -23,6 +24,7 @@ import ghidra.program.model.data.DataOrganization;
import ghidra.program.model.data.GenericCallingConvention; import ghidra.program.model.data.GenericCallingConvention;
import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.listing.DefaultProgramContext;
import ghidra.program.model.listing.Parameter; import ghidra.program.model.listing.Parameter;
import ghidra.program.model.pcode.Encoder;
/** /**
* Interface for requesting specific information about the compiler used to * Interface for requesting specific information about the compiler used to
@ -239,11 +241,12 @@ public interface CompilerSpec {
public Set<String> getPropertyKeys(); public Set<String> getPropertyKeys();
/** /**
* Marshal this entire specification to an XML stream. An XML document is written with * Encode this entire specification to a stream. A document is written with
* root tag \<compiler_spec>. * root element \<compiler_spec>.
* @param buffer is the XML stream * @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/ */
public void saveXml(StringBuilder buffer); public void encode(Encoder encoder) throws IOException;
/** /**
* Determine if this CompilerSpec is equivalent to another specified instance * Determine if this CompilerSpec is equivalent to another specified instance

View file

@ -15,11 +15,11 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.PcodeDataTypeManager; import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* Class for manipulating "deferred" constant systems like the java virtual machine constant pool * Class for manipulating "deferred" constant systems like the java virtual machine constant pool
@ -43,45 +43,46 @@ public abstract class ConstantPool {
public DataType type; public DataType type;
public boolean isConstructor = false; public boolean isConstructor = false;
public StringBuilder build(long ref, PcodeDataTypeManager dtmanage) { public void encode(Encoder encoder, long ref, PcodeDataTypeManager dtmanage)
StringBuilder buf = new StringBuilder(); throws IOException {
buf.append("<cpoolrec"); encoder.openElement(ElementId.ELEM_CPOOLREC);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "ref", ref); encoder.writeUnsignedInteger(AttributeId.ATTRIB_REF, ref);
if (tag == STRING_LITERAL) { if (tag == STRING_LITERAL) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "string"); encoder.writeString(AttributeId.ATTRIB_TAG, "string");
} }
else if (tag == CLASS_REFERENCE) { else if (tag == CLASS_REFERENCE) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "classref"); encoder.writeString(AttributeId.ATTRIB_TAG, "classref");
} }
else if (tag == POINTER_METHOD) { else if (tag == POINTER_METHOD) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "method"); encoder.writeString(AttributeId.ATTRIB_TAG, "method");
} }
else if (tag == POINTER_FIELD) { else if (tag == POINTER_FIELD) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "field"); encoder.writeString(AttributeId.ATTRIB_TAG, "field");
} }
else if (tag == ARRAY_LENGTH) { else if (tag == ARRAY_LENGTH) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "arraylength"); encoder.writeString(AttributeId.ATTRIB_TAG, "arraylength");
} }
else if (tag == INSTANCE_OF) { else if (tag == INSTANCE_OF) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "instanceof"); encoder.writeString(AttributeId.ATTRIB_TAG, "instanceof");
} }
else if (tag == CHECK_CAST) { else if (tag == CHECK_CAST) {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "checkcast"); encoder.writeString(AttributeId.ATTRIB_TAG, "checkcast");
} }
else { else {
SpecXmlUtils.encodeStringAttribute(buf, "tag", "primitive"); encoder.writeString(AttributeId.ATTRIB_TAG, "primitive");
} }
if (isConstructor) { if (isConstructor) {
SpecXmlUtils.encodeBooleanAttribute(buf, "constructor", true); encoder.writeBool(AttributeId.ATTRIB_CONSTRUCTOR, true);
} }
buf.append(">\n");
if (tag == PRIMITIVE) { if (tag == PRIMITIVE) {
buf.append("<value>"); encoder.openElement(ElementId.ELEM_VALUE);
buf.append(SpecXmlUtils.encodeUnsignedInteger(value)); encoder.writeUnsignedInteger(AttributeId.ATTRIB_CONTENT, value);
buf.append("</value>\n"); encoder.closeElement(ElementId.ELEM_VALUE);
} }
if (byteData != null) { if (byteData != null) {
buf.append("<data length=\"").append(byteData.length).append("\">\n"); encoder.openElement(ElementId.ELEM_DATA);
encoder.writeSignedInteger(AttributeId.ATTRIB_LENGTH, byteData.length);
StringBuilder buf = new StringBuilder();
int wrap = 0; int wrap = 0;
for (byte val : byteData) { for (byte val : byteData) {
int hival = (val >> 4) & 0xf; int hival = (val >> 4) & 0xf;
@ -95,16 +96,16 @@ public abstract class ConstantPool {
wrap = 0; wrap = 0;
} }
} }
buf.append("</data>\n"); encoder.writeString(AttributeId.ATTRIB_CONTENT, buf.toString());
encoder.closeElement(ElementId.ELEM_DATA);
} }
else { else {
buf.append("<token>"); encoder.openElement(ElementId.ELEM_TOKEN);
SpecXmlUtils.xmlEscape(buf, token); encoder.writeString(AttributeId.ATTRIB_CONTENT, token);
buf.append("</token>\n"); encoder.closeElement(ElementId.ELEM_TOKEN);
} }
dtmanage.buildTypeRef(buf, type, type.getLength()); dtmanage.encodeTypeRef(encoder, type, type.getLength());
buf.append("</cpoolrec>\n"); encoder.closeElement(ElementId.ELEM_CPOOLREC);
return buf;
} }
public void setUTF8Data(String val) { public void setUTF8Data(String val) {

View file

@ -15,14 +15,14 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.app.plugin.processors.sleigh.SleighException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.AddressXML; import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
/** /**
@ -101,11 +101,11 @@ public final class ContextSetting {
} }
} }
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<set"); encoder.openElement(ElementId.ELEM_SET);
SpecXmlUtils.encodeStringAttribute(buffer, "name", register.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, register.getName());
SpecXmlUtils.encodeStringAttribute(buffer, "val", value.toString()); encoder.writeString(AttributeId.ATTRIB_VAL, value.toString());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_SET);
} }
/** /**
@ -164,21 +164,22 @@ public final class ContextSetting {
parser.end(); parser.end();
} }
public static void buildContextDataXml(StringBuilder buffer, List<ContextSetting> ctxList) { public static void encodeContextData(Encoder encoder, List<ContextSetting> ctxList)
throws IOException {
if (ctxList.isEmpty()) { if (ctxList.isEmpty()) {
return; return;
} }
buffer.append("<context_data>\n"); encoder.openElement(ElementId.ELEM_CONTEXT_DATA);
Iterator<ContextSetting> iter = ctxList.iterator(); Iterator<ContextSetting> iter = ctxList.iterator();
ContextSetting startContext = iter.next(); ContextSetting startContext = iter.next();
boolean isContextReg = startContext.register.isProcessorContext(); boolean isContextReg = startContext.register.isProcessorContext();
Address firstAddr = startContext.startAddr; Address firstAddr = startContext.startAddr;
Address lastAddr = startContext.endAddr; Address lastAddr = startContext.endAddr;
while (iter.hasNext()) { while (iter.hasNext()) {
buffer.append(isContextReg ? "<context_set" : "<tracked_set"); encoder.openElement(
AddressXML.appendAttributes(buffer, firstAddr, lastAddr); isContextReg ? ElementId.ELEM_CONTEXT_SET : ElementId.ELEM_TRACKED_SET);
buffer.append(">\n"); AddressXML.encodeAttributes(encoder, firstAddr, lastAddr);
startContext.saveXml(buffer); startContext.encode(encoder);
while (iter.hasNext()) { while (iter.hasNext()) {
startContext = iter.next(); startContext = iter.next();
boolean nextIsContext = startContext.register.isProcessorContext(); boolean nextIsContext = startContext.register.isProcessorContext();
@ -198,10 +199,11 @@ public final class ContextSetting {
if (shouldBreak) { if (shouldBreak) {
break; break;
} }
startContext.saveXml(buffer); startContext.encode(encoder);
} }
buffer.append(isContextReg ? "</context_set>\n" : "</tracked_set>\n"); encoder.closeElement(
isContextReg ? ElementId.ELEM_CONTEXT_SET : ElementId.ELEM_TRACKED_SET);
} }
buffer.append("</context_data>\n"); encoder.closeElement(ElementId.ELEM_CONTEXT_DATA);
} }
} }

View file

@ -15,9 +15,12 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import ghidra.app.plugin.processors.sleigh.PcodeEmit; import ghidra.app.plugin.processors.sleigh.PcodeEmit;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.Encoder;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.PcodeOp;
import ghidra.xml.XmlParseException; import ghidra.xml.XmlParseException;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -142,10 +145,11 @@ public interface InjectPayload {
public boolean isIncidentalCopy(); public boolean isIncidentalCopy();
/** /**
* Write out configuration parameters as a \<pcode> XML tag * Encode configuration parameters as a \<pcode> element to stream
* @param buffer is the stream to write to * @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/ */
public void saveXml(StringBuilder buffer); public void encode(Encoder encoder) throws IOException;
/** /**
* Restore the payload from an XML stream. The root expected document is * Restore the payload from an XML stream. The root expected document is

View file

@ -15,12 +15,13 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.*;
import ghidra.xml.*; import ghidra.xml.*;
public class InjectPayloadCallfixup extends InjectPayloadSleigh { public class InjectPayloadCallfixup extends InjectPayloadSleigh {
@ -58,17 +59,16 @@ public class InjectPayloadCallfixup extends InjectPayloadSleigh {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<callfixup"); encoder.openElement(ElementId.ELEM_CALLFIXUP);
SpecXmlUtils.encodeStringAttribute(buffer, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
buffer.append(">\n");
for (String nm : targetSymbolNames) { for (String nm : targetSymbolNames) {
buffer.append("<target"); encoder.openElement(ElementId.ELEM_TARGET);
SpecXmlUtils.encodeStringAttribute(buffer, "name", nm); encoder.writeString(AttributeId.ATTRIB_NAME, nm);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_TARGET);
} }
super.saveXml(buffer); super.encode(encoder);
buffer.append("</callfixup>\n"); encoder.closeElement(ElementId.ELEM_CALLFIXUP);
} }
@Override @Override

View file

@ -15,9 +15,11 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.*;
import ghidra.xml.*; import ghidra.xml.*;
public class InjectPayloadCallother extends InjectPayloadSleigh { public class InjectPayloadCallother extends InjectPayloadSleigh {
@ -46,12 +48,11 @@ public class InjectPayloadCallother extends InjectPayloadSleigh {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<callotherfixup"); encoder.openElement(ElementId.ELEM_CALLOTHERFIXUP);
SpecXmlUtils.encodeStringAttribute(buffer, "targetop", name); encoder.writeString(AttributeId.ATTRIB_TARGETOP, name);
buffer.append(">\n"); super.encode(encoder);
super.saveXml(buffer); encoder.closeElement(ElementId.ELEM_CALLOTHERFIXUP);
buffer.append("</callotherfixup>\n");
} }
@Override @Override

View file

@ -15,9 +15,11 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.pcode.AddressXML; import ghidra.program.model.pcode.*;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -41,29 +43,28 @@ public class InjectPayloadSegment extends InjectPayloadSleigh {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<segmentop"); encoder.openElement(ElementId.ELEM_SEGMENTOP);
int pos = name.indexOf('_'); int pos = name.indexOf('_');
String subName = pos > 0 ? name.substring(0, pos) : name; String subName = pos > 0 ? name.substring(0, pos) : name;
if (!subName.equals("segment")) { if (!subName.equals("segment")) {
SpecXmlUtils.encodeStringAttribute(buffer, "userop", subName); encoder.writeString(AttributeId.ATTRIB_USEROP, subName);
} }
SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
if (supportsFarPointer) { if (supportsFarPointer) {
SpecXmlUtils.encodeBooleanAttribute(buffer, "farpointer", supportsFarPointer); encoder.writeBool(AttributeId.ATTRIB_FARPOINTER, supportsFarPointer);
} }
buffer.append(">\n"); super.encode(encoder);
super.saveXml(buffer);
if (constResolveSpace != null) { if (constResolveSpace != null) {
buffer.append("<constresolve>\n"); encoder.openElement(ElementId.ELEM_CONSTRESOLVE);
buffer.append("<varnode"); encoder.openElement(ElementId.ELEM_VARNODE);
SpecXmlUtils.encodeStringAttribute(buffer, "space", constResolveSpace.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, constResolveSpace);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "offset", constResolveOffset); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, constResolveOffset);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "size", constResolveSize); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, constResolveSize);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_VARNODE);
buffer.append("</constresolve>\n"); encoder.closeElement(ElementId.ELEM_CONSTRESOLVE);
} }
buffer.append("</segmentop>\n"); encoder.closeElement(ElementId.ELEM_SEGMENTOP);
} }
@Override @Override

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -24,8 +25,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory; import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -230,39 +230,40 @@ public class InjectPayloadSleigh implements InjectPayload {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<pcode"); encoder.openElement(ElementId.ELEM_PCODE);
if (type == CALLMECHANISM_TYPE && subType >= 0) { if (type == CALLMECHANISM_TYPE && subType >= 0) {
SpecXmlUtils.encodeStringAttribute(buffer, "inject", encoder.writeString(AttributeId.ATTRIB_INJECT,
(subType == 0) ? "uponentry" : "uponreturn"); (subType == 0) ? "uponentry" : "uponreturn");
} }
if (paramShift != 0) { if (paramShift != 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "paramshift", paramShift); encoder.writeSignedInteger(AttributeId.ATTRIB_PARAMSHIFT, paramShift);
} }
if (pcodeTemplate == null) { if (pcodeTemplate == null) {
SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true); encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true);
} }
if (incidentalCopy) { if (incidentalCopy) {
SpecXmlUtils.encodeBooleanAttribute(buffer, "incidentalcopy", incidentalCopy); encoder.writeBool(AttributeId.ATTRIB_INCIDENTALCOPY, incidentalCopy);
} }
buffer.append(">\n");
for (InjectParameter param : inputlist) { for (InjectParameter param : inputlist) {
buffer.append("<input"); encoder.openElement(ElementId.ELEM_INPUT);
SpecXmlUtils.encodeStringAttribute(buffer, "name", param.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, param.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "size", param.getSize()); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, param.getSize());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_INPUT);
} }
for (InjectParameter param : output) { for (InjectParameter param : output) {
buffer.append("<output"); encoder.openElement(ElementId.ELEM_OUTPUT);
SpecXmlUtils.encodeStringAttribute(buffer, "name", param.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, param.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "size", param.getSize()); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, param.getSize());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_OUTPUT);
} }
if (pcodeTemplate != null) { if (pcodeTemplate != null) {
// Decompiler will not read the <body> tag // Decompiler will not read the <body> tag
buffer.append("<body> local tmp:1 = 0; </body>\n"); encoder.openElement(ElementId.ELEM_BODY);
encoder.writeString(AttributeId.ATTRIB_CONTENT, " local tmp:1 = 0; ");
encoder.closeElement(ElementId.ELEM_BODY);
} }
buffer.append("</pcode>\n"); encoder.closeElement(ElementId.ELEM_PCODE);
} }
@Override @Override

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -22,8 +23,7 @@ import ghidra.app.plugin.processors.sleigh.VarnodeData;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.pcode.AddressXML; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -437,16 +437,16 @@ public class ParamEntry {
flags |= OVERLAPPING; flags |= OVERLAPPING;
} }
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<pentry"); encoder.openElement(ElementId.ELEM_PENTRY);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "minsize", minsize); encoder.writeSignedInteger(AttributeId.ATTRIB_MINSIZE, minsize);
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "maxsize", size); encoder.writeSignedInteger(AttributeId.ATTRIB_MAXSIZE, size);
if (alignment != 0) { if (alignment != 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "align", alignment); encoder.writeSignedInteger(AttributeId.ATTRIB_ALIGN, alignment);
} }
if (type == TYPE_FLOAT || type == TYPE_PTR) { if (type == TYPE_FLOAT || type == TYPE_PTR) {
String tok = (type == TYPE_FLOAT) ? "float" : "ptr"; String tok = (type == TYPE_FLOAT) ? "float" : "ptr";
SpecXmlUtils.encodeStringAttribute(buffer, "metatype", tok); encoder.writeString(AttributeId.ATTRIB_METATYPE, tok);
} }
String extString = null; String extString = null;
if ((flags & SMALLSIZE_SEXT) != 0) { if ((flags & SMALLSIZE_SEXT) != 0) {
@ -462,9 +462,8 @@ public class ParamEntry {
extString = "float"; extString = "float";
} }
if (extString != null) { if (extString != null) {
SpecXmlUtils.encodeStringAttribute(buffer, "extension", extString); encoder.writeString(AttributeId.ATTRIB_EXTENSION, extString);
} }
buffer.append(">\n");
AddressXML addressSize; AddressXML addressSize;
if (joinrec == null) { if (joinrec == null) {
// Treat as unsized address with no size // Treat as unsized address with no size
@ -473,8 +472,8 @@ public class ParamEntry {
else { else {
addressSize = new AddressXML(spaceid, addressbase, size, joinrec); addressSize = new AddressXML(spaceid, addressbase, size, joinrec);
} }
addressSize.saveXml(buffer); addressSize.encode(encoder);
buffer.append("</pentry>"); encoder.closeElement(ElementId.ELEM_PENTRY);
} }
public void restoreXml(XmlPullParser parser, CompilerSpec cspec, List<ParamEntry> curList, public void restoreXml(XmlPullParser parser, CompilerSpec cspec, List<ParamEntry> curList,

View file

@ -15,12 +15,14 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.program.model.pcode.Encoder;
import ghidra.xml.XmlParseException; import ghidra.xml.XmlParseException;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -44,7 +46,7 @@ public interface ParamList {
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res, public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
boolean addAutoParams); boolean addAutoParams);
public void saveXml(StringBuilder buffer, boolean isInput); public void encode(Encoder encoder, boolean isInput) throws IOException;
public void restoreXml(XmlPullParser parser, CompilerSpec cspec) throws XmlParseException; public void restoreXml(XmlPullParser parser, CompilerSpec cspec) throws XmlParseException;

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.VarnodeData; import ghidra.app.plugin.processors.sleigh.VarnodeData;
@ -22,7 +23,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.Varnode; import ghidra.program.model.pcode.*;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
@ -199,39 +200,37 @@ public class ParamListStandard implements ParamList {
} }
@Override @Override
public void saveXml(StringBuilder buffer, boolean isInput) { public void encode(Encoder encoder, boolean isInput) throws IOException {
buffer.append(isInput ? "<input" : "<output"); encoder.openElement(isInput ? ElementId.ELEM_INPUT : ElementId.ELEM_OUTPUT);
if (pointermax != 0) { if (pointermax != 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "pointermax", pointermax); encoder.writeSignedInteger(AttributeId.ATTRIB_POINTERMAX, pointermax);
} }
if (thisbeforeret) { if (thisbeforeret) {
SpecXmlUtils.encodeStringAttribute(buffer, "thisbeforeretpointer", "yes"); encoder.writeBool(AttributeId.ATTRIB_THISBEFORERETPOINTER, true);
} }
if (isInput && resourceTwoStart == 0) { if (isInput && resourceTwoStart == 0) {
SpecXmlUtils.encodeBooleanAttribute(buffer, "separatefloat", false); encoder.writeBool(AttributeId.ATTRIB_SEPARATEFLOAT, false);
} }
buffer.append(">\n");
int curgroup = -1; int curgroup = -1;
for (ParamEntry el : entry) { for (ParamEntry el : entry) {
if (curgroup >= 0) { if (curgroup >= 0) {
if (!el.isGrouped() || el.getGroup() != curgroup) { if (!el.isGrouped() || el.getGroup() != curgroup) {
buffer.append("</group>\n"); encoder.closeElement(ElementId.ELEM_GROUP);
curgroup = -1; curgroup = -1;
} }
} }
if (el.isGrouped()) { if (el.isGrouped()) {
if (curgroup < 0) { if (curgroup < 0) {
buffer.append("<group>\n"); encoder.openElement(ElementId.ELEM_GROUP);
curgroup = el.getGroup(); curgroup = el.getGroup();
} }
} }
el.saveXml(buffer); el.encode(encoder);
buffer.append('\n');
} }
if (curgroup >= 0) { if (curgroup >= 0) {
buffer.append("</group>\n"); encoder.closeElement(ElementId.ELEM_GROUP);
} }
buffer.append(isInput ? "</input>" : "</output>"); encoder.closeElement(isInput ? ElementId.ELEM_INPUT : ElementId.ELEM_OUTPUT);
} }
private void parsePentry(XmlPullParser parser, CompilerSpec cspec, ArrayList<ParamEntry> pe, private void parsePentry(XmlPullParser parser, CompilerSpec cspec, ArrayList<ParamEntry> pe,

View file

@ -23,6 +23,7 @@ import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.program.model.lang.InjectPayload.InjectParameter; import ghidra.program.model.lang.InjectPayload.InjectParameter;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.Encoder;
import ghidra.sleigh.grammar.Location; import ghidra.sleigh.grammar.Location;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.xml.XmlParseException; import ghidra.xml.XmlParseException;
@ -375,25 +376,26 @@ public class PcodeInjectLibrary {
} }
/** /**
* Save the parts of the inject library that come from the compiler spec * Encode the parts of the inject library that come from the compiler spec
* to the output stream as XML tags * to the output stream
* @param buffer is the output stream * @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/ */
public void saveCompilerSpecXml(StringBuilder buffer) { public void encodeCompilerSpec(Encoder encoder) throws IOException {
for (InjectPayload injectPayload : callFixupMap.values()) { for (InjectPayload injectPayload : callFixupMap.values()) {
if (injectPayload instanceof InjectPayloadSleigh) { if (injectPayload instanceof InjectPayloadSleigh) {
((InjectPayloadSleigh) injectPayload).saveXml(buffer); ((InjectPayloadSleigh) injectPayload).encode(encoder);
} }
} }
for (InjectPayload injectPayload : callOtherFixupMap.values()) { for (InjectPayload injectPayload : callOtherFixupMap.values()) {
if (injectPayload instanceof InjectPayloadSleigh) { if (injectPayload instanceof InjectPayloadSleigh) {
((InjectPayloadSleigh) injectPayload).saveXml(buffer); ((InjectPayloadSleigh) injectPayload).encode(encoder);
} }
} }
for (InjectPayload injectPayload : exePcodeMap.values()) { for (InjectPayload injectPayload : exePcodeMap.values()) {
if (injectPayload instanceof InjectPayloadSegment) { if (injectPayload instanceof InjectPayloadSegment) {
if (injectPayload.getSource().startsWith("cspec")) { if (injectPayload.getSource().startsWith("cspec")) {
((InjectPayloadSleigh) injectPayload).saveXml(buffer); ((InjectPayloadSleigh) injectPayload).encode(encoder);
} }
} }
} }

View file

@ -15,14 +15,14 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.database.SpecExtension; import ghidra.program.database.SpecExtension;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.AddressXML; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
@ -417,89 +417,87 @@ public class PrototypeModel {
} }
/** /**
* Marshal this object as XML to an output buffer * Encode this object to an output stream
* @param buffer is the output buffer * @param encoder is the stream encoder
* @param injectLibrary is a library containing any inject payloads associated with the model * @param injectLibrary is a library containing any inject payloads associated with the model
* @throws IOException for errors writing to the underlying stream
*/ */
public void saveXml(StringBuilder buffer, PcodeInjectLibrary injectLibrary) { public void encode(Encoder encoder, PcodeInjectLibrary injectLibrary) throws IOException {
if (compatModel != null) { if (compatModel != null) {
buffer.append("<modelalias"); encoder.openElement(ElementId.ELEM_MODELALIAS);
SpecXmlUtils.encodeStringAttribute(buffer, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
SpecXmlUtils.encodeStringAttribute(buffer, "parent", compatModel.name); encoder.writeString(AttributeId.ATTRIB_PARENT, compatModel.name);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_MODELALIAS);
return; return;
} }
buffer.append("<prototype"); encoder.openElement(ElementId.ELEM_PROTOTYPE);
SpecXmlUtils.encodeStringAttribute(buffer, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
if (extrapop != PrototypeModel.UNKNOWN_EXTRAPOP) { if (extrapop != PrototypeModel.UNKNOWN_EXTRAPOP) {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "extrapop", extrapop); encoder.writeSignedInteger(AttributeId.ATTRIB_EXTRAPOP, extrapop);
} }
else { else {
SpecXmlUtils.encodeStringAttribute(buffer, "extrapop", "unknown"); encoder.writeString(AttributeId.ATTRIB_EXTRAPOP, "unknown");
} }
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "stackshift", stackshift); encoder.writeSignedInteger(AttributeId.ATTRIB_STACKSHIFT, stackshift);
GenericCallingConvention nameType = GenericCallingConvention.guessFromName(name); GenericCallingConvention nameType = GenericCallingConvention.guessFromName(name);
if (nameType != genericCallingConvention) { if (nameType != genericCallingConvention) {
SpecXmlUtils.encodeStringAttribute(buffer, "type", encoder.writeString(AttributeId.ATTRIB_TYPE,
genericCallingConvention.getDeclarationName()); genericCallingConvention.getDeclarationName());
} }
if (hasThis) { if (hasThis) {
SpecXmlUtils.encodeStringAttribute(buffer, "hasthis", "yes"); encoder.writeBool(AttributeId.ATTRIB_HASTHIS, true);
} }
if (isConstruct) { if (isConstruct) {
SpecXmlUtils.encodeStringAttribute(buffer, "constructor", "yes"); encoder.writeBool(AttributeId.ATTRIB_CONSTRUCTOR, true);
} }
if (inputListType != InputListType.STANDARD) { if (inputListType != InputListType.STANDARD) {
SpecXmlUtils.encodeStringAttribute(buffer, "strategy", "register"); encoder.writeString(AttributeId.ATTRIB_STRATEGY, "register");
} }
buffer.append(">\n"); inputParams.encode(encoder, true);
inputParams.saveXml(buffer, true); outputParams.encode(encoder, false);
buffer.append('\n');
outputParams.saveXml(buffer, false);
buffer.append('\n');
if (hasUponEntry || hasUponReturn) { if (hasUponEntry || hasUponReturn) {
InjectPayload payload = InjectPayload payload =
injectLibrary.getPayload(InjectPayload.CALLMECHANISM_TYPE, getInjectName()); injectLibrary.getPayload(InjectPayload.CALLMECHANISM_TYPE, getInjectName());
payload.saveXml(buffer); payload.encode(encoder);
} }
if (unaffected != null) { if (unaffected != null) {
buffer.append("<unaffected>\n"); encoder.openElement(ElementId.ELEM_UNAFFECTED);
writeVarnodes(buffer, unaffected); encodeVarnodes(encoder, unaffected);
buffer.append("</unaffected>\n"); encoder.closeElement(ElementId.ELEM_UNAFFECTED);
} }
if (killedbycall != null) { if (killedbycall != null) {
buffer.append("<killedbycall>\n"); encoder.openElement(ElementId.ELEM_KILLEDBYCALL);
writeVarnodes(buffer, killedbycall); encodeVarnodes(encoder, killedbycall);
buffer.append("</killedbycall>\n"); encoder.closeElement(ElementId.ELEM_KILLEDBYCALL);
} }
if (likelytrash != null) { if (likelytrash != null) {
buffer.append("<likelytrash>\n"); encoder.openElement(ElementId.ELEM_LIKELYTRASH);
writeVarnodes(buffer, likelytrash); encodeVarnodes(encoder, likelytrash);
buffer.append("</likelytrash>\n"); encoder.closeElement(ElementId.ELEM_LIKELYTRASH);
} }
if (returnaddress != null) { if (returnaddress != null) {
buffer.append("<returnaddress>\n"); encoder.openElement(ElementId.ELEM_RETURNADDRESS);
writeVarnodes(buffer, returnaddress); encodeVarnodes(encoder, returnaddress);
buffer.append("</returnaddress>\n"); encoder.closeElement(ElementId.ELEM_RETURNADDRESS);
} }
if (localRange != null && !localRange.isEmpty()) { if (localRange != null && !localRange.isEmpty()) {
buffer.append("<localrange>\n"); encoder.openElement(ElementId.ELEM_LOCALRANGE);
writeAddressSet(buffer, localRange); encodeAddressSet(encoder, localRange);
buffer.append("</localrange>\n"); encoder.closeElement(ElementId.ELEM_LOCALRANGE);
} }
if (paramRange != null && !paramRange.isEmpty()) { if (paramRange != null && !paramRange.isEmpty()) {
buffer.append("<paramrange>\n"); encoder.openElement(ElementId.ELEM_PARAMRANGE);
writeAddressSet(buffer, paramRange); encodeAddressSet(encoder, paramRange);
buffer.append("</paramrange>\n"); encoder.closeElement(ElementId.ELEM_PARAMRANGE);
} }
buffer.append("</prototype>\n"); encoder.closeElement(ElementId.ELEM_PROTOTYPE);
} }
private void writeVarnodes(StringBuilder buffer, Varnode[] varnodes) { private void encodeVarnodes(Encoder encoder, Varnode[] varnodes) throws IOException {
for (Varnode vn : varnodes) { for (Varnode vn : varnodes) {
buffer.append("<varnode"); encoder.openElement(ElementId.ELEM_VARNODE);
AddressXML.appendAttributes(buffer, vn.getAddress(), vn.getSize()); AddressXML.encodeAttributes(encoder, vn.getAddress(), vn.getSize());
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_VARNODE);
} }
} }
@ -523,7 +521,7 @@ public class PrototypeModel {
return res; return res;
} }
private void writeAddressSet(StringBuilder buffer, AddressSet addressSet) { private void encodeAddressSet(Encoder encoder, AddressSet addressSet) throws IOException {
AddressRangeIterator iter = addressSet.getAddressRanges(); AddressRangeIterator iter = addressSet.getAddressRanges();
while (iter.hasNext()) { while (iter.hasNext()) {
AddressRange addrRange = iter.next(); AddressRange addrRange = iter.next();
@ -543,22 +541,22 @@ public class PrototypeModel {
if (first < 0 && last >= 0) { // Range crosses 0 if (first < 0 && last >= 0) { // Range crosses 0
first &= mask; first &= mask;
// Split out the piece coming before 0 // Split out the piece coming before 0
buffer.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first", first); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", mask); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, mask);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_RANGE);
// Reset first,last to be the piece coming after 0 // Reset first,last to be the piece coming after 0
first = 0; first = 0;
} }
first &= mask; first &= mask;
last &= mask; last &= mask;
} }
buffer.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first", first); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", last); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_RANGE);
} }
} }

View file

@ -15,12 +15,13 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.app.plugin.processors.sleigh.SleighException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Parameter; import ghidra.program.model.listing.Parameter;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.*;
import ghidra.xml.*; import ghidra.xml.*;
/** /**
@ -54,16 +55,15 @@ public class PrototypeModelMerged extends PrototypeModel {
} }
@Override @Override
public void saveXml(StringBuilder buffer, PcodeInjectLibrary injectLibrary) { public void encode(Encoder encoder, PcodeInjectLibrary injectLibrary) throws IOException {
buffer.append("<resolveprototype"); encoder.openElement(ElementId.ELEM_RESOLVEPROTOTYPE);
SpecXmlUtils.encodeStringAttribute(buffer, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
buffer.append(">\n");
for (PrototypeModel model : modellist) { for (PrototypeModel model : modellist) {
buffer.append("<model"); encoder.openElement(ElementId.ELEM_MODEL);
SpecXmlUtils.encodeStringAttribute(buffer, "name", model.name); encoder.writeString(AttributeId.ATTRIB_NAME, model.name);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_MODEL);
} }
buffer.append("</resolveprototype>\n"); encoder.closeElement(ElementId.ELEM_RESOLVEPROTOTYPE);
} }
public void restoreXml(XmlPullParser parser, List<PrototypeModel> modelList) public void restoreXml(XmlPullParser parser, List<PrototypeModel> modelList)

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -127,10 +128,11 @@ public class AddressXML {
} }
/** /**
* Write this sized address as an \<addr> XML tag. * Encode this sized address as an \<addr> element to the stream
* @param buffer is the buffer to write to * @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
if (joinRecord != null) { if (joinRecord != null) {
long logicalSize = size; long logicalSize = size;
long sizeSum = 0; long sizeSum = 0;
@ -140,18 +142,18 @@ public class AddressXML {
if (sizeSum == size) { if (sizeSum == size) {
logicalSize = 0; logicalSize = 0;
} }
buildXML(buffer, joinRecord, logicalSize); encode(encoder, joinRecord, logicalSize);
return; return;
} }
buffer.append("<addr"); encoder.openElement(ElementId.ELEM_ADDR);
if (space != null) { if (space != null) {
SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "offset", offset); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, offset);
if (size != 0) { if (size != 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "size", size); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size);
} }
} }
buffer.append("/>"); encoder.closeElement(ElementId.ELEM_ADDR);
} }
/** /**
@ -432,12 +434,13 @@ public class AddressXML {
} }
/** /**
* Append "space" and "offset" attributes describing the given Address to the XML stream. * Encode "space" and "offset" attributes for the current element, describing the
* This assumes the XML tag name has already been emitted. * given Address to the stream.
* @param buf is the XML stream * @param encoder is the stream encoder
* @param addr is the given Address * @param addr is the given Address
* @throws IOException for errors in the underlying stream
*/ */
public static void appendAttributes(StringBuilder buf, Address addr) { public static void encodeAttributes(Encoder encoder, Address addr) throws IOException {
AddressSpace space = addr.getAddressSpace(); AddressSpace space = addr.getAddressSpace();
if (space.isOverlaySpace()) { if (space.isOverlaySpace()) {
if (space.getType() != AddressSpace.TYPE_OTHER) { if (space.getType() != AddressSpace.TYPE_OTHER) {
@ -445,18 +448,20 @@ public class AddressXML {
addr = space.getAddress(addr.getOffset()); addr = space.getAddress(addr.getOffset());
} }
} }
SpecXmlUtils.encodeStringAttribute(buf, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, addr.getUnsignedOffset());
} }
/** /**
* Append "space" "offset" and "size" attributes describing the given memory range to the XML stream. * Encode "space" "offset" and "size" attributes for the current element, describing
* This assumes the XML tag name has already been emitted. * the given memory range to the stream.
* @param buf is the XML stream * @param encoder is the stream encoder
* @param addr is the starting Address of the memory range * @param addr is the starting Address of the memory range
* @param size is the size of the memory range * @param size is the size of the memory range
* @throws IOException for errors in the underlying stream
*/ */
public static void appendAttributes(StringBuilder buf, Address addr, int size) { public static void encodeAttributes(Encoder encoder, Address addr, int size)
throws IOException {
AddressSpace space = addr.getAddressSpace(); AddressSpace space = addr.getAddressSpace();
if (space.isOverlaySpace()) { if (space.isOverlaySpace()) {
if (space.getType() != AddressSpace.TYPE_OTHER) { if (space.getType() != AddressSpace.TYPE_OTHER) {
@ -464,19 +469,22 @@ public class AddressXML {
addr = space.getAddress(addr.getOffset()); addr = space.getAddress(addr.getOffset());
} }
} }
SpecXmlUtils.encodeStringAttribute(buf, "space", space.getName());
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "size", size); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, addr.getUnsignedOffset());
encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size);
} }
/** /**
* Append a memory range, as "space", "first", and "last" attributes, to the XML stream. * Encode a memory range, as "space", "first", and "last" attributes, for the current element,
* This assumes the XML tag name has already been emitted. * to the stream.
* @param buffer is the XML stream * @param encoder is the stream encoder
* @param startAddr is the first address in the range * @param startAddr is the first address in the range
* @param endAddr is the last address in the range * @param endAddr is the last address in the range
* @throws IOException for errors in the underlying stream
*/ */
public static void appendAttributes(StringBuilder buffer, Address startAddr, Address endAddr) { public static void encodeAttributes(Encoder encoder, Address startAddr, Address endAddr)
throws IOException {
AddressSpace space = startAddr.getAddressSpace(); AddressSpace space = startAddr.getAddressSpace();
long offset = startAddr.getOffset(); long offset = startAddr.getOffset();
long size = endAddr.getOffset() - offset + 1; long size = endAddr.getOffset() - offset + 1;
@ -492,91 +500,114 @@ public class AddressXML {
long last = offset + size - 1; long last = offset + size - 1;
boolean useFirst = (offset != 0); boolean useFirst = (offset != 0);
boolean useLast = (last != -1); boolean useLast = (last != -1);
SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
if (useFirst) { if (useFirst) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first", offset); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, offset);
} }
if (useLast) { if (useLast) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", last); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last);
} }
} }
/** /**
* Write out the given Address as an \<addr> tag to the XML stream * Encode the given Address as an \<addr> element to the stream
* *
* @param buf is the XML stream * @param encoder is the stream encoder
* @param addr -- Address to convert to XML * @param addr -- Address to encode
* @throws IOException for errors in the underlying stream
*/ */
public static void buildXML(StringBuilder buf, Address addr) { public static void encode(Encoder encoder, Address addr) throws IOException {
encoder.openElement(ElementId.ELEM_ADDR);
if ((addr == null) || (addr == Address.NO_ADDRESS)) { if ((addr == null) || (addr == Address.NO_ADDRESS)) {
buf.append("<addr/>"); encoder.closeElement(ElementId.ELEM_ADDR);
return; return;
} }
buf.append("<addr"); encodeAttributes(encoder, addr);
AddressXML.appendAttributes(buf, addr); encoder.closeElement(ElementId.ELEM_ADDR);
buf.append("/>");
} }
/** /**
* Write out the given Address and a size as an \<addr> tag to the XML stream * Encode the given Address and a size as an \<addr> element to the stream
* *
* @param buf is the XML stream * @param encoder is the stream encoder
* @param addr is the given Address * @param addr is the given Address
* @param size is the given size * @param size is the given size
* @throws IOException for errors in the underlying stream
*/ */
public static void buildXML(StringBuilder buf, Address addr, int size) { public static void encode(Encoder encoder, Address addr, int size) throws IOException {
buf.append("<addr"); encoder.openElement(ElementId.ELEM_ADDR);
AddressXML.appendAttributes(buf, addr, size); encodeAttributes(encoder, addr, size);
buf.append("/>"); encoder.closeElement(ElementId.ELEM_ADDR);
} }
private static void buildVarnodePiece(StringBuilder buf, Address addr, int size) { private static String encodeVarnodePiece(Varnode vn) {
StringBuilder buffer = new StringBuilder();
Address addr = vn.getAddress();
AddressSpace space = addr.getAddressSpace(); AddressSpace space = addr.getAddressSpace();
if (space.isOverlaySpace()) { if (space.isOverlaySpace()) {
space = space.getPhysicalSpace(); space = space.getPhysicalSpace();
addr = space.getAddress(addr.getOffset()); addr = space.getAddress(addr.getOffset());
} }
buf.append(space.getName()); buffer.append(space.getName());
buf.append(":0x"); buffer.append(":0x");
long off = addr.getUnsignedOffset(); long off = addr.getUnsignedOffset();
buf.append(Long.toHexString(off)); buffer.append(Long.toHexString(off));
buf.append(':'); buffer.append(':');
buf.append(Integer.toString(size)); buffer.append(Integer.toString(vn.getSize()));
return buffer.toString();
} }
/** /**
* Write out a sequence of Varnodes as a single \<addr> tag to an XML stream. * Encode a sequence of Varnodes as a single \<addr> element to the stream.
* If there is more than one Varnode, or if the logical size is non-zero, * If there is more than one Varnode, or if the logical size is non-zero,
* the \<addr> tag will specify the address space as "join" and will have * the \<addr> element will specify the address space as "join" and will have
* additional "piece" attributes. * additional "piece" attributes.
* *
* @param buf is the XML stream * @param encoder is the stream encoder
* @param varnodes is the sequence of storage varnodes * @param varnodes is the sequence of storage varnodes
* @param logicalsize is the logical size value of the varnode * @param logicalsize is the logical size value of the varnode
* @throws IOException for errors in the underlying stream
*/ */
public static void buildXML(StringBuilder buf, Varnode[] varnodes, long logicalsize) { public static void encode(Encoder encoder, Varnode[] varnodes, long logicalsize)
throws IOException {
if (varnodes == null) { if (varnodes == null) {
buf.append("<addr/>"); encoder.openElement(ElementId.ELEM_ADDR);
encoder.closeElement(ElementId.ELEM_ADDR);
return; return;
} }
if ((varnodes.length == 1) && (logicalsize == 0)) { if ((varnodes.length == 1) && (logicalsize == 0)) {
AddressXML.buildXML(buf, varnodes[0].getAddress(), varnodes[0].getSize()); AddressXML.encode(encoder, varnodes[0].getAddress(), varnodes[0].getSize());
return; return;
} }
buf.append("<addr space=\"join\""); encoder.openElement(ElementId.ELEM_ADDR);
int piece = 0; encoder.writeSpace(AttributeId.ATTRIB_SPACE, AddressSpace.VARIABLE_SPACE);
for (Varnode vn : varnodes) { encoder.writeString(AttributeId.ATTRIB_PIECE1, encodeVarnodePiece(varnodes[0]));
buf.append(" piece"); encoder.writeString(AttributeId.ATTRIB_PIECE2, encodeVarnodePiece(varnodes[1]));
buf.append(Integer.toString(++piece)); if (varnodes.length > 2) {
buf.append("=\""); encoder.writeString(AttributeId.ATTRIB_PIECE3, encodeVarnodePiece(varnodes[2]));
buildVarnodePiece(buf, vn.getAddress(), vn.getSize()); }
buf.append("\""); if (varnodes.length > 3) {
encoder.writeString(AttributeId.ATTRIB_PIECE4, encodeVarnodePiece(varnodes[3]));
}
if (varnodes.length > 4) {
encoder.writeString(AttributeId.ATTRIB_PIECE5, encodeVarnodePiece(varnodes[4]));
}
if (varnodes.length > 5) {
encoder.writeString(AttributeId.ATTRIB_PIECE6, encodeVarnodePiece(varnodes[5]));
}
if (varnodes.length > 6) {
encoder.writeString(AttributeId.ATTRIB_PIECE7, encodeVarnodePiece(varnodes[6]));
}
if (varnodes.length > 7) {
encoder.writeString(AttributeId.ATTRIB_PIECE8, encodeVarnodePiece(varnodes[7]));
}
if (varnodes.length > 8) {
encoder.writeString(AttributeId.ATTRIB_PIECE9, encodeVarnodePiece(varnodes[8]));
} }
if (logicalsize != 0) { if (logicalsize != 0) {
buf.append(" logicalsize=\"").append(logicalsize).append('\"'); encoder.writeSignedInteger(AttributeId.ATTRIB_LOGICALSIZE, logicalsize);
} }
buf.append("/>"); encoder.closeElement(ElementId.ELEM_ADDR);
} }
} }

View file

@ -32,14 +32,16 @@ import java.util.HashMap;
* The same AttributeId can be used to label a different type of data when associated with a different ElementId. * The same AttributeId can be used to label a different type of data when associated with a different ElementId.
*/ */
public class AttributeId { public class AttributeId {
private static HashMap<String, Integer> lookupAttributeId = new HashMap<>(); private static HashMap<String, AttributeId> lookupAttributeId = new HashMap<>();
private final String name; // The name of the attribute private final String name; // The name of the attribute
private final int id; // The (internal) id of the attribute private final int id; // The (internal) id of the attribute
public AttributeId(String nm, int i) { public AttributeId(String nm, int i) {
name = nm; name = nm;
id = i; id = i;
lookupAttributeId.put(nm, i); if (null != lookupAttributeId.put(nm, this)) {
throw new RuntimeException("Duplicate AttributeId: " + nm);
}
} }
public final String getName() { public final String getName() {
@ -56,11 +58,8 @@ public class AttributeId {
* @return the associated id * @return the associated id
*/ */
public static int find(String nm) { public static int find(String nm) {
Integer res = lookupAttributeId.get(nm); AttributeId res = lookupAttributeId.getOrDefault(nm, ATTRIB_UNKNOWN);
if (res != null) { return res.id;
return res.intValue();
}
return ATTRIB_UNKNOWN.id;
} }
// Common attributes. Attributes with multiple uses // Common attributes. Attributes with multiple uses
@ -96,147 +95,162 @@ public class AttributeId {
public static final AttributeId ATTRIB_LAST = new AttributeId("last", 28); public static final AttributeId ATTRIB_LAST = new AttributeId("last", 28);
public static final AttributeId ATTRIB_UNIQ = new AttributeId("uniq", 29); public static final AttributeId ATTRIB_UNIQ = new AttributeId("uniq", 29);
// architecture // varnode
public static final AttributeId ATTRIB_ADJUSTVMA = new AttributeId("adjustvma", 30); public static final AttributeId ATTRIB_ADDRTIED = new AttributeId("addrtied", 30);
public static final AttributeId ATTRIB_ENABLE = new AttributeId("enable", 31); public static final AttributeId ATTRIB_GRP = new AttributeId("grp", 31);
public static final AttributeId ATTRIB_GROUP = new AttributeId("group", 32); public static final AttributeId ATTRIB_INPUT = new AttributeId("input", 32);
public static final AttributeId ATTRIB_GROWTH = new AttributeId("growth", 33); public static final AttributeId ATTRIB_PERSISTS = new AttributeId("persists", 33);
public static final AttributeId ATTRIB_LOADERSYMBOLS = new AttributeId("loadersymbols", 34); public static final AttributeId ATTRIB_UNAFF = new AttributeId("unaff", 34);
public static final AttributeId ATTRIB_PARENT = new AttributeId("parent", 35);
public static final AttributeId ATTRIB_REGISTER = new AttributeId("register", 36);
public static final AttributeId ATTRIB_REVERSEJUSTIFY = new AttributeId("reversejustify", 37);
public static final AttributeId ATTRIB_SIGNEXT = new AttributeId("signext", 38);
public static final AttributeId ATTRIB_STYLE = new AttributeId("style", 39);
// block // prettyprint
public static final AttributeId ATTRIB_ALTINDEX = new AttributeId("altindex", 40); public static final AttributeId ATTRIB_BLOCKREF = new AttributeId("blockref", 35);
public static final AttributeId ATTRIB_DEPTH = new AttributeId("depth", 41); public static final AttributeId ATTRIB_CLOSE = new AttributeId("close", 36);
public static final AttributeId ATTRIB_END = new AttributeId("end", 42); public static final AttributeId ATTRIB_COLOR = new AttributeId("color", 37);
public static final AttributeId ATTRIB_OPCODE = new AttributeId("opcode", 43); public static final AttributeId ATTRIB_INDENT = new AttributeId("indent", 38);
public static final AttributeId ATTRIB_REV = new AttributeId("rev", 44); public static final AttributeId ATTRIB_OFF = new AttributeId("off", 39);
public static final AttributeId ATTRIB_OPEN = new AttributeId("open", 40);
public static final AttributeId ATTRIB_OPREF = new AttributeId("opref", 41);
public static final AttributeId ATTRIB_VARREF = new AttributeId("varref", 42);
// cpool // translate
public static final AttributeId ATTRIB_A = new AttributeId("a", 45); public static final AttributeId ATTRIB_CODE = new AttributeId("code", 43);
public static final AttributeId ATTRIB_B = new AttributeId("b", 46); public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 44);
public static final AttributeId ATTRIB_LENGTH = new AttributeId("length", 47); public static final AttributeId ATTRIB_DEFAULTSPACE = new AttributeId("defaultspace", 45);
public static final AttributeId ATTRIB_TAG = new AttributeId("tag", 48); public static final AttributeId ATTRIB_UNIQBASE = new AttributeId("uniqbase", 46);
// type
public static final AttributeId ATTRIB_ALIGNMENT = new AttributeId("alignment", 47);
public static final AttributeId ATTRIB_ARRAYSIZE = new AttributeId("arraysize", 48);
public static final AttributeId ATTRIB_CHAR = new AttributeId("char", 49);
public static final AttributeId ATTRIB_CORE = new AttributeId("core", 50);
public static final AttributeId ATTRIB_ENUM = new AttributeId("enum", 51);
public static final AttributeId ATTRIB_ENUMSIGNED = new AttributeId("enumsigned", 52);
public static final AttributeId ATTRIB_ENUMSIZE = new AttributeId("enumsize", 53);
public static final AttributeId ATTRIB_INTSIZE = new AttributeId("intsize", 54);
public static final AttributeId ATTRIB_LONGSIZE = new AttributeId("longsize", 55);
public static final AttributeId ATTRIB_OPAQUESTRING = new AttributeId("opaquestring", 56);
public static final AttributeId ATTRIB_SIGNED = new AttributeId("signed", 57);
public static final AttributeId ATTRIB_STRUCTALIGN = new AttributeId("structalign", 58);
public static final AttributeId ATTRIB_UTF = new AttributeId("utf", 59);
public static final AttributeId ATTRIB_VARLENGTH = new AttributeId("varlength", 60);
// database // database
public static final AttributeId ATTRIB_CAT = new AttributeId("cat", 49); public static final AttributeId ATTRIB_CAT = new AttributeId("cat", 61);
public static final AttributeId ATTRIB_FIELD = new AttributeId("field", 50); public static final AttributeId ATTRIB_FIELD = new AttributeId("field", 62);
public static final AttributeId ATTRIB_MERGE = new AttributeId("merge", 51); public static final AttributeId ATTRIB_MERGE = new AttributeId("merge", 63);
public static final AttributeId ATTRIB_SCOPEIDBYNAME = new AttributeId("scopeidbyname", 52); public static final AttributeId ATTRIB_SCOPEIDBYNAME = new AttributeId("scopeidbyname", 64);
public static final AttributeId ATTRIB_VOLATILE = new AttributeId("volatile", 53); public static final AttributeId ATTRIB_VOLATILE = new AttributeId("volatile", 65);
// fspec // variable
public static final AttributeId ATTRIB_CUSTOM = new AttributeId("custom", 54); public static final AttributeId ATTRIB_CLASS = new AttributeId("class", 66);
public static final AttributeId ATTRIB_DOTDOTDOT = new AttributeId("dotdotdot", 55); public static final AttributeId ATTRIB_REPREF = new AttributeId("repref", 67);
public static final AttributeId ATTRIB_EXTENSION = new AttributeId("extension", 56); public static final AttributeId ATTRIB_SYMREF = new AttributeId("symref", 68);
public static final AttributeId ATTRIB_HASTHIS = new AttributeId("hasthis", 57);
public static final AttributeId ATTRIB_INLINE = new AttributeId("inline", 58);
public static final AttributeId ATTRIB_KILLEDBYCALL = new AttributeId("killedbycall", 59);
public static final AttributeId ATTRIB_MAXSIZE = new AttributeId("maxsize", 60);
public static final AttributeId ATTRIB_MINSIZE = new AttributeId("minsize", 61);
public static final AttributeId ATTRIB_MODELLOCK = new AttributeId("modellock", 62);
public static final AttributeId ATTRIB_NORETURN = new AttributeId("noreturn", 63);
public static final AttributeId ATTRIB_POINTERMAX = new AttributeId("pointermax", 64);
public static final AttributeId ATTRIB_SEPARATEFLOAT = new AttributeId("separatefloat", 65);
public static final AttributeId ATTRIB_STACKSHIFT = new AttributeId("stackshift", 66);
public static final AttributeId ATTRIB_STRATEGY = new AttributeId("strategy", 67);
public static final AttributeId ATTRIB_THISBEFORERETPOINTER =
new AttributeId("thisbeforeretpointer", 68);
public static final AttributeId ATTRIB_VOIDLOCK = new AttributeId("voidlock", 69);
// funcdata
public static final AttributeId ATTRIB_NOCODE = new AttributeId("nocode", 70);
// jumptable
public static final AttributeId ATTRIB_LABEL = new AttributeId("label", 71);
public static final AttributeId ATTRIB_NUM = new AttributeId("num", 72);
// pcodeinject
public static final AttributeId ATTRIB_DYNAMIC = new AttributeId("dynamic", 74);
public static final AttributeId ATTRIB_INCIDENTALCOPY = new AttributeId("incidentalcopy", 75);
public static final AttributeId ATTRIB_INJECT = new AttributeId("inject", 76);
public static final AttributeId ATTRIB_PARAMSHIFT = new AttributeId("paramshift", 77);
public static final AttributeId ATTRIB_TARGETOP = new AttributeId("targetop", 78);
// space
public static final AttributeId ATTRIB_BASE = new AttributeId("base", 88);
public static final AttributeId ATTRIB_DEADCODEDELAY = new AttributeId("deadcodedelay", 89);
public static final AttributeId ATTRIB_DELAY = new AttributeId("delay", 90);
public static final AttributeId ATTRIB_LOGICALSIZE = new AttributeId("logicalsize", 91);
public static final AttributeId ATTRIB_PHYSICAL = new AttributeId("physical", 92);
public static final AttributeId ATTRIB_PIECE1 = new AttributeId("piece1", 93);
public static final AttributeId ATTRIB_PIECE2 = new AttributeId("piece2", 94);
public static final AttributeId ATTRIB_PIECE3 = new AttributeId("piece3", 95);
public static final AttributeId ATTRIB_PIECE4 = new AttributeId("piece4", 96);
public static final AttributeId ATTRIB_PIECE5 = new AttributeId("piece5", 97);
public static final AttributeId ATTRIB_PIECE6 = new AttributeId("piece6", 98);
public static final AttributeId ATTRIB_PIECE7 = new AttributeId("piece7", 99);
public static final AttributeId ATTRIB_PIECE8 = new AttributeId("piece8", 100);
public static final AttributeId ATTRIB_PIECE9 = new AttributeId("piece9", 101);
// stringmanage // stringmanage
public static final AttributeId ATTRIB_TRUNC = new AttributeId("trunc", 102); public static final AttributeId ATTRIB_TRUNC = new AttributeId("trunc", 69);
// pcodeinject
public static final AttributeId ATTRIB_DYNAMIC = new AttributeId("dynamic", 70);
public static final AttributeId ATTRIB_INCIDENTALCOPY = new AttributeId("incidentalcopy", 71);
public static final AttributeId ATTRIB_INJECT = new AttributeId("inject", 72);
public static final AttributeId ATTRIB_PARAMSHIFT = new AttributeId("paramshift", 73);
public static final AttributeId ATTRIB_TARGETOP = new AttributeId("targetop", 74);
// block
public static final AttributeId ATTRIB_ALTINDEX = new AttributeId("altindex", 75);
public static final AttributeId ATTRIB_DEPTH = new AttributeId("depth", 76);
public static final AttributeId ATTRIB_END = new AttributeId("end", 77);
public static final AttributeId ATTRIB_OPCODE = new AttributeId("opcode", 78);
public static final AttributeId ATTRIB_REV = new AttributeId("rev", 79);
// cpool
public static final AttributeId ATTRIB_A = new AttributeId("a", 80);
public static final AttributeId ATTRIB_B = new AttributeId("b", 81);
public static final AttributeId ATTRIB_LENGTH = new AttributeId("length", 82);
public static final AttributeId ATTRIB_TAG = new AttributeId("tag", 83);
// funcdata
public static final AttributeId ATTRIB_NOCODE = new AttributeId("nocode", 84);
// userop
public static final AttributeId ATTRIB_FARPOINTER = new AttributeId("farpointer", 85);
public static final AttributeId ATTRIB_INPUTOP = new AttributeId("inputop", 86);
public static final AttributeId ATTRIB_OUTPUTOP = new AttributeId("outputop", 87);
public static final AttributeId ATTRIB_USEROP = new AttributeId("userop", 88);
// space
public static final AttributeId ATTRIB_BASE = new AttributeId("base", 89);
public static final AttributeId ATTRIB_DEADCODEDELAY = new AttributeId("deadcodedelay", 90);
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);
// architecture
public static final AttributeId ATTRIB_ADJUSTVMA = new AttributeId("adjustvma", 103);
public static final AttributeId ATTRIB_ENABLE = new AttributeId("enable", 104);
public static final AttributeId ATTRIB_GROUP = new AttributeId("group", 105);
public static final AttributeId ATTRIB_GROWTH = new AttributeId("growth", 106);
public static final AttributeId ATTRIB_KEY = new AttributeId("key", 107);
public static final AttributeId ATTRIB_LOADERSYMBOLS = new AttributeId("loadersymbols", 108);
public static final AttributeId ATTRIB_PARENT = new AttributeId("parent", 109);
public static final AttributeId ATTRIB_REGISTER = new AttributeId("register", 110);
public static final AttributeId ATTRIB_REVERSEJUSTIFY = new AttributeId("reversejustify", 111);
public static final AttributeId ATTRIB_SIGNEXT = new AttributeId("signext", 112);
public static final AttributeId ATTRIB_STYLE = new AttributeId("style", 113);
// fspec
public static final AttributeId ATTRIB_CUSTOM = new AttributeId("custom", 114);
public static final AttributeId ATTRIB_DOTDOTDOT = new AttributeId("dotdotdot", 115);
public static final AttributeId ATTRIB_EXTENSION = new AttributeId("extension", 116);
public static final AttributeId ATTRIB_HASTHIS = new AttributeId("hasthis", 117);
public static final AttributeId ATTRIB_INLINE = new AttributeId("inline", 118);
public static final AttributeId ATTRIB_KILLEDBYCALL = new AttributeId("killedbycall", 119);
public static final AttributeId ATTRIB_MAXSIZE = new AttributeId("maxsize", 120);
public static final AttributeId ATTRIB_MINSIZE = new AttributeId("minsize", 121);
public static final AttributeId ATTRIB_MODELLOCK = new AttributeId("modellock", 122);
public static final AttributeId ATTRIB_NORETURN = new AttributeId("noreturn", 123);
public static final AttributeId ATTRIB_POINTERMAX = new AttributeId("pointermax", 124);
public static final AttributeId ATTRIB_SEPARATEFLOAT = new AttributeId("separatefloat", 125);
public static final AttributeId ATTRIB_STACKSHIFT = new AttributeId("stackshift", 126);
public static final AttributeId ATTRIB_STRATEGY = new AttributeId("strategy", 127);
public static final AttributeId ATTRIB_THISBEFORERETPOINTER =
new AttributeId("thisbeforeretpointer", 128);
public static final AttributeId ATTRIB_VOIDLOCK = new AttributeId("voidlock", 129);
// transform // transform
public static final AttributeId ATTRIB_VECTOR_LANE_SIZES = public static final AttributeId ATTRIB_VECTOR_LANE_SIZES =
new AttributeId("vector_lane_sizes", 103); new AttributeId("vector_lane_sizes", 130);
// translate // jumptable
public static final AttributeId ATTRIB_CODE = new AttributeId("code", 104); public static final AttributeId ATTRIB_LABEL = new AttributeId("label", 131);
public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 105); public static final AttributeId ATTRIB_NUM = new AttributeId("num", 132);
public static final AttributeId ATTRIB_DEFAULTSPACE = new AttributeId("defaultspace", 106);
public static final AttributeId ATTRIB_UNIQBASE = new AttributeId("uniqbase", 107);
// type
public static final AttributeId ATTRIB_ALIGNMENT = new AttributeId("alignment", 108);
public static final AttributeId ATTRIB_ARRAYSIZE = new AttributeId("arraysize", 109);
public static final AttributeId ATTRIB_CHAR = new AttributeId("char", 110);
public static final AttributeId ATTRIB_CORE = new AttributeId("core", 111);
public static final AttributeId ATTRIB_ENUM = new AttributeId("enum", 112);
public static final AttributeId ATTRIB_ENUMSIGNED = new AttributeId("enumsigned", 113);
public static final AttributeId ATTRIB_ENUMSIZE = new AttributeId("enumsize", 114);
public static final AttributeId ATTRIB_INTSIZE = new AttributeId("intsize", 115);
public static final AttributeId ATTRIB_LONGSIZE = new AttributeId("longsize", 116);
public static final AttributeId ATTRIB_OPAQUESTRING = new AttributeId("opaquestring", 117);
public static final AttributeId ATTRIB_SIGNED = new AttributeId("signed", 118);
public static final AttributeId ATTRIB_STRUCTALIGN = new AttributeId("structalign", 119);
public static final AttributeId ATTRIB_UTF = new AttributeId("utf", 120);
public static final AttributeId ATTRIB_VARLENGTH = new AttributeId("varlength", 121);
// userop
public static final AttributeId ATTRIB_FARPOINTER = new AttributeId("farpointer", 122);
public static final AttributeId ATTRIB_INPUTOP = new AttributeId("inputop", 123);
public static final AttributeId ATTRIB_OUTPUTOP = new AttributeId("outputop", 124);
public static final AttributeId ATTRIB_USEROP = new AttributeId("userop", 125);
// variable
public static final AttributeId ATTRIB_CLASS = new AttributeId("class", 126);
public static final AttributeId ATTRIB_REPREF = new AttributeId("repref", 127);
public static final AttributeId ATTRIB_SYMREF = new AttributeId("symref", 128);
// varmap // varmap
public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 129); public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 133);
public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 130); public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 134);
// varnode // loadimage_xml
public static final AttributeId ATTRIB_ADDRTIED = new AttributeId("addrtied", 131); // public static final AttributeId ATTRIB_ARCH = new AttributeId("arch", 135);
public static final AttributeId ATTRIB_GRP = new AttributeId("grp", 132);
public static final AttributeId ATTRIB_INPUT = new AttributeId("input", 133);
public static final AttributeId ATTRIB_PERSISTS = new AttributeId("persists", 134);
public static final AttributeId ATTRIB_UNAFF = new AttributeId("unaff", 135);
// prettyprint // sleigh_arch
public static final AttributeId ATTRIB_BLOCKREF = new AttributeId("blockref", 136); // public static final AttributeId ATTRIB_DEPRECATED = new AttributeId("deprecated", 136);
public static final AttributeId ATTRIB_CLOSE = new AttributeId("close", 137); // public static final AttributeId ATTRIB_ENDIAN = new AttributeId("endian", 137);
public static final AttributeId ATTRIB_COLOR = new AttributeId("color", 138); // public static final AttributeId ATTRIB_PROCESSOR = new AttributeId("processor", 138);
public static final AttributeId ATTRIB_INDENT = new AttributeId("indent", 139); // public static final AttributeId ATTRIB_PROCESSORSPEC = new AttributeId("processorspec", 139);
public static final AttributeId ATTRIB_OFF = new AttributeId("off", 140); // public static final AttributeId ATTRIB_SLAFILE = new AttributeId("slafile", 140);
public static final AttributeId ATTRIB_OPEN = new AttributeId("open", 141); // public static final AttributeId ATTRIB_SPEC = new AttributeId("spec", 141);
public static final AttributeId ATTRIB_OPREF = new AttributeId("opref", 142); // public static final AttributeId ATTRIB_TARGET = new AttributeId("target", 142);
public static final AttributeId ATTRIB_VARREF = new AttributeId("varref", 143); // public static final AttributeId ATTRIB_VARIANT = new AttributeId("variant", 143);
// public static final AttributeId ATTRIB_VERSION = new AttributeId("version", 144);
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 147); public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 148);
} }

View file

@ -15,8 +15,9 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* Block representing and '&amp;&amp;' or '||' control flow path within a conditional expression * Block representing and '&amp;&amp;' or '||' control flow path within a conditional expression
@ -41,14 +42,14 @@ public class BlockCondition extends BlockGraph {
} }
@Override @Override
public void saveXmlHeader(StringBuilder buffer) { protected void encodeHeader(Encoder encoder) throws IOException {
super.saveXmlHeader(buffer); super.encodeHeader(encoder);
String opcodename = PcodeOp.getMnemonic(opcode); String opcodename = PcodeOp.getMnemonic(opcode);
SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename); encoder.writeString(AttributeId.ATTRIB_OPCODE, opcodename);
} }
@Override @Override
public void decodeHeader(Decoder decoder) throws PcodeXMLException { protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.decodeHeader(decoder); super.decodeHeader(decoder);
String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE); String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE);
try { try {

View file

@ -15,8 +15,9 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* Placeholder for a basic block (BlockBasic) within a structured * Placeholder for a basic block (BlockBasic) within a structured
@ -78,13 +79,13 @@ public class BlockCopy extends PcodeBlock {
} }
@Override @Override
public void saveXmlHeader(StringBuilder buf) { protected void encodeHeader(Encoder encoder) throws IOException {
super.saveXmlHeader(buf); super.encodeHeader(encoder);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "altindex", altindex); encoder.writeSignedInteger(AttributeId.ATTRIB_ALTINDEX, altindex);
} }
@Override @Override
public void decodeHeader(Decoder decoder) throws PcodeXMLException { protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.decodeHeader(decoder); super.decodeHeader(decoder);
altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX); altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX);
} }

View file

@ -16,9 +16,6 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A "plain" goto block * A "plain" goto block
@ -51,21 +48,19 @@ public class BlockGoto extends BlockGraph {
} }
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
super.saveXmlBody(writer); super.encodeBody(encoder);
StringBuilder buf = new StringBuilder(); encoder.openElement(ElementId.ELEM_TARGET);
buf.append("<target");
PcodeBlock leaf = gototarget.getFrontLeaf(); PcodeBlock leaf = gototarget.getFrontLeaf();
int depth = gototarget.calcDepth(leaf); int depth = gototarget.calcDepth(leaf);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", leaf.getIndex()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex());
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "depth", depth); encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "type", gototype); encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, gototype);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_TARGET);
writer.write(buf.toString());
} }
@Override @Override
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver); super.decodeBody(decoder, resolver);
int el = decoder.openElement(ElementId.ELEM_TARGET); int el = decoder.openElement(ElementId.ELEM_TARGET);
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX); int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);

View file

@ -16,11 +16,8 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A block (with in edges and out edges) that contains other blocks * A block (with in edges and out edges) that contains other blocks
* *
@ -141,24 +138,22 @@ public class BlockGraph extends PcodeBlock {
} }
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
super.saveXmlBody(writer); super.encodeBody(encoder);
for (PcodeBlock bl : list) { for (PcodeBlock bl : list) {
StringBuilder buf = new StringBuilder(); encoder.openElement(ElementId.ELEM_BHEAD);
buf.append("<bhead"); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, bl.getIndex());
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", bl.getIndex());
String name = PcodeBlock.typeToName(bl.blocktype); String name = PcodeBlock.typeToName(bl.blocktype);
SpecXmlUtils.encodeStringAttribute(buf, "type", name); encoder.writeString(AttributeId.ATTRIB_TYPE, name);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_BHEAD);
writer.write(buf.toString());
} }
for (PcodeBlock bl : list) { for (PcodeBlock bl : list) {
bl.saveXml(writer); bl.encode(encoder);
} }
} }
@Override @Override
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
BlockMap newresolver = new BlockMap(resolver); BlockMap newresolver = new BlockMap(resolver);
super.decodeBody(decoder, newresolver); super.decodeBody(decoder, newresolver);
ArrayList<PcodeBlock> tmplist = new ArrayList<>(); ArrayList<PcodeBlock> tmplist = new ArrayList<>();
@ -186,7 +181,7 @@ public class BlockGraph extends PcodeBlock {
* @param decoder is the stream decoder * @param decoder is the stream decoder
* @throws PcodeXMLException if there are invalid encodings * @throws PcodeXMLException if there are invalid encodings
*/ */
public void restoreXml(Decoder decoder) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
BlockMap resolver = new BlockMap(decoder.getAddressFactory()); BlockMap resolver = new BlockMap(decoder.getAddressFactory());
decode(decoder, resolver); decode(decoder, resolver);
resolver.resolveGotoReferences(); resolver.resolveGotoReferences();

View file

@ -16,9 +16,6 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* Block representing an if () goto control flow * Block representing an if () goto control flow
@ -54,21 +51,19 @@ public class BlockIfGoto extends BlockGraph {
} }
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
super.saveXmlBody(writer); super.encodeBody(encoder);
PcodeBlock leaf = gototarget.getFrontLeaf(); PcodeBlock leaf = gototarget.getFrontLeaf();
int depth = gototarget.calcDepth(leaf); int depth = gototarget.calcDepth(leaf);
StringBuilder buf = new StringBuilder(); encoder.openElement(ElementId.ELEM_TARGET);
buf.append("<target"); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex());
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", leaf.getIndex()); encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "depth", depth); encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, gototype);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "type", gototype); encoder.closeElement(ElementId.ELEM_TARGET);
buf.append("/>\n");
writer.write(buf.toString());
} }
@Override @Override
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver); super.decodeBody(decoder, resolver);
int el = decoder.openElement(ElementId.ELEM_TARGET); int el = decoder.openElement(ElementId.ELEM_TARGET);
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX); int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);

View file

@ -16,11 +16,8 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A block representing a 2-or-more control flow branchpoint * A block representing a 2-or-more control flow branchpoint
* *
@ -45,24 +42,21 @@ public class BlockMultiGoto extends BlockGraph {
} }
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
super.saveXmlBody(writer); super.encodeBody(encoder);
for (PcodeBlock gototarget : targets) { for (PcodeBlock gototarget : targets) {
encoder.openElement(ElementId.ELEM_TARGET);
StringBuilder buf = new StringBuilder();
buf.append("<target");
PcodeBlock leaf = gototarget.getFrontLeaf(); PcodeBlock leaf = gototarget.getFrontLeaf();
int depth = gototarget.calcDepth(leaf); int depth = gototarget.calcDepth(leaf);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", leaf.getIndex()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex());
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "depth", depth); encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth);
// SpecXmlUtils.encodeSignedIntegerAttribute(buf, "type", 2); // Always a break // encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, 2); // Always a break
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_TARGET);
writer.write(buf.toString());
} }
} }
@Override @Override
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver); super.decodeBody(decoder, resolver);
for (;;) { for (;;) {
int el = decoder.peekElement(); int el = decoder.peekElement();

View file

@ -33,7 +33,7 @@ import ghidra.program.model.address.AddressSpace;
* one of the read*(void) methods to extract the data. Alternately a read*(AttributeId) call can be used * one of the read*(void) methods to extract the data. Alternately a read*(AttributeId) call can be used
* to extract data for an attribute known to be in the element. There is a special content attribute * to extract data for an attribute known to be in the element. There is a special content attribute
* whose data can be extracted using a read*(AttributeId) call that is passed the special ATTRIB_CONTENT id. * whose data can be extracted using a read*(AttributeId) call that is passed the special ATTRIB_CONTENT id.
* This attribute will not be traversed by getNextAttribute(). * This attribute will not be traversed by getNextAttributeId().
*/ */
public interface Decoder { public interface Decoder {
@ -67,7 +67,7 @@ public interface Decoder {
* Open (traverse into) the next child element of the current parent. * Open (traverse into) the next child element of the current parent.
* The child becomes the current parent. * The child becomes the current parent.
* The list of attributes is initialized for use with getNextAttributeId. * The list of attributes is initialized for use with getNextAttributeId.
* @return the id of the child element * @return the id of the child element or 0 if there are no additional children
*/ */
public int openElement(); public int openElement();

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -68,9 +70,11 @@ public class DynamicEntry extends SymbolEntry {
} }
@Override @Override
public void saveXml(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<hash val=\"0x").append(Long.toHexString(hash)).append("\"/>"); encoder.openElement(ElementId.ELEM_HASH);
buildRangelistXML(buf); encoder.writeUnsignedInteger(AttributeId.ATTRIB_VAL, hash);
encoder.closeElement(ElementId.ELEM_HASH);
encodeRangelist(encoder);
} }
@Override @Override

View file

@ -28,21 +28,23 @@ import java.util.HashMap;
* as an attribute. * as an attribute.
*/ */
public class ElementId { public class ElementId {
private static HashMap<String, Integer> lookupElementId = new HashMap<>(); private static HashMap<String, ElementId> lookupElementId = new HashMap<>();
private String name; // The name of the element private String name; // The name of the element
private int id; // The (internal) id of the element private int id; // The (internal) id of the element
public ElementId(String nm, int i) { public ElementId(String nm, int i) {
name = nm; name = nm;
id = i; id = i;
lookupElementId.put(nm, i); if (null != lookupElementId.put(nm, this)) {
throw new RuntimeException("Duplicate ElementId instance: " + nm);
}
} }
public String getName() { public final String getName() {
return name; return name;
} }
public int getId() { public final int getId() {
return id; return id;
} }
@ -52,11 +54,8 @@ public class ElementId {
* @return the associated id * @return the associated id
*/ */
public static int find(String nm) { public static int find(String nm) {
Integer res = lookupElementId.get(nm); ElementId res = lookupElementId.getOrDefault(nm, ELEM_UNKNOWN);
if (res != null) { return res.id;
return res.intValue();
}
return ELEM_UNKNOWN.id;
} }
public static final ElementId ELEM_DATA = new ElementId("data", 1); public static final ElementId ELEM_DATA = new ElementId("data", 1);
@ -69,267 +68,308 @@ public class ElementId {
public static final ElementId ELEM_VAL = new ElementId("val", 8); public static final ElementId ELEM_VAL = new ElementId("val", 8);
public static final ElementId ELEM_VALUE = new ElementId("value", 9); public static final ElementId ELEM_VALUE = new ElementId("value", 9);
public static final ElementId ELEM_VOID = new ElementId("void", 10); public static final ElementId ELEM_VOID = new ElementId("void", 10);
public static final ElementId ELEM_ADDR = new ElementId("addr", 11);
// address // address
public static final ElementId ELEM_ADDR = new ElementId("addr", 11);
public static final ElementId ELEM_RANGE = new ElementId("range", 12); public static final ElementId ELEM_RANGE = new ElementId("range", 12);
public static final ElementId ELEM_RANGELIST = new ElementId("rangelist", 13); public static final ElementId ELEM_RANGELIST = new ElementId("rangelist", 13);
public static final ElementId ELEM_REGISTER = new ElementId("register", 14); public static final ElementId ELEM_REGISTER = new ElementId("register", 14);
public static final ElementId ELEM_SEQNUM = new ElementId("seqnum", 15); public static final ElementId ELEM_SEQNUM = new ElementId("seqnum", 15);
public static final ElementId ELEM_VARNODE = new ElementId("varnode", 16); public static final ElementId ELEM_VARNODE = new ElementId("varnode", 16);
// architecture // prettyprint
public static final ElementId ELEM_ADDRESS_SHIFT_AMOUNT = public static final ElementId ELEM_BREAK = new ElementId("break", 17);
new ElementId("address_shift_amount", 17); public static final ElementId ELEM_CLANG_DOCUMENT = new ElementId("clang_document", 18);
public static final ElementId ELEM_AGGRESSIVETRIM = new ElementId("aggressivetrim", 18); public static final ElementId ELEM_FUNCNAME = new ElementId("funcname", 19);
public static final ElementId ELEM_COMPILER_SPEC = new ElementId("compiler_spec", 19); public static final ElementId ELEM_FUNCPROTO = new ElementId("funcproto", 20);
public static final ElementId ELEM_DATA_SPACE = new ElementId("data_space", 20); public static final ElementId ELEM_LABEL = new ElementId("label", 21);
public static final ElementId ELEM_DEFAULT_MEMORY_BLOCKS = public static final ElementId ELEM_RETURN_TYPE = new ElementId("return_type", 22);
new ElementId("default_memory_blocks", 21); public static final ElementId ELEM_STATEMENT = new ElementId("statement", 23);
public static final ElementId ELEM_DEFAULT_PROTO = new ElementId("default_proto", 22); public static final ElementId ELEM_SYNTAX = new ElementId("syntax", 24);
public static final ElementId ELEM_DEFAULT_SYMBOLS = new ElementId("default_symbols", 23); public static final ElementId ELEM_VARDECL = new ElementId("vardecl", 25);
public static final ElementId ELEM_EVAL_CALLED_PROTOTYPE = public static final ElementId ELEM_VARIABLE = new ElementId("variable", 26);
new ElementId("eval_called_prototype", 24);
public static final ElementId ELEM_EVAL_CURRENT_PROTOTYPE =
new ElementId("eval_current_prototype", 25);
public static final ElementId ELEM_EXPERIMENTAL_RULES = new ElementId("experimental_rules", 26);
public static final ElementId ELEM_FLOWOVERRIDELIST = new ElementId("flowoverridelist", 27);
public static final ElementId ELEM_FUNCPTR = new ElementId("funcptr", 28);
public static final ElementId ELEM_GLOBAL = new ElementId("global", 29);
public static final ElementId ELEM_INCIDENTALCOPY = new ElementId("incidentalcopy", 30);
public static final ElementId ELEM_INFERPTRBOUNDS = new ElementId("inferptrbounds", 31);
public static final ElementId ELEM_MODELALIAS = new ElementId("modelalias", 32);
public static final ElementId ELEM_NOHIGHPTR = new ElementId("nohighptr", 33);
public static final ElementId ELEM_PROCESSOR_SPEC = new ElementId("processor_spec", 34);
public static final ElementId ELEM_PROGRAMCOUNTER = new ElementId("programcounter", 35);
public static final ElementId ELEM_PROPERTIES = new ElementId("properties", 36);
public static final ElementId ELEM_READONLY = new ElementId("readonly", 37);
public static final ElementId ELEM_REGISTER_DATA = new ElementId("register_data", 38);
public static final ElementId ELEM_RULE = new ElementId("rule", 39);
public static final ElementId ELEM_SAVE_STATE = new ElementId("save_state", 40);
public static final ElementId ELEM_SEGMENTED_ADDRESS = new ElementId("segmented_address", 41);
public static final ElementId ELEM_SPACEBASE = new ElementId("spacebase", 42);
public static final ElementId ELEM_SPECEXTENSIONS = new ElementId("specextensions", 43);
public static final ElementId ELEM_STACKPOINTER = new ElementId("stackpointer", 44);
public static final ElementId ELEM_VOLATILE = new ElementId("volatile", 45);
// block // transform
public static final ElementId ELEM_BHEAD = new ElementId("bhead", 47); public static final ElementId ELEM_OP = new ElementId("op", 27);
public static final ElementId ELEM_BLOCK = new ElementId("block", 48); public static final ElementId ELEM_SLEIGH = new ElementId("sleigh", 28);
public static final ElementId ELEM_BLOCKEDGE = new ElementId("blockedge", 49); public static final ElementId ELEM_SPACE = new ElementId("space", 29);
public static final ElementId ELEM_EDGE = new ElementId("edge", 50); public static final ElementId ELEM_SPACEID = new ElementId("spaceid", 30);
public static final ElementId ELEM_SPACES = new ElementId("spaces", 31);
// callgraph public static final ElementId ELEM_SPACE_BASE = new ElementId("space_base", 32);
public static final ElementId ELEM_CALLGRAPH = new ElementId("callgraph", 51); public static final ElementId ELEM_SPACE_OTHER = new ElementId("space_other", 33);
public static final ElementId ELEM_NODE = new ElementId("node", 52); public static final ElementId ELEM_SPACE_OVERLAY = new ElementId("space_overlay", 34);
public static final ElementId ELEM_SPACE_UNIQUE = new ElementId("space_unique", 35);
// comment public static final ElementId ELEM_TRUNCATE_SPACE = new ElementId("truncate_space", 36);
public static final ElementId ELEM_COMMENT = new ElementId("comment", 53);
public static final ElementId ELEM_COMMENTDB = new ElementId("commentdb", 54);
public static final ElementId ELEM_TEXT = new ElementId("text", 55);
// cpool
public static final ElementId ELEM_CONSTANTPOOL = new ElementId("constantpool", 56);
public static final ElementId ELEM_CPOOLREC = new ElementId("cpoolrec", 57);
public static final ElementId ELEM_REF = new ElementId("ref", 58);
public static final ElementId ELEM_TOKEN = new ElementId("token", 59);
// database
public static final ElementId ELEM_COLLISION = new ElementId("collision", 60);
public static final ElementId ELEM_DB = new ElementId("db", 61);
public static final ElementId ELEM_EQUATESYMBOL = new ElementId("equatesymbol", 62);
public static final ElementId ELEM_EXTERNREFSYMBOL = new ElementId("externrefsymbol", 63);
public static final ElementId ELEM_FACETSYMBOL = new ElementId("facetsymbol", 64);
public static final ElementId ELEM_FUNCTIONSHELL = new ElementId("functionshell", 65);
public static final ElementId ELEM_HASH = new ElementId("hash", 66);
public static final ElementId ELEM_HOLE = new ElementId("hole", 67);
public static final ElementId ELEM_LABELSYM = new ElementId("labelsym", 68);
public static final ElementId ELEM_MAPSYM = new ElementId("mapsym", 69);
public static final ElementId ELEM_PARENT = new ElementId("parent", 70);
public static final ElementId ELEM_PROPERTY_CHANGEPOINT =
new ElementId("property_changepoint", 71);
public static final ElementId ELEM_RANGEEQUALSSYMBOLS = new ElementId("rangeequalssymbols", 72);
public static final ElementId ELEM_SCOPE = new ElementId("scope", 73);
public static final ElementId ELEM_SYMBOLLIST = new ElementId("symbollist", 74);
// fspec
public static final ElementId ELEM_GROUP = new ElementId("group", 75);
public static final ElementId ELEM_INTERNALLIST = new ElementId("internallist", 76);
public static final ElementId ELEM_KILLEDBYCALL = new ElementId("killedbycall", 77);
public static final ElementId ELEM_LIKELYTRASH = new ElementId("likelytrash", 78);
public static final ElementId ELEM_LOCALRANGE = new ElementId("localrange", 79);
public static final ElementId ELEM_MODEL = new ElementId("model", 80);
public static final ElementId ELEM_PARAM = new ElementId("param", 81);
public static final ElementId ELEM_PARAMRANGE = new ElementId("paramrange", 82);
public static final ElementId ELEM_PENTRY = new ElementId("pentry", 83);
public static final ElementId ELEM_PROTOTYPE = new ElementId("prototype", 84);
public static final ElementId ELEM_RESOLVEPROTOTYPE = new ElementId("resolveprototype", 85);
public static final ElementId ELEM_RETPARAM = new ElementId("retparam", 86);
public static final ElementId ELEM_RETURNSYM = new ElementId("returnsym", 87);
public static final ElementId ELEM_UNAFFECTED = new ElementId("unaffected", 88);
// funcdata
public static final ElementId ELEM_AST = new ElementId("ast", 89);
public static final ElementId ELEM_FUNCTION = new ElementId("function", 90);
public static final ElementId ELEM_HIGHLIST = new ElementId("highlist", 91);
public static final ElementId ELEM_JUMPTABLELIST = new ElementId("jumptablelist", 92);
public static final ElementId ELEM_VARNODES = new ElementId("varnodes", 93);
// globalcontext
public static final ElementId ELEM_CONTEXT_DATA = new ElementId("context_data", 94);
public static final ElementId ELEM_CONTEXT_POINTS = new ElementId("context_points", 95);
public static final ElementId ELEM_CONTEXT_POINTSET = new ElementId("context_pointset", 96);
public static final ElementId ELEM_CONTEXT_SET = new ElementId("context_set", 97);
public static final ElementId ELEM_SET = new ElementId("set", 98);
public static final ElementId ELEM_TRACKED_POINTSET = new ElementId("tracked_pointset", 99);
public static final ElementId ELEM_TRACKED_SET = new ElementId("tracked_set", 100);
// jumptable
public static final ElementId ELEM_BASICOVERRIDE = new ElementId("basicoverride", 101);
public static final ElementId ELEM_DEST = new ElementId("dest", 102);
public static final ElementId ELEM_JUMPTABLE = new ElementId("jumptable", 103);
public static final ElementId ELEM_LOADTABLE = new ElementId("loadtable", 104);
public static final ElementId ELEM_NORMADDR = new ElementId("normaddr", 105);
public static final ElementId ELEM_NORMHASH = new ElementId("normhash", 106);
public static final ElementId ELEM_STARTVAL = new ElementId("startval", 107);
// op
public static final ElementId ELEM_IOP = new ElementId("iop", 110);
// options
public static final ElementId ELEM_ALIASBLOCK = new ElementId("aliasblock", 111);
public static final ElementId ELEM_ALLOWCONTEXTSET = new ElementId("allowcontextset", 112);
public static final ElementId ELEM_ANALYZEFORLOOPS = new ElementId("analyzeforloops", 113);
public static final ElementId ELEM_COMMENTHEADER = new ElementId("commentheader", 114);
public static final ElementId ELEM_COMMENTINDENT = new ElementId("commentindent", 115);
public static final ElementId ELEM_COMMENTINSTRUCTION =
new ElementId("commentinstruction", 116);
public static final ElementId ELEM_COMMENTSTYLE = new ElementId("commentstyle", 117);
public static final ElementId ELEM_CONVENTIONPRINTING =
new ElementId("conventionprinting", 118);
public static final ElementId ELEM_CURRENTACTION = new ElementId("currentaction", 119);
public static final ElementId ELEM_DEFAULTPROTOTYPE = new ElementId("defaultprototype", 120);
public static final ElementId ELEM_ERRORREINTERPRETED =
new ElementId("errorreinterpreted", 121);
public static final ElementId ELEM_ERRORTOOMANYINSTRUCTIONS =
new ElementId("errortoomanyinstructions", 122);
public static final ElementId ELEM_ERRORUNIMPLEMENTED =
new ElementId("errorunimplemented", 123);
public static final ElementId ELEM_EXTRAPOP = new ElementId("extrapop", 124);
public static final ElementId ELEM_IGNOREUNIMPLEMENTED =
new ElementId("ignoreunimplemented", 125);
public static final ElementId ELEM_INDENTINCREMENT = new ElementId("indentincrement", 126);
public static final ElementId ELEM_INFERCONSTPTR = new ElementId("inferconstptr", 127);
public static final ElementId ELEM_INLINE = new ElementId("inline", 128);
public static final ElementId ELEM_INPLACEOPS = new ElementId("inplaceops", 129);
public static final ElementId ELEM_INTEGERFORMAT = new ElementId("integerformat", 130);
public static final ElementId ELEM_JUMPLOAD = new ElementId("jumpload", 131);
public static final ElementId ELEM_MAXINSTRUCTION = new ElementId("maxinstruction", 132);
public static final ElementId ELEM_MAXLINEWIDTH = new ElementId("maxlinewidth", 133);
public static final ElementId ELEM_NAMESPACESTRATEGY = new ElementId("namespacestrategy", 134);
public static final ElementId ELEM_NOCASTPRINTING = new ElementId("nocastprinting", 135);
public static final ElementId ELEM_NORETURN = new ElementId("noreturn", 136);
public static final ElementId ELEM_NULLPRINTING = new ElementId("nullprinting", 137);
public static final ElementId ELEM_OPTIONSLIST = new ElementId("optionslist", 138);
public static final ElementId ELEM_PARAM1 = new ElementId("param1", 139);
public static final ElementId ELEM_PARAM2 = new ElementId("param2", 140);
public static final ElementId ELEM_PARAM3 = new ElementId("param3", 141);
public static final ElementId ELEM_PROTOEVAL = new ElementId("protoeval", 142);
public static final ElementId ELEM_SETACTION = new ElementId("setaction", 143);
public static final ElementId ELEM_SETLANGUAGE = new ElementId("setlanguage", 144);
public static final ElementId ELEM_STRUCTALIGN = new ElementId("structalign", 145);
public static final ElementId ELEM_TOGGLERULE = new ElementId("togglerule", 146);
public static final ElementId ELEM_WARNING = new ElementId("warning", 147);
// override
public static final ElementId ELEM_DEADCODEDELAY = new ElementId("deadcodedelay", 148);
public static final ElementId ELEM_FLOW = new ElementId("flow", 149);
public static final ElementId ELEM_FORCEGOTO = new ElementId("forcegoto", 150);
public static final ElementId ELEM_INDIRECTOVERRIDE = new ElementId("indirectoverride", 151);
public static final ElementId ELEM_MULTISTAGEJUMP = new ElementId("multistagejump", 152);
public static final ElementId ELEM_OVERRIDE = new ElementId("override", 153);
public static final ElementId ELEM_PROTOOVERRIDE = new ElementId("protooverride", 154);
// paramid
public static final ElementId ELEM_PARAMMEASURES = new ElementId("parammeasures", 155);
public static final ElementId ELEM_PROTO = new ElementId("proto", 156);
public static final ElementId ELEM_RANK = new ElementId("rank", 157);
// pcodeinject
public static final ElementId ELEM_ADDR_PCODE = new ElementId("addr_pcode", 158);
public static final ElementId ELEM_BODY = new ElementId("body", 159);
public static final ElementId ELEM_CALLFIXUP = new ElementId("callfixup", 160);
public static final ElementId ELEM_CALLOTHERFIXUP = new ElementId("callotherfixup", 161);
public static final ElementId ELEM_CASE_PCODE = new ElementId("case_pcode", 162);
public static final ElementId ELEM_CONTEXT = new ElementId("context", 163);
public static final ElementId ELEM_DEFAULT_PCODE = new ElementId("default_pcode", 164);
public static final ElementId ELEM_INJECT = new ElementId("inject", 165);
public static final ElementId ELEM_INJECTDEBUG = new ElementId("injectdebug", 166);
public static final ElementId ELEM_INST = new ElementId("inst", 167);
public static final ElementId ELEM_PAYLOAD = new ElementId("payload", 168);
public static final ElementId ELEM_PCODE = new ElementId("pcode", 169);
public static final ElementId ELEM_SIZE_PCODE = new ElementId("size_pcode", 170);
// prefersplit
public static final ElementId ELEM_PREFERSPLIT = new ElementId("prefersplit", 171);
// stringmanage
public static final ElementId ELEM_BYTES = new ElementId("bytes", 177);
public static final ElementId ELEM_STRING = new ElementId("string", 178);
public static final ElementId ELEM_STRINGMANAGE = new ElementId("stringmanage", 179);
// translate
public static final ElementId ELEM_OP = new ElementId("op", 180);
public static final ElementId ELEM_SLEIGH = new ElementId("sleigh", 181);
public static final ElementId ELEM_SPACE = new ElementId("space", 182);
public static final ElementId ELEM_SPACEID = new ElementId("spaceid", 183);
public static final ElementId ELEM_SPACES = new ElementId("spaces", 184);
public static final ElementId ELEM_SPACE_BASE = new ElementId("space_base", 185);
public static final ElementId ELEM_SPACE_OTHER = new ElementId("space_other", 186);
public static final ElementId ELEM_SPACE_OVERLAY = new ElementId("space_overlay", 187);
public static final ElementId ELEM_SPACE_UNIQUE = new ElementId("space_unique", 188);
public static final ElementId ELEM_TRUNCATE_SPACE = new ElementId("truncate_space", 189);
// type // type
public static final ElementId ELEM_CORETYPES = new ElementId("coretypes", 190); public static final ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT =
public static final ElementId ELEM_DATA_ORGANIZATION = new ElementId("data_organization", 191); new ElementId("absolute_max_alignment", 37);
public static final ElementId ELEM_DEF = new ElementId("def", 192); public static final ElementId ELEM_BITFIELD_PACKING = new ElementId("bitfield_packing", 38);
public static final ElementId ELEM_ENTRY = new ElementId("entry", 193); public static final ElementId ELEM_CHAR_SIZE = new ElementId("char_size", 39);
public static final ElementId ELEM_ENUM = new ElementId("enum", 194); public static final ElementId ELEM_CHAR_TYPE = new ElementId("char_type", 40);
public static final ElementId ELEM_FIELD = new ElementId("field", 195); public static final ElementId ELEM_CORETYPES = new ElementId("coretypes", 41);
public static final ElementId ELEM_INTEGER_SIZE = new ElementId("integer_size", 196); public static final ElementId ELEM_DATA_ORGANIZATION = new ElementId("data_organization", 42);
public static final ElementId ELEM_LONG_SIZE = new ElementId("long_size", 197); public static final ElementId ELEM_DEF = new ElementId("def", 43);
public static final ElementId ELEM_SIZE_ALIGNMENT_MAP = public static final ElementId ELEM_DEFAULT_ALIGNMENT = new ElementId("default_alignment", 44);
new ElementId("size_alignment_map", 198); public static final ElementId ELEM_DEFAULT_POINTER_ALIGNMENT =
public static final ElementId ELEM_TYPE = new ElementId("type", 199); new ElementId("default_pointer_alignment", 45);
public static final ElementId ELEM_TYPEGRP = new ElementId("typegrp", 200); public static final ElementId ELEM_DOUBLE_SIZE = new ElementId("double_size", 46);
public static final ElementId ELEM_TYPEREF = new ElementId("typeref", 201); public static final ElementId ELEM_ENTRY = new ElementId("entry", 47);
public static final ElementId ELEM_ENUM = new ElementId("enum", 48);
public static final ElementId ELEM_FIELD = new ElementId("field", 49);
public static final ElementId ELEM_FLOAT_SIZE = new ElementId("float_size", 50);
public static final ElementId ELEM_INTEGER_SIZE = new ElementId("integer_size", 51);
public static final ElementId ELEM_LONG_DOUBLE_SIZE = new ElementId("long_double_size", 52);
public static final ElementId ELEM_LONG_LONG_SIZE = new ElementId("long_long_size", 53);
public static final ElementId ELEM_LONG_SIZE = new ElementId("long_size", 54);
public static final ElementId ELEM_MACHINE_ALIGNMENT = new ElementId("machine_alignment", 55);
public static final ElementId ELEM_POINTER_SHIFT = new ElementId("pointer_shift", 56);
public static final ElementId ELEM_POINTER_SIZE = new ElementId("pointer_size", 57);
public static final ElementId ELEM_SHORT_SIZE = new ElementId("short_size", 58);
public static final ElementId ELEM_SIZE_ALIGNMENT_MAP = new ElementId("size_alignment_map", 59);
public static final ElementId ELEM_TYPE = new ElementId("type", 60);
public static final ElementId ELEM_TYPE_ALIGNMENT_ENABLED =
new ElementId("type_alignment_enabled", 61);
public static final ElementId ELEM_TYPEGRP = new ElementId("typegrp", 62);
public static final ElementId ELEM_TYPEREF = new ElementId("typeref", 63);
public static final ElementId ELEM_USE_MS_CONVENTION = new ElementId("use_MS_convention", 64);
public static final ElementId ELEM_WCHAR_SIZE = new ElementId("wchar_size", 65);
public static final ElementId ELEM_ZERO_LENGTH_BOUNDARY =
new ElementId("zero_length_boundary", 66);
// userop // database
public static final ElementId ELEM_CONSTRESOLVE = new ElementId("constresolve", 202); public static final ElementId ELEM_COLLISION = new ElementId("collision", 67);
public static final ElementId ELEM_JUMPASSIST = new ElementId("jumpassist", 203); public static final ElementId ELEM_DB = new ElementId("db", 68);
public static final ElementId ELEM_SEGMENTOP = new ElementId("segmentop", 204); public static final ElementId ELEM_EQUATESYMBOL = new ElementId("equatesymbol", 69);
public static final ElementId ELEM_EXTERNREFSYMBOL = new ElementId("externrefsymbol", 70);
public static final ElementId ELEM_FACETSYMBOL = new ElementId("facetsymbol", 71);
public static final ElementId ELEM_FUNCTIONSHELL = new ElementId("functionshell", 72);
public static final ElementId ELEM_HASH = new ElementId("hash", 73);
public static final ElementId ELEM_HOLE = new ElementId("hole", 74);
public static final ElementId ELEM_LABELSYM = new ElementId("labelsym", 75);
public static final ElementId ELEM_MAPSYM = new ElementId("mapsym", 76);
public static final ElementId ELEM_PARENT = new ElementId("parent", 77);
public static final ElementId ELEM_PROPERTY_CHANGEPOINT =
new ElementId("property_changepoint", 78);
public static final ElementId ELEM_RANGEEQUALSSYMBOLS = new ElementId("rangeequalssymbols", 79);
public static final ElementId ELEM_SCOPE = new ElementId("scope", 80);
public static final ElementId ELEM_SYMBOLLIST = new ElementId("symbollist", 81);
// variable // variable
public static final ElementId ELEM_HIGH = new ElementId("high", 205); public static final ElementId ELEM_HIGH = new ElementId("high", 82);
// stringmanage
public static final ElementId ELEM_BYTES = new ElementId("bytes", 83);
public static final ElementId ELEM_STRING = new ElementId("string", 84);
public static final ElementId ELEM_STRINGMANAGE = new ElementId("stringmanage", 85);
// comment
public static final ElementId ELEM_COMMENT = new ElementId("comment", 86);
public static final ElementId ELEM_COMMENTDB = new ElementId("commentdb", 87);
public static final ElementId ELEM_TEXT = new ElementId("text", 88);
// pcodeinject
public static final ElementId ELEM_ADDR_PCODE = new ElementId("addr_pcode", 89);
public static final ElementId ELEM_BODY = new ElementId("body", 90);
public static final ElementId ELEM_CALLFIXUP = new ElementId("callfixup", 91);
public static final ElementId ELEM_CALLOTHERFIXUP = new ElementId("callotherfixup", 92);
public static final ElementId ELEM_CASE_PCODE = new ElementId("case_pcode", 93);
public static final ElementId ELEM_CONTEXT = new ElementId("context", 94);
public static final ElementId ELEM_DEFAULT_PCODE = new ElementId("default_pcode", 95);
public static final ElementId ELEM_INJECT = new ElementId("inject", 96);
public static final ElementId ELEM_INJECTDEBUG = new ElementId("injectdebug", 97);
public static final ElementId ELEM_INST = new ElementId("inst", 98);
public static final ElementId ELEM_PAYLOAD = new ElementId("payload", 99);
public static final ElementId ELEM_PCODE = new ElementId("pcode", 100);
public static final ElementId ELEM_SIZE_PCODE = new ElementId("size_pcode", 101);
// block
public static final ElementId ELEM_BHEAD = new ElementId("bhead", 102);
public static final ElementId ELEM_BLOCK = new ElementId("block", 103);
public static final ElementId ELEM_BLOCKEDGE = new ElementId("blockedge", 104);
public static final ElementId ELEM_EDGE = new ElementId("edge", 105);
// paramid
public static final ElementId ELEM_PARAMMEASURES = new ElementId("parammeasures", 106);
public static final ElementId ELEM_PROTO = new ElementId("proto", 107);
public static final ElementId ELEM_RANK = new ElementId("rank", 108);
// cpool
public static final ElementId ELEM_CONSTANTPOOL = new ElementId("constantpool", 109);
public static final ElementId ELEM_CPOOLREC = new ElementId("cpoolrec", 110);
public static final ElementId ELEM_REF = new ElementId("ref", 111);
public static final ElementId ELEM_TOKEN = new ElementId("token", 112);
// op
public static final ElementId ELEM_IOP = new ElementId("iop", 113);
public static final ElementId ELEM_UNIMPL = new ElementId("unimpl", 114);
// funcdata
public static final ElementId ELEM_AST = new ElementId("ast", 115);
public static final ElementId ELEM_FUNCTION = new ElementId("function", 116);
public static final ElementId ELEM_HIGHLIST = new ElementId("highlist", 117);
public static final ElementId ELEM_JUMPTABLELIST = new ElementId("jumptablelist", 118);
public static final ElementId ELEM_VARNODES = new ElementId("varnodes", 119);
// globalcontext
public static final ElementId ELEM_CONTEXT_DATA = new ElementId("context_data", 120);
public static final ElementId ELEM_CONTEXT_POINTS = new ElementId("context_points", 121);
public static final ElementId ELEM_CONTEXT_POINTSET = new ElementId("context_pointset", 122);
public static final ElementId ELEM_CONTEXT_SET = new ElementId("context_set", 123);
public static final ElementId ELEM_SET = new ElementId("set", 124);
public static final ElementId ELEM_TRACKED_POINTSET = new ElementId("tracked_pointset", 125);
public static final ElementId ELEM_TRACKED_SET = new ElementId("tracked_set", 126);
// userop
public static final ElementId ELEM_CONSTRESOLVE = new ElementId("constresolve", 127);
public static final ElementId ELEM_JUMPASSIST = new ElementId("jumpassist", 128);
public static final ElementId ELEM_SEGMENTOP = new ElementId("segmentop", 129);
// architecture
public static final ElementId ELEM_ADDRESS_SHIFT_AMOUNT =
new ElementId("address_shift_amount", 130);
public static final ElementId ELEM_AGGRESSIVETRIM = new ElementId("aggressivetrim", 131);
public static final ElementId ELEM_COMPILER_SPEC = new ElementId("compiler_spec", 132);
public static final ElementId ELEM_DATA_SPACE = new ElementId("data_space", 133);
public static final ElementId ELEM_DEFAULT_MEMORY_BLOCKS =
new ElementId("default_memory_blocks", 134);
public static final ElementId ELEM_DEFAULT_PROTO = new ElementId("default_proto", 135);
public static final ElementId ELEM_DEFAULT_SYMBOLS = new ElementId("default_symbols", 136);
public static final ElementId ELEM_EVAL_CALLED_PROTOTYPE =
new ElementId("eval_called_prototype", 137);
public static final ElementId ELEM_EVAL_CURRENT_PROTOTYPE =
new ElementId("eval_current_prototype", 138);
public static final ElementId ELEM_EXPERIMENTAL_RULES =
new ElementId("experimental_rules", 139);
public static final ElementId ELEM_FLOWOVERRIDELIST = new ElementId("flowoverridelist", 140);
public static final ElementId ELEM_FUNCPTR = new ElementId("funcptr", 141);
public static final ElementId ELEM_GLOBAL = new ElementId("global", 142);
public static final ElementId ELEM_INCIDENTALCOPY = new ElementId("incidentalcopy", 143);
public static final ElementId ELEM_INFERPTRBOUNDS = new ElementId("inferptrbounds", 144);
public static final ElementId ELEM_MODELALIAS = new ElementId("modelalias", 145);
public static final ElementId ELEM_NOHIGHPTR = new ElementId("nohighptr", 146);
public static final ElementId ELEM_PROCESSOR_SPEC = new ElementId("processor_spec", 147);
public static final ElementId ELEM_PROGRAMCOUNTER = new ElementId("programcounter", 148);
public static final ElementId ELEM_PROPERTIES = new ElementId("properties", 149);
public static final ElementId ELEM_PROPERTY = new ElementId("property", 150);
public static final ElementId ELEM_READONLY = new ElementId("readonly", 151);
public static final ElementId ELEM_REGISTER_DATA = new ElementId("register_data", 152);
public static final ElementId ELEM_RULE = new ElementId("rule", 153);
public static final ElementId ELEM_SAVE_STATE = new ElementId("save_state", 154);
public static final ElementId ELEM_SEGMENTED_ADDRESS = new ElementId("segmented_address", 155);
public static final ElementId ELEM_SPACEBASE = new ElementId("spacebase", 156);
public static final ElementId ELEM_SPECEXTENSIONS = new ElementId("specextensions", 157);
public static final ElementId ELEM_STACKPOINTER = new ElementId("stackpointer", 158);
public static final ElementId ELEM_VOLATILE = new ElementId("volatile", 159);
// fspec
public static final ElementId ELEM_GROUP = new ElementId("group", 160);
public static final ElementId ELEM_INTERNALLIST = new ElementId("internallist", 161);
public static final ElementId ELEM_KILLEDBYCALL = new ElementId("killedbycall", 162);
public static final ElementId ELEM_LIKELYTRASH = new ElementId("likelytrash", 163);
public static final ElementId ELEM_LOCALRANGE = new ElementId("localrange", 164);
public static final ElementId ELEM_MODEL = new ElementId("model", 165);
public static final ElementId ELEM_PARAM = new ElementId("param", 166);
public static final ElementId ELEM_PARAMRANGE = new ElementId("paramrange", 167);
public static final ElementId ELEM_PENTRY = new ElementId("pentry", 168);
public static final ElementId ELEM_PROTOTYPE = new ElementId("prototype", 169);
public static final ElementId ELEM_RESOLVEPROTOTYPE = new ElementId("resolveprototype", 170);
public static final ElementId ELEM_RETPARAM = new ElementId("retparam", 171);
public static final ElementId ELEM_RETURNSYM = new ElementId("returnsym", 172);
public static final ElementId ELEM_UNAFFECTED = new ElementId("unaffected", 173);
// options
public static final ElementId ELEM_ALIASBLOCK = new ElementId("aliasblock", 174);
public static final ElementId ELEM_ALLOWCONTEXTSET = new ElementId("allowcontextset", 175);
public static final ElementId ELEM_ANALYZEFORLOOPS = new ElementId("analyzeforloops", 176);
public static final ElementId ELEM_COMMENTHEADER = new ElementId("commentheader", 177);
public static final ElementId ELEM_COMMENTINDENT = new ElementId("commentindent", 178);
public static final ElementId ELEM_COMMENTINSTRUCTION =
new ElementId("commentinstruction", 179);
public static final ElementId ELEM_COMMENTSTYLE = new ElementId("commentstyle", 180);
public static final ElementId ELEM_CONVENTIONPRINTING =
new ElementId("conventionprinting", 181);
public static final ElementId ELEM_CURRENTACTION = new ElementId("currentaction", 182);
public static final ElementId ELEM_DEFAULTPROTOTYPE = new ElementId("defaultprototype", 183);
public static final ElementId ELEM_ERRORREINTERPRETED =
new ElementId("errorreinterpreted", 184);
public static final ElementId ELEM_ERRORTOOMANYINSTRUCTIONS =
new ElementId("errortoomanyinstructions", 185);
public static final ElementId ELEM_ERRORUNIMPLEMENTED =
new ElementId("errorunimplemented", 186);
public static final ElementId ELEM_EXTRAPOP = new ElementId("extrapop", 187);
public static final ElementId ELEM_IGNOREUNIMPLEMENTED =
new ElementId("ignoreunimplemented", 188);
public static final ElementId ELEM_INDENTINCREMENT = new ElementId("indentincrement", 189);
public static final ElementId ELEM_INFERCONSTPTR = new ElementId("inferconstptr", 190);
public static final ElementId ELEM_INLINE = new ElementId("inline", 191);
public static final ElementId ELEM_INPLACEOPS = new ElementId("inplaceops", 192);
public static final ElementId ELEM_INTEGERFORMAT = new ElementId("integerformat", 193);
public static final ElementId ELEM_JUMPLOAD = new ElementId("jumpload", 194);
public static final ElementId ELEM_MAXINSTRUCTION = new ElementId("maxinstruction", 195);
public static final ElementId ELEM_MAXLINEWIDTH = new ElementId("maxlinewidth", 196);
public static final ElementId ELEM_NAMESPACESTRATEGY = new ElementId("namespacestrategy", 197);
public static final ElementId ELEM_NOCASTPRINTING = new ElementId("nocastprinting", 198);
public static final ElementId ELEM_NORETURN = new ElementId("noreturn", 199);
public static final ElementId ELEM_NULLPRINTING = new ElementId("nullprinting", 200);
public static final ElementId ELEM_OPTIONSLIST = new ElementId("optionslist", 201);
public static final ElementId ELEM_PARAM1 = new ElementId("param1", 202);
public static final ElementId ELEM_PARAM2 = new ElementId("param2", 203);
public static final ElementId ELEM_PARAM3 = new ElementId("param3", 204);
public static final ElementId ELEM_PROTOEVAL = new ElementId("protoeval", 205);
public static final ElementId ELEM_SETACTION = new ElementId("setaction", 206);
public static final ElementId ELEM_SETLANGUAGE = new ElementId("setlanguage", 207);
public static final ElementId ELEM_STRUCTALIGN = new ElementId("structalign", 208);
public static final ElementId ELEM_TOGGLERULE = new ElementId("togglerule", 209);
public static final ElementId ELEM_WARNING = new ElementId("warning", 210);
// jumptable
public static final ElementId ELEM_BASICOVERRIDE = new ElementId("basicoverride", 211);
public static final ElementId ELEM_DEST = new ElementId("dest", 212);
public static final ElementId ELEM_JUMPTABLE = new ElementId("jumptable", 213);
public static final ElementId ELEM_LOADTABLE = new ElementId("loadtable", 214);
public static final ElementId ELEM_NORMADDR = new ElementId("normaddr", 215);
public static final ElementId ELEM_NORMHASH = new ElementId("normhash", 216);
public static final ElementId ELEM_STARTVAL = new ElementId("startval", 217);
// override
public static final ElementId ELEM_DEADCODEDELAY = new ElementId("deadcodedelay", 218);
public static final ElementId ELEM_FLOW = new ElementId("flow", 219);
public static final ElementId ELEM_FORCEGOTO = new ElementId("forcegoto", 220);
public static final ElementId ELEM_INDIRECTOVERRIDE = new ElementId("indirectoverride", 221);
public static final ElementId ELEM_MULTISTAGEJUMP = new ElementId("multistagejump", 222);
public static final ElementId ELEM_OVERRIDE = new ElementId("override", 223);
public static final ElementId ELEM_PROTOOVERRIDE = new ElementId("protooverride", 224);
// prefersplit
public static final ElementId ELEM_PREFERSPLIT = new ElementId("prefersplit", 225);
// callgraph
public static final ElementId ELEM_CALLGRAPH = new ElementId("callgraph", 226);
public static final ElementId ELEM_NODE = new ElementId("node", 227);
// varmap // varmap
public static final ElementId ELEM_LOCALDB = new ElementId("localdb", 206); public static final ElementId ELEM_LOCALDB = new ElementId("localdb", 228);
// prettyprint
public static final ElementId ELEM_BREAK = new ElementId("break", 208);
public static final ElementId ELEM_CLANG_DOCUMENT = new ElementId("clang_document", 209);
public static final ElementId ELEM_FUNCNAME = new ElementId("funcname", 210);
public static final ElementId ELEM_FUNCPROTO = new ElementId("funcproto", 211);
public static final ElementId ELEM_LABEL = new ElementId("label", 212);
public static final ElementId ELEM_RETURN_TYPE = new ElementId("return_type", 213);
public static final ElementId ELEM_STATEMENT = new ElementId("statement", 214);
public static final ElementId ELEM_SYNTAX = new ElementId("syntax", 215);
public static final ElementId ELEM_VARDECL = new ElementId("vardecl", 216);
public static final ElementId ELEM_VARIABLE = new ElementId("variable", 217);
// ghidra_process // ghidra_process
public static final ElementId ELEM_DOC = new ElementId("doc", 218); public static final ElementId ELEM_DOC = new ElementId("doc", 229);
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 231); // loadimage_xml
// public static final ElementId ELEM_BINARYIMAGE = new ElementId("binaryimage", 230);
// public static final ElementId ELEM_BYTECHUNK = new ElementId("bytechunk", 231);
// sleigh_arch
// public static final ElementId ELEM_COMPILER = new ElementId("compiler", 232);
// public static final ElementId ELEM_DESCRIPTION = new ElementId("description", 233);
// public static final ElementId ELEM_LANGUAGE = new ElementId("language", 234);
// public static final ElementId ELEM_LANGUAGE_DEFINITIONS =
// new ElementId("language_definitions", 235);
// xml_arch
// public static final ElementId ELEM_XML_SAVEFILE = new ElementId("xml_savefile", 236);
// raw_arch
// public static final ElementId ELEM_RAW_SAVEFILE = new ElementId("raw_savefile", 237);
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 251);
} }

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
/** /**
@ -42,53 +44,66 @@ public interface Encoder {
* Begin a new element in the encoding * Begin a new element in the encoding
* The element will have the given ElementId annotation and becomes the \e current element. * The element will have the given ElementId annotation and becomes the \e current element.
* @param elemId is the given ElementId annotation * @param elemId is the given ElementId annotation
* @throws IOException for errors in the underlying stream
*/ */
void openElement(ElementId elemId); void openElement(ElementId elemId) throws IOException;
/** /**
* End the current element in the encoding * End the current element in the encoding
* The current element must match the given annotation or an exception is thrown. * The current element must match the given annotation or an exception is thrown.
* @param elemId is the given (expected) annotation for the current element * @param elemId is the given (expected) annotation for the current element
* @throws IOException for errors in the underlying stream
*/ */
void closeElement(ElementId elemId); void closeElement(ElementId elemId) throws IOException;
/** /**
* Write an annotated boolean value into the encoding * Write an annotated boolean value into the encoding
* The boolean data is associated with the given AttributeId annotation and the current open element. * The boolean data is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation * @param attribId is the given AttributeId annotation
* @param val is boolean value to encode * @param val is boolean value to encode
* @throws IOException for errors in the underlying stream
*/ */
void writeBool(AttributeId attribId, boolean val); void writeBool(AttributeId attribId, boolean val) throws IOException;
/** /**
* Write an annotated signed integer value into the encoding * Write an annotated signed integer value into the encoding
* The integer is associated with the given AttributeId annotation and the current open element. * The integer is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation * @param attribId is the given AttributeId annotation
* @param val is the signed integer value to encode * @param val is the signed integer value to encode
* @throws IOException for errors in the underlying stream
*/ */
void writeSignedInteger(AttributeId attribId, long val); void writeSignedInteger(AttributeId attribId, long val) throws IOException;
/** /**
* Write an annotated unsigned integer value into the encoding * Write an annotated unsigned integer value into the encoding
* The integer is associated with the given AttributeId annotation and the current open element. * The integer is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation * @param attribId is the given AttributeId annotation
* @param val is the unsigned integer value to encode * @param val is the unsigned integer value to encode
* @throws IOException for errors in the underlying stream
*/ */
void writeUnsignedInteger(AttributeId attribId, long val); void writeUnsignedInteger(AttributeId attribId, long val) throws IOException;
/** /**
* Write an annotated string into the encoding * Write an annotated string into the encoding
* The string is associated with the given AttributeId annotation and the current open element. * The string is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation * @param attribId is the given AttributeId annotation
* @param val is the string to encode * @param val is the string to encode
* @throws IOException for errors in the underlying stream
*/ */
void writeString(AttributeId attribId, String val); void writeString(AttributeId attribId, String val) throws IOException;
/** /**
* Write an address space reference into the encoding * Write an address space reference into the encoding
* The address space is associated with the given AttributeId annotation and the current open element. * The address space is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation * @param attribId is the given AttributeId annotation
* @param spc is the address space to encode * @param spc is the address space to encode
* @throws IOException for errors in the underlying stream
*/ */
void writeSpace(AttributeId attribId, AddressSpace spc); void writeSpace(AttributeId attribId, AddressSpace spc) throws IOException;
/**
* Return anything written to the encoder (since the last clear) as a byte array.
* @return the array of bytes
*/
byte[] getBytes();
} }

View file

@ -15,9 +15,10 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
public class EquateSymbol extends HighSymbol { public class EquateSymbol extends HighSymbol {
@ -104,9 +105,9 @@ public class EquateSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<equatesymbol"); encoder.openElement(ElementId.ELEM_EQUATESYMBOL);
saveXMLHeader(buf); encodeHeader(encoder);
if (convert != 0) { if (convert != 0) {
String formString = "hex"; String formString = "hex";
if (convert == FORMAT_HEX) { if (convert == FORMAT_HEX) {
@ -124,13 +125,12 @@ public class EquateSymbol extends HighSymbol {
else if (convert == FORMAT_CHAR) { else if (convert == FORMAT_CHAR) {
formString = "char"; formString = "char";
} }
SpecXmlUtils.encodeStringAttribute(buf, "format", formString); encoder.writeString(AttributeId.ATTRIB_FORMAT, formString);
} }
buf.append(">\n"); encoder.openElement(ElementId.ELEM_VALUE);
buf.append(" <value>0x"); encoder.writeUnsignedInteger(AttributeId.ATTRIB_CONTENT, value);
buf.append(Long.toHexString(value)); encoder.closeElement(ElementId.ELEM_VALUE);
buf.append("</value>\n"); encoder.closeElement(ElementId.ELEM_EQUATESYMBOL);
buf.append("</equatesymbol>\n");
} }
/** /**

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -314,49 +316,48 @@ public class FunctionPrototype {
} }
/** /**
* append an XML string representing this function prototype * Encode this function prototype to a stream.
* @param res is where the string should be appended * @param encoder is the stream encoder
* @param dtmanage is the DataTypeManager for building type reference tags * @param dtmanage is the DataTypeManager for building type reference tags
* @throws IOException for errors in the underlying stream
*/ */
public void buildPrototypeXML(StringBuilder res, PcodeDataTypeManager dtmanage) { public void encodePrototype(Encoder encoder, PcodeDataTypeManager dtmanage) throws IOException {
res.append("<prototype"); encoder.openElement(ElementId.ELEM_PROTOTYPE);
if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) { if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) {
SpecXmlUtils.encodeStringAttribute(res, "extrapop", "unknown"); encoder.writeString(AttributeId.ATTRIB_EXTRAPOP, "unknown");
} }
else { else {
SpecXmlUtils.encodeSignedIntegerAttribute(res, "extrapop", extrapop); encoder.writeSignedInteger(AttributeId.ATTRIB_EXTRAPOP, extrapop);
} }
SpecXmlUtils.encodeStringAttribute(res, "model", modelname); encoder.writeString(AttributeId.ATTRIB_MODEL, modelname);
if (modellock) { if (modellock) {
SpecXmlUtils.encodeBooleanAttribute(res, "modellock", modellock); encoder.writeBool(AttributeId.ATTRIB_MODELLOCK, modellock);
} }
if (dotdotdot) { if (dotdotdot) {
SpecXmlUtils.encodeBooleanAttribute(res, "dotdotdot", dotdotdot); encoder.writeBool(AttributeId.ATTRIB_DOTDOTDOT, dotdotdot);
} }
if (voidinputlock) { if (voidinputlock) {
SpecXmlUtils.encodeBooleanAttribute(res, "voidlock", voidinputlock); encoder.writeBool(AttributeId.ATTRIB_VOIDLOCK, voidinputlock);
} }
if (isinline) { if (isinline) {
SpecXmlUtils.encodeBooleanAttribute(res, "inline", isinline); encoder.writeBool(AttributeId.ATTRIB_INLINE, isinline);
} }
if (noreturn) { if (noreturn) {
SpecXmlUtils.encodeBooleanAttribute(res, "noreturn", noreturn); encoder.writeBool(AttributeId.ATTRIB_NORETURN, noreturn);
} }
if (custom) { if (custom) {
SpecXmlUtils.encodeBooleanAttribute(res, "custom", custom); encoder.writeBool(AttributeId.ATTRIB_CUSTOM, custom);
} }
if (isConstruct) { if (isConstruct) {
SpecXmlUtils.encodeBooleanAttribute(res, "constructor", isConstruct); encoder.writeBool(AttributeId.ATTRIB_CONSTRUCTOR, isConstruct);
} }
if (isDestruct) { if (isDestruct) {
SpecXmlUtils.encodeBooleanAttribute(res, "destructor", isDestruct); encoder.writeBool(AttributeId.ATTRIB_DESTRUCTOR, isDestruct);
} }
res.append(">\n"); encoder.openElement(ElementId.ELEM_RETURNSYM);
res.append(" <returnsym");
if (outputlock) { if (outputlock) {
SpecXmlUtils.encodeBooleanAttribute(res, "typelock", outputlock); encoder.writeBool(AttributeId.ATTRIB_TYPELOCK, outputlock);
} }
res.append(">\n ");
int sz = returntype.getLength(); int sz = returntype.getLength();
if (sz < 0) { if (sz < 0) {
Msg.warn(this, "Bad returntype size"); Msg.warn(this, "Bad returntype size");
@ -368,46 +369,46 @@ public class FunctionPrototype {
if (sz != returnstorage.size()) { // If the sizes do no match if (sz != returnstorage.size()) { // If the sizes do no match
logicalsize = sz; // force the logical size on the varnode logicalsize = sz; // force the logical size on the varnode
} }
AddressXML.buildXML(res, returnstorage.getVarnodes(), logicalsize); AddressXML.encode(encoder, returnstorage.getVarnodes(), logicalsize);
res.append("\n ");
} }
else { else {
// Decompiler will use model for storage // Decompiler will use model for storage. Don't specify where return type is stored
res.append("<addr/>\n "); // Don't specify where return type is stored encoder.openElement(ElementId.ELEM_ADDR);
encoder.closeElement(ElementId.ELEM_ADDR);
} }
dtmanage.buildTypeRef(res, returntype, sz); dtmanage.encodeTypeRef(encoder, returntype, sz);
res.append(" </returnsym>\n"); encoder.closeElement(ElementId.ELEM_RETURNSYM);
if (injectname != null) { if (injectname != null) {
res.append("<inject>"); encoder.openElement(ElementId.ELEM_INJECT);
res.append(injectname); encoder.writeString(AttributeId.ATTRIB_CONTENT, injectname);
res.append("</inject>\n"); encoder.closeElement(ElementId.ELEM_INJECT);
} }
if (params != null) { if (params != null) {
res.append("<internallist>\n"); encoder.openElement(ElementId.ELEM_INTERNALLIST);
for (ParameterDefinition param : params) { for (ParameterDefinition param : params) {
res.append("<param"); encoder.openElement(ElementId.ELEM_PARAM);
String name = param.getName(); String name = param.getName();
DataType dt = param.getDataType(); DataType dt = param.getDataType();
boolean namelock = false; boolean namelock = false;
if ((name != null) && (name.length() > 0)) { if ((name != null) && (name.length() > 0)) {
res.append(" name=\"").append(name).append('\"'); encoder.writeString(AttributeId.ATTRIB_NAME, name);
namelock = true; namelock = true;
} }
res.append(" typelock=\"true\" namelock=\""); encoder.writeBool(AttributeId.ATTRIB_TYPELOCK, true);
res.append(namelock ? "true" : "false"); encoder.writeBool(AttributeId.ATTRIB_NAMELOCK, namelock);
res.append("\">\n"); encoder.openElement(ElementId.ELEM_ADDR);
res.append(" <addr/>\n "); // Blank address encoder.closeElement(ElementId.ELEM_ADDR); // Blank address
sz = dt.getLength(); sz = dt.getLength();
if (sz < 0) { if (sz < 0) {
sz = 1; sz = 1;
} }
dtmanage.buildTypeRef(res, dt, sz); dtmanage.encodeTypeRef(encoder, dt, sz);
res.append("</param>\n"); encoder.closeElement(ElementId.ELEM_PARAM);
} }
res.append("</internallist>\n"); encoder.closeElement(ElementId.ELEM_INTERNALLIST);
} }
res.append("</prototype>\n"); encoder.closeElement(ElementId.ELEM_PROTOTYPE);
} }
/** /**

View file

@ -15,11 +15,12 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A symbol, within a decompiler model, for a function without a body in the current Program. * A symbol, within a decompiler model, for a function without a body in the current Program.
@ -55,13 +56,12 @@ public class HighExternalSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<externrefsymbol"); encoder.openElement(ElementId.ELEM_EXTERNREFSYMBOL);
if ((name != null) && (name.length() > 0)) { // Give the symbol a name if we can if ((name != null) && (name.length() > 0)) { // Give the symbol a name if we can
SpecXmlUtils.xmlEscapeAttribute(buf, "name", name + "_exref"); encoder.writeString(AttributeId.ATTRIB_NAME, name + "_exref");
} }
buf.append(">\n"); AddressXML.encode(encoder, resolveAddress);
AddressXML.buildXML(buf, resolveAddress); encoder.closeElement(ElementId.ELEM_EXTERNREFSYMBOL);
buf.append("</externrefsymbol>\n");
} }
} }

View file

@ -15,19 +15,19 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.program.database.function.FunctionDB; import ghidra.program.database.function.FunctionDB;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.model.address.Address; import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressOutOfBoundsException; import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -58,7 +58,8 @@ public class HighFunction extends PcodeSyntaxTree {
func = function; func = function;
this.language = language; this.language = language;
this.compilerSpec = compilerSpec; this.compilerSpec = compilerSpec;
localSymbols = new LocalSymbolMap(this, SpaceNames.STACK_SPACE_NAME); AddressSpace stackSpace = function.getProgram().getAddressFactory().getStackSpace();
localSymbols = new LocalSymbolMap(this, stackSpace);
globalSymbols = new GlobalSymbolMap(this); globalSymbols = new GlobalSymbolMap(this);
proto = new FunctionPrototype(localSymbols, function); proto = new FunctionPrototype(localSymbols, function);
jumpTables = null; jumpTables = null;
@ -423,70 +424,63 @@ public class HighFunction extends PcodeSyntaxTree {
} }
/** /**
* Build an XML string that represents all the information about this HighFunction. The * Encode this HighFunction to a stream. The size describes how many bytes starting from the
* size describes how many bytes starting from the entry point are used by the function, but * entry point are used by the function, but this doesn't need to be strictly accurate as it
* this doesn't need to be strictly accurate as it is only used to associate the function with * is only used to associate the function with addresses near its entry point.
* addresses near its entry point. * @param encoder is the stream encoder
*
* @param id is the id associated with the function symbol * @param id is the id associated with the function symbol
* @param namespace is the namespace containing the function symbol * @param namespace is the namespace containing the function symbol
* @param entryPoint pass null to use the function entryPoint, pass an address to force an entry point * @param entryPoint pass null to use the function entryPoint, pass an address to force an entry point
* @param size describes how many bytes the function occupies as code * @param size describes how many bytes the function occupies as code
* @return the XML string * @throws IOException for errors in the underlying stream
*/ */
public String buildFunctionXML(long id, Namespace namespace, Address entryPoint, int size) { public void encode(Encoder encoder, long id, Namespace namespace, Address entryPoint, int size)
throws IOException {
// Functions aren't necessarily contiguous with the smallest address being the entry point // Functions aren't necessarily contiguous with the smallest address being the entry point
// So size needs to be smaller than size of the contiguous chunk containing the entry point // So size needs to be smaller than size of the contiguous chunk containing the entry point
StringBuilder resBuf = new StringBuilder(); encoder.openElement(ElementId.ELEM_FUNCTION);
resBuf.append("<function");
if (id != 0) { if (id != 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id);
} }
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, func.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size);
if (func.isInline()) { if (func.isInline()) {
SpecXmlUtils.encodeBooleanAttribute(resBuf, "inline", true); encoder.writeBool(AttributeId.ATTRIB_INLINE, true);
} }
if (func.hasNoReturn()) { if (func.hasNoReturn()) {
SpecXmlUtils.encodeBooleanAttribute(resBuf, "noreturn", true); encoder.writeBool(AttributeId.ATTRIB_NORETURN, true);
} }
resBuf.append(">\n");
if (entryPoint == null) { if (entryPoint == null) {
AddressXML.buildXML(resBuf, func.getEntryPoint()); AddressXML.encode(encoder, func.getEntryPoint());
} }
else { else {
AddressXML.buildXML(resBuf, entryPoint); // Address is forced on XML AddressXML.encode(encoder, entryPoint); // Address is forced on XML
} }
localSymbols.buildLocalDbXML(resBuf, namespace); localSymbols.encodeLocalDb(encoder, namespace);
proto.buildPrototypeXML(resBuf, getDataTypeManager()); proto.encodePrototype(encoder, getDataTypeManager());
if ((jumpTables != null) && (jumpTables.size() > 0)) { if ((jumpTables != null) && (jumpTables.size() > 0)) {
resBuf.append("<jumptablelist>\n"); encoder.openElement(ElementId.ELEM_JUMPTABLELIST);
for (JumpTable jumpTable : jumpTables) { for (JumpTable jumpTable : jumpTables) {
jumpTable.buildXml(resBuf); jumpTable.encode(encoder);
} }
resBuf.append("</jumptablelist>\n"); encoder.closeElement(ElementId.ELEM_JUMPTABLELIST);
} }
boolean hasOverrideTag = ((protoOverrides != null) && (protoOverrides.size() > 0)); boolean hasOverrideTag = ((protoOverrides != null) && (protoOverrides.size() > 0));
if (hasOverrideTag) { if (hasOverrideTag) {
resBuf.append("<override>\n"); encoder.openElement(ElementId.ELEM_OVERRIDE);
}
if ((protoOverrides != null) && (protoOverrides.size() > 0)) {
PcodeDataTypeManager dtmanage = getDataTypeManager(); PcodeDataTypeManager dtmanage = getDataTypeManager();
for (DataTypeSymbol sym : protoOverrides) { for (DataTypeSymbol sym : protoOverrides) {
Address addr = sym.getAddress(); Address addr = sym.getAddress();
FunctionPrototype fproto = new FunctionPrototype( FunctionPrototype fproto = new FunctionPrototype(
(FunctionSignature) sym.getDataType(), compilerSpec, false); (FunctionSignature) sym.getDataType(), compilerSpec, false);
resBuf.append("<protooverride>\n"); encoder.openElement(ElementId.ELEM_PROTOOVERRIDE);
AddressXML.buildXML(resBuf, addr); AddressXML.encode(encoder, addr);
fproto.buildPrototypeXML(resBuf, dtmanage); fproto.encodePrototype(encoder, dtmanage);
resBuf.append("</protooverride>\n"); encoder.closeElement(ElementId.ELEM_PROTOOVERRIDE);
} }
encoder.closeElement(ElementId.ELEM_OVERRIDE);
} }
if (hasOverrideTag) { encoder.closeElement(ElementId.ELEM_FUNCTION);
resBuf.append("</override>\n");
}
resBuf.append("</function>\n");
return resBuf.toString();
} }
public static Namespace findOverrideSpace(Function func) { public static Namespace findOverrideSpace(Function func) {
@ -580,13 +574,14 @@ public class HighFunction extends PcodeSyntaxTree {
} }
/** /**
* Append an XML &lt;parent&gt; tag to the buffer describing the formal path elements * Encode &lt;parent&gt; element to the stream describing the formal path elements
* from the root (global) namespace up to the given namespace * from the root (global) namespace up to the given namespace
* @param buf is the buffer to write to * @param encoder is the stream encoder
* @param namespace is the namespace being described * @param namespace is the namespace being described
* @throws IOException for errors in the underlying stream
*/ */
static public void createNamespaceTag(StringBuilder buf, Namespace namespace) { static public void encodeNamespace(Encoder encoder, Namespace namespace) throws IOException {
buf.append("<parent>\n"); encoder.openElement(ElementId.ELEM_PARENT);
if (namespace != null) { if (namespace != null) {
ArrayList<Namespace> arr = new ArrayList<>(); ArrayList<Namespace> arr = new ArrayList<>();
Namespace curspc = namespace; Namespace curspc = namespace;
@ -597,17 +592,17 @@ public class HighFunction extends PcodeSyntaxTree {
} }
curspc = curspc.getParentNamespace(); curspc = curspc.getParentNamespace();
} }
buf.append("<val/>\n"); // Force global scope to have empty name encoder.openElement(ElementId.ELEM_VAL); // Force global scope to have empty name
encoder.closeElement(ElementId.ELEM_VAL);
for (int i = 1; i < arr.size(); ++i) { for (int i = 1; i < arr.size(); ++i) {
Namespace curScope = arr.get(i); Namespace curScope = arr.get(i);
buf.append("<val"); encoder.openElement(ElementId.ELEM_VAL);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", curScope.getID()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, curScope.getID());
buf.append('>'); encoder.writeString(AttributeId.ATTRIB_CONTENT, curScope.getName());
SpecXmlUtils.xmlEscape(buf, curScope.getName()); encoder.closeElement(ElementId.ELEM_VAL);
buf.append("</val>\n");
} }
} }
buf.append("</parent>\n"); encoder.closeElement(ElementId.ELEM_PARENT);
} }
/** /**

View file

@ -15,11 +15,12 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A function symbol that represents only a shell of (the name and address) the function, * A function symbol that represents only a shell of (the name and address) the function,
@ -53,13 +54,12 @@ public class HighFunctionShellSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<function"); encoder.openElement(ElementId.ELEM_FUNCTION);
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", getId()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, getId());
SpecXmlUtils.xmlEscapeAttribute(buf, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "size", 1); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, 1);
buf.append(">\n"); AddressXML.encode(encoder, getStorage().getMinAddress());
AddressXML.buildXML(buf, getStorage().getMinAddress()); encoder.closeElement(ElementId.ELEM_FUNCTION);
buf.append("</function>\n");
} }
} }

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
@ -70,11 +72,9 @@ public class HighFunctionSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
MappedEntry entry = (MappedEntry) getFirstWholeMap(); MappedEntry entry = (MappedEntry) getFirstWholeMap();
String funcString = function.encode(encoder, getId(), getNamespace(), entry.getStorage().getMinAddress(),
function.buildFunctionXML(getId(), getNamespace(), entry.getStorage().getMinAddress(), entry.getSize());
entry.getSize());
buf.append(funcString);
} }
} }

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
@ -46,9 +48,9 @@ public class HighLabelSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<labelsym"); encoder.openElement(ElementId.ELEM_LABELSYM);
saveXMLHeader(buf); encodeHeader(encoder);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_LABELSYM);
} }
} }

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.DynamicVariableStorage; import ghidra.program.model.lang.DynamicVariableStorage;
@ -22,7 +24,6 @@ import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.Symbol;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type * A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type
@ -361,46 +362,47 @@ public class HighSymbol {
} }
/** /**
* Write out attributes for the base XML tag * Encode attributes for the base symbol element
* @param buf is the XML output stream * @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
protected void saveXMLHeader(StringBuilder buf) { protected void encodeHeader(Encoder encoder) throws IOException {
if ((id >> 56) != (ID_BASE >> 56)) { // Don't send down internal ids if ((id >> 56) != (ID_BASE >> 56)) { // Don't send down internal ids
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", id); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id);
} }
SpecXmlUtils.xmlEscapeAttribute(buf, "name", name); encoder.writeString(AttributeId.ATTRIB_NAME, name);
SpecXmlUtils.encodeBooleanAttribute(buf, "typelock", typelock); encoder.writeBool(AttributeId.ATTRIB_TYPELOCK, typelock);
SpecXmlUtils.encodeBooleanAttribute(buf, "namelock", namelock); encoder.writeBool(AttributeId.ATTRIB_NAMELOCK, namelock);
SpecXmlUtils.encodeBooleanAttribute(buf, "readonly", isReadOnly()); encoder.writeBool(AttributeId.ATTRIB_READONLY, isReadOnly());
boolean isVolatile = entryList[0].isVolatile(); boolean isVolatile = entryList[0].isVolatile();
if (isVolatile) { if (isVolatile) {
SpecXmlUtils.encodeBooleanAttribute(buf, "volatile", true); encoder.writeBool(AttributeId.ATTRIB_VOLATILE, true);
} }
if (isIsolated()) { if (isIsolated()) {
SpecXmlUtils.encodeBooleanAttribute(buf, "merge", false); encoder.writeBool(AttributeId.ATTRIB_MERGE, false);
} }
if (isThis) { if (isThis) {
SpecXmlUtils.encodeBooleanAttribute(buf, "thisptr", true); encoder.writeBool(AttributeId.ATTRIB_THISPTR, true);
} }
if (isHidden) { if (isHidden) {
SpecXmlUtils.encodeBooleanAttribute(buf, "hiddenretparm", true); encoder.writeBool(AttributeId.ATTRIB_HIDDENRETPARM, true);
} }
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "cat", category); encoder.writeSignedInteger(AttributeId.ATTRIB_CAT, category);
if (categoryIndex >= 0) { if (categoryIndex >= 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", categoryIndex); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, categoryIndex);
} }
} }
/** /**
* Save the symbol description as a tag to the XML stream. This does NOT save the mappings. * Encode the symbol description as an element to the stream. This does NOT save the mappings.
* @param buf is the XML stream * @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<symbol"); encoder.openElement(ElementId.ELEM_SYMBOL);
saveXMLHeader(buf); encodeHeader(encoder);
buf.append(">\n"); dtmanage.encodeTypeRef(encoder, type, getSize());
dtmanage.buildTypeRef(buf, type, getSize()); encoder.closeElement(ElementId.ELEM_SYMBOL);
buf.append("</symbol>\n");
} }
protected void decodeHeader(Decoder decoder) throws PcodeXMLException { protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
@ -544,16 +546,17 @@ public class HighSymbol {
} }
/** /**
* Write out the given symbol with all its mapping as a &lt;mapsym&gt; tag to the given XML stream. * Encode the given symbol with all its mapping as a &lt;mapsym&gt; element to the stream.
* @param res is the given XML stream * @param encoder is the stream encoder
* @param sym is the given symbol * @param sym is the given symbol
* @throws IOException for errors in the underlying stream
*/ */
public static void buildMapSymXML(StringBuilder res, HighSymbol sym) { public static void encodeMapSym(Encoder encoder, HighSymbol sym) throws IOException {
res.append("<mapsym>\n"); encoder.openElement(ElementId.ELEM_MAPSYM);
sym.saveXML(res); sym.encode(encoder);
for (SymbolEntry entry : sym.entryList) { for (SymbolEntry entry : sym.entryList) {
entry.saveXml(res); entry.encode(encoder);
} }
res.append("</mapsym>\n"); encoder.closeElement(ElementId.ELEM_MAPSYM);
} }
} }

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
@ -96,16 +97,16 @@ public class JumpTable {
return destlist; return destlist;
} }
public void buildXml(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<basicoverride>\n"); encoder.openElement(ElementId.ELEM_BASICOVERRIDE);
for (Address element : destlist) { for (Address element : destlist) {
buf.append("<dest"); encoder.openElement(ElementId.ELEM_DEST);
AddressXML.appendAttributes(buf, element); AddressXML.encodeAttributes(encoder, element);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_DEST);
} }
// We could add <normaddr> and <normhash> tags to specify switch variable // We could add <normaddr> and <normhash> elements to specify switch variable
// We could add a <startval> tag to indicate starting value of the switch variable // We could add a <startval> tag to indicate starting value of the switch variable
buf.append("</basicoverride>\n"); encoder.closeElement(ElementId.ELEM_BASICOVERRIDE);
} }
} }
@ -177,7 +178,8 @@ public class JumpTable {
} }
if (subel == ElementId.ELEM_DEST.getId()) { if (subel == ElementId.ELEM_DEST.getId()) {
decoder.openElement(); decoder.openElement();
Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder)); Address caseAddr =
translateOverlayAddress(AddressXML.decodeFromAttributes(decoder));
aTable.add(caseAddr); aTable.add(caseAddr);
decoder.rewindAttributes(); decoder.rewindAttributes();
for (;;) { for (;;) {
@ -212,21 +214,20 @@ public class JumpTable {
decoder.closeElement(el); decoder.closeElement(el);
} }
public void buildXml(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<jumptable>\n"); encoder.openElement(ElementId.ELEM_JUMPTABLE);
AddressXML.buildXML(buf, opAddress); AddressXML.encode(encoder, opAddress);
buf.append('\n');
if (addressTable != null) { if (addressTable != null) {
for (Address element : addressTable) { for (Address element : addressTable) {
buf.append("<dest"); encoder.openElement(ElementId.ELEM_DEST);
AddressXML.appendAttributes(buf, element); AddressXML.encodeAttributes(encoder, element);
buf.append("/>\n"); encoder.closeElement(ElementId.ELEM_DEST);
} }
} }
if (override != null) { if (override != null) {
override.buildXml(buf); override.encode(encoder);
} }
buf.append("</jumptable>\n"); encoder.closeElement(ElementId.ELEM_JUMPTABLE);
} }
public Address getSwitchAddress() { public Address getSwitchAddress() {

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@ -23,7 +24,6 @@ import ghidra.program.model.data.Undefined;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A container for local symbols within the decompiler's model of a function. It contains HighSymbol * A container for local symbols within the decompiler's model of a function. It contains HighSymbol
@ -35,7 +35,7 @@ import ghidra.util.xml.SpecXmlUtils;
*/ */
public class LocalSymbolMap { public class LocalSymbolMap {
private HighFunction func; // Function to which these variables are local private HighFunction func; // Function to which these variables are local
private String spacename; private AddressSpace localSpace; // The address space (usually stack) associated with map
private HashMap<MappedVarKey, HighSymbol> addrMappedSymbols; // Hashed by addr and pcaddr private HashMap<MappedVarKey, HighSymbol> addrMappedSymbols; // Hashed by addr and pcaddr
private HashMap<Long, HighSymbol> symbolMap; // Hashed by unique key private HashMap<Long, HighSymbol> symbolMap; // Hashed by unique key
private HighSymbol[] paramSymbols; private HighSymbol[] paramSymbols;
@ -43,11 +43,11 @@ public class LocalSymbolMap {
/** /**
* @param highFunc HighFunction the local variables are defined within. * @param highFunc HighFunction the local variables are defined within.
* @param spcname space name the local variables are defined within. * @param spc the address space the local variables are defined within.
*/ */
public LocalSymbolMap(HighFunction highFunc, String spcname) { public LocalSymbolMap(HighFunction highFunc, AddressSpace spc) {
func = highFunc; func = highFunc;
spacename = spcname; localSpace = spc;
addrMappedSymbols = new HashMap<>(); addrMappedSymbols = new HashMap<>();
symbolMap = new HashMap<>(); symbolMap = new HashMap<>();
paramSymbols = new HighSymbol[0]; paramSymbols = new HighSymbol[0];
@ -278,7 +278,7 @@ public class LocalSymbolMap {
*/ */
public void decodeScope(Decoder decoder) throws PcodeXMLException { public void decodeScope(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_LOCALDB); int el = decoder.openElement(ElementId.ELEM_LOCALDB);
spacename = decoder.readString(AttributeId.ATTRIB_MAIN); localSpace = decoder.readSpace(AttributeId.ATTRIB_MAIN);
int scopeel = decoder.openElement(ElementId.ELEM_SCOPE); int scopeel = decoder.openElement(ElementId.ELEM_SCOPE);
decoder.skipElement(); // This is the parent scope path decoder.skipElement(); // This is the parent scope path
@ -323,35 +323,35 @@ public class LocalSymbolMap {
} }
/** /**
* Output an XML document representing this local variable map. * Encode all the variables in this local variable map to the stream
* @param resBuf is the buffer to write to * @param encoder is the stream encoder
* @param namespace if the namespace of the function * @param namespace if the namespace of the function
* @throws IOException for errors in the underlying stream
*/ */
public void buildLocalDbXML(StringBuilder resBuf, Namespace namespace) { // Get memory mapped local variables public void encodeLocalDb(Encoder encoder, Namespace namespace) throws IOException {
resBuf.append("<localdb"); encoder.openElement(ElementId.ELEM_LOCALDB);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "lock", false); encoder.writeBool(AttributeId.ATTRIB_LOCK, false);
SpecXmlUtils.encodeStringAttribute(resBuf, "main", spacename); encoder.writeSpace(AttributeId.ATTRIB_MAIN, localSpace);
resBuf.append(">\n"); encoder.openElement(ElementId.ELEM_SCOPE);
resBuf.append("<scope"); encoder.writeString(AttributeId.ATTRIB_NAME, func.getFunction().getName());
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", func.getFunction().getName()); encoder.openElement(ElementId.ELEM_PARENT);
resBuf.append(">\n");
resBuf.append("<parent");
long parentid = Namespace.GLOBAL_NAMESPACE_ID; long parentid = Namespace.GLOBAL_NAMESPACE_ID;
if (!HighFunction.collapseToGlobal(namespace)) { if (!HighFunction.collapseToGlobal(namespace)) {
parentid = namespace.getID(); parentid = namespace.getID();
} }
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", parentid); encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, parentid);
resBuf.append("/>\n"); encoder.closeElement(ElementId.ELEM_PARENT);
resBuf.append("<rangelist/>\n"); // Empty address range encoder.openElement(ElementId.ELEM_RANGELIST); // Emptry address range
resBuf.append("<symbollist>\n"); encoder.closeElement(ElementId.ELEM_RANGELIST);
encoder.openElement(ElementId.ELEM_SYMBOLLIST);
Iterator<HighSymbol> iter = symbolMap.values().iterator(); Iterator<HighSymbol> iter = symbolMap.values().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
HighSymbol sym = iter.next(); HighSymbol sym = iter.next();
HighSymbol.buildMapSymXML(resBuf, sym); HighSymbol.encodeMapSym(encoder, sym);
} }
resBuf.append("</symbollist>\n"); encoder.closeElement(ElementId.ELEM_SYMBOLLIST);
resBuf.append("</scope>\n"); encoder.closeElement(ElementId.ELEM_SCOPE);
resBuf.append("</localdb>\n"); encoder.closeElement(ElementId.ELEM_LOCALDB);
} }
/** /**

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.AbstractFloatDataType; import ghidra.program.model.data.AbstractFloatDataType;
@ -82,14 +84,14 @@ public class MappedEntry extends SymbolEntry {
} }
@Override @Override
public void saveXml(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
int logicalsize = 0; // Assume datatype size and storage size are the same int logicalsize = 0; // Assume datatype size and storage size are the same
int typeLength = symbol.type.getLength(); int typeLength = symbol.type.getLength();
if (typeLength != storage.size() && symbol.type instanceof AbstractFloatDataType) { if (typeLength != storage.size() && symbol.type instanceof AbstractFloatDataType) {
logicalsize = typeLength; // Force a logicalsize logicalsize = typeLength; // Force a logicalsize
} }
AddressXML.buildXML(buf, storage.getVarnodes(), logicalsize); AddressXML.encode(encoder, storage.getVarnodes(), logicalsize);
buildRangelistXML(buf); encodeRangelist(encoder);
} }
@Override @Override

View file

@ -16,11 +16,9 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -146,15 +144,19 @@ public class PcodeBlock {
} }
/** /**
* Save edge as XML assuming we already know what block we are in * Encode edge to stream assuming we already know what block we are in
* @param buffer to write tag to * @param encoder is the stream encoder
* @throws IOException for errors writing to underlying stream
*/ */
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
buffer.append("<edge"); encoder.openElement(ElementId.ELEM_EDGE);
// We are not saving label currently // We are not encoding label currently
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "end", point.getIndex()); // Reference to other end of edge
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "rev", reverse_index); // Position within other blocks edgelist // Reference to other end of edge
buffer.append("/>\n"); encoder.writeSignedInteger(AttributeId.ATTRIB_END, point.getIndex());
// Position within other blocks edgelist
encoder.writeSignedInteger(AttributeId.ATTRIB_REV, reverse_index);
encoder.closeElement(ElementId.ELEM_EDGE);
} }
/** /**
@ -344,30 +346,38 @@ public class PcodeBlock {
return bl; return bl;
} }
public void saveXmlHeader(StringBuilder buffer) { /**
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "index", index); * Encode basic attributes to stream. Assume this block's element is already started.
* @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/
protected void encodeHeader(Encoder encoder) throws IOException {
encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, index);
} }
public void decodeHeader(Decoder decoder) throws PcodeXMLException { protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX); index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
} }
/** /**
* Serialize information about the block to XML, * Encode information about the block to stream,
* other than header and edge info * other than header and edge info
* @param writer is where to serialize to * @param encoder is the stream encoder
* @throws IOException if there is a problem with the stream * @throws IOException for errors writing to the underlying stream
*/ */
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
// No body by default // No body by default
} }
public void saveXmlEdges(Writer writer) throws IOException { /**
StringBuilder buf = new StringBuilder(); * Encode information about this blocks edges to stream
* @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
*/
protected void encodeEdges(Encoder encoder) throws IOException {
for (BlockEdge element : intothis) { for (BlockEdge element : intothis) {
element.saveXml(buf); element.encode(encoder);
} }
writer.write(buf.toString());
} }
/** /**
@ -376,11 +386,11 @@ public class PcodeBlock {
* @param resolver is for looking up edge references * @param resolver is for looking up edge references
* @throws PcodeXMLException for invalid encoding * @throws PcodeXMLException for invalid encoding
*/ */
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
// No body to restore by default // No body to restore by default
} }
public void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
for (;;) { for (;;) {
int el = decoder.peekElement(); int el = decoder.peekElement();
if (el != ElementId.ELEM_EDGE.getId()) { if (el != ElementId.ELEM_EDGE.getId()) {
@ -390,17 +400,25 @@ public class PcodeBlock {
} }
} }
public void saveXml(Writer writer) throws IOException { /**
StringBuilder buf = new StringBuilder(); * Encode this block to a stream
buf.append("<block"); * @param encoder is the stream encoder
saveXmlHeader(buf); * @throws IOException for errors writing to the underlying stream
buf.append(">\n"); */
writer.write(buf.toString()); public void encode(Encoder encoder) throws IOException {
saveXmlBody(writer); encoder.openElement(ElementId.ELEM_BLOCK);
saveXmlEdges(writer); encodeHeader(encoder);
writer.write("</block>\n"); encodeBody(encoder);
encodeEdges(encoder);
encoder.closeElement(ElementId.ELEM_BLOCK);
} }
/**
* Decode this block from a stream
* @param decoder is the stream decoder
* @param resolver is the map from reference to block object
* @throws PcodeXMLException for errors in the encoding
*/
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException { public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_BLOCK); int el = decoder.openElement(ElementId.ELEM_BLOCK);
decodeHeader(decoder); decodeHeader(decoder);

View file

@ -16,11 +16,9 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -110,25 +108,23 @@ public class PcodeBlockBasic extends PcodeBlock {
} }
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { protected void encodeBody(Encoder encoder) throws IOException {
writer.append("<rangelist>\n"); encoder.openElement(ElementId.ELEM_RANGELIST);
AddressRangeIterator iter = cover.getAddressRanges(true); AddressRangeIterator iter = cover.getAddressRanges(true);
while (iter.hasNext()) { while (iter.hasNext()) {
AddressRange range = iter.next(); AddressRange range = iter.next();
StringBuilder buffer = new StringBuilder(); encoder.openElement(ElementId.ELEM_RANGE);
buffer.append("<range"); encoder.writeSpace(AttributeId.ATTRIB_SPACE, range.getAddressSpace());
SpecXmlUtils.encodeStringAttribute(buffer, "space", range.getAddressSpace().getName()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST,
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first",
range.getMinAddress().getOffset()); range.getMinAddress().getOffset());
SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST,
range.getMaxAddress().getOffset()); range.getMaxAddress().getOffset());
writer.append(buffer);
} }
writer.append("</rangelist>\n"); encoder.closeElement(ElementId.ELEM_RANGELIST);
} }
@Override @Override
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST); int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
for (;;) { for (;;) {
int rangeel = decoder.peekElement(); int rangeel = decoder.peekElement();

View file

@ -15,11 +15,11 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -416,31 +416,37 @@ public class PcodeOp {
output = vn; output = vn;
} }
public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) { /**
resBuf.append("<op"); * Encode this PcodeOp to a stream as an \<op> element
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode); * @param encoder is the stream encoder
resBuf.append('>'); * @param addrFactory is a factory for looking up encoded address spaces
resBuf.append(seqnum.buildXML()); * @throws IOException for errors in the underlying stream
*/
public void encode(Encoder encoder, AddressFactory addrFactory) throws IOException {
encoder.openElement(ElementId.ELEM_OP);
encoder.writeSignedInteger(AttributeId.ATTRIB_CODE, opcode);
seqnum.encode(encoder);
if (output == null) { if (output == null) {
resBuf.append("<void/>"); encoder.openElement(ElementId.ELEM_VOID);
encoder.closeElement(ElementId.ELEM_VOID);
} }
else { else {
output.buildXML(resBuf); output.encode(encoder);
} }
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) { if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
int spaceId = (int) input[0].getOffset(); int spaceId = (int) input[0].getOffset();
resBuf.append("<spaceid"); encoder.openElement(ElementId.ELEM_SPACEID);
AddressSpace space = addrFactory.getAddressSpace(spaceId); AddressSpace space = addrFactory.getAddressSpace(spaceId);
SpecXmlUtils.encodeStringAttribute(resBuf, "name", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_NAME, space);
resBuf.append("/>"); encoder.closeElement(ElementId.ELEM_SPACEID);
} }
else if (input.length > 0) { else if (input.length > 0) {
input[0].buildXML(resBuf); input[0].encode(encoder);
} }
for (int i = 1; i < input.length; ++i) { for (int i = 1; i < input.length; ++i) {
input[i].buildXML(resBuf); input[i].encode(encoder);
} }
resBuf.append("</op>"); encoder.closeElement(ElementId.ELEM_OP);
} }
/** /**

View file

@ -15,9 +15,10 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -29,9 +30,9 @@ import ghidra.util.xml.SpecXmlUtils;
public class SequenceNumber implements Comparable<SequenceNumber> { public class SequenceNumber implements Comparable<SequenceNumber> {
private Address pc; // Address of assembly language instruction private Address pc; // Address of assembly language instruction
private int uniq; // Sub-address for distinguishing multiple PcodeOps at one private int uniq; // Sub-address for distinguishing multiple PcodeOps at one
// instruction address. Does not change over lifetime of PcodeOp // instruction address. Does not change over lifetime of PcodeOp
private int order; // Contains relative position information of PcodeOps within private int order; // Contains relative position information of PcodeOps within
// a basic block, may change as basic block is edited. // a basic block, may change as basic block is edited.
/** /**
* Construct a sequence number for an instruction at an address and sequence of pcode op within * Construct a sequence number for an instruction at an address and sequence of pcode op within
@ -125,19 +126,19 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
} }
/** /**
* @return Build XML tag for SequenceNumber * Encode this sequence number to the stream
* @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
public StringBuilder buildXML() { public void encode(Encoder encoder) throws IOException {
StringBuilder resBuf = new StringBuilder(); encoder.openElement(ElementId.ELEM_SEQNUM);
resBuf.append("<seqnum");
AddressSpace space = pc.getAddressSpace(); AddressSpace space = pc.getAddressSpace();
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, pc.getOffset());
if (uniq != -1) { if (uniq != -1) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq); encoder.writeUnsignedInteger(AttributeId.ATTRIB_UNIQ, uniq);
} }
resBuf.append("/>"); encoder.closeElement(ElementId.ELEM_SEQNUM);
return resBuf;
} }
/** /**

View file

@ -15,10 +15,11 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A mapping from a HighSymbol object to the storage that holds the symbol's value. * A mapping from a HighSymbol object to the storage that holds the symbol's value.
@ -44,10 +45,11 @@ public abstract class SymbolEntry {
public abstract void decode(Decoder decoder) throws PcodeXMLException; public abstract void decode(Decoder decoder) throws PcodeXMLException;
/** /**
* Save this entry as (a set of) XML tags to the given stream * Encode this entry as (a set of) elements to the given stream
* @param buf is the given stream * @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
public abstract void saveXml(StringBuilder buf); public abstract void encode(Encoder encoder) throws IOException;
/** /**
* Get the storage associated with this particular mapping of the Symbol * Get the storage associated with this particular mapping of the Symbol
@ -98,12 +100,12 @@ public abstract class SymbolEntry {
decoder.closeElement(rangelistel); decoder.closeElement(rangelistel);
} }
protected void buildRangelistXML(StringBuilder res) { protected void encodeRangelist(Encoder encoder) throws IOException {
encoder.openElement(ElementId.ELEM_RANGELIST);
if (pcaddr == null || pcaddr.isExternalAddress()) { if (pcaddr == null || pcaddr.isExternalAddress()) {
res.append("<rangelist/>"); encoder.closeElement(ElementId.ELEM_RANGELIST);
return; return;
} }
res.append("<rangelist>");
AddressSpace space = pcaddr.getAddressSpace(); AddressSpace space = pcaddr.getAddressSpace();
long off; long off;
if (space.isOverlaySpace()) { if (space.isOverlaySpace()) {
@ -113,11 +115,11 @@ public abstract class SymbolEntry {
else { else {
off = pcaddr.getUnsignedOffset(); off = pcaddr.getUnsignedOffset();
} }
res.append("<range"); encoder.openElement(ElementId.ELEM_RANGE);
SpecXmlUtils.encodeStringAttribute(res, "space", space.getName()); encoder.writeSpace(AttributeId.ATTRIB_SPACE, space);
SpecXmlUtils.encodeUnsignedIntegerAttribute(res, "first", off); encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, off);
SpecXmlUtils.encodeUnsignedIntegerAttribute(res, "last", off); encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, off);
res.append("/>"); encoder.closeElement(ElementId.ELEM_RANGE);
res.append("</rangelist>\n"); encoder.closeElement(ElementId.ELEM_RANGELIST);
} }
} }

View file

@ -15,9 +15,10 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* A specialized HighSymbol that directs the decompiler to use a specific field of a union, * A specialized HighSymbol that directs the decompiler to use a specific field of a union,
@ -39,13 +40,12 @@ public class UnionFacetSymbol extends HighSymbol {
} }
@Override @Override
public void saveXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
buf.append("<facetsymbol"); encoder.openElement(ElementId.ELEM_FACETSYMBOL);
saveXMLHeader(buf); encodeHeader(encoder);
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "field", fieldNumber); encoder.writeSignedInteger(AttributeId.ATTRIB_FIELD, fieldNumber);
buf.append(">\n"); dtmanage.encodeTypeRef(encoder, type, getSize());
dtmanage.buildTypeRef(buf, type, getSize()); encoder.closeElement(ElementId.ELEM_FACETSYMBOL);
buf.append("</facetsymbol>\n");
} }
/** /**

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@ -312,10 +313,11 @@ public class Varnode {
} }
/** /**
* @param buf is the builder to which to append XML * @param encoder is the stream encoder
* @throws IOException for errors in the underlying stream
*/ */
public void buildXML(StringBuilder buf) { public void encode(Encoder encoder) throws IOException {
AddressXML.buildXML(buf, address, size); AddressXML.encode(encoder, address, size);
} }
/** /**
@ -348,7 +350,7 @@ public class Varnode {
} }
else if (attribId == AttributeId.ATTRIB_REF.getId()) { // If we have a reference else if (attribId == AttributeId.ATTRIB_REF.getId()) { // If we have a reference
ref = (int) decoder.readUnsignedInteger(); ref = (int) decoder.readUnsignedInteger();
Varnode vn = factory.getRef(ref); // The varnode may already exit Varnode vn = factory.getRef(ref); // The varnode may already exist
if (vn != null) { if (vn != null) {
decoder.closeElement(el); decoder.closeElement(el);
return vn; return vn;

View file

@ -119,6 +119,8 @@ public class XmlDecode implements Decoder {
throw new PcodeXMLException("Expecting end, but got start <" + el.getName() + '>'); throw new PcodeXMLException("Expecting end, but got start <" + el.getName() + '>');
} }
currentEl = null; currentEl = null;
// Only one possible element can be closed as enforced by SAXParser
// so additional checks are somewhat redundant
// int elemId = ElementId.find(el.getName()); // int elemId = ElementId.find(el.getName());
// if (elemId != id) { // if (elemId != id) {
// throw new PcodeXMLException("Unexpected end, <" + el.getName() + '>'); // throw new PcodeXMLException("Unexpected end, <" + el.getName() + '>');

View file

@ -0,0 +1,172 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.pcode;
import java.io.IOException;
import ghidra.program.model.address.AddressSpace;
import ghidra.util.xml.SpecXmlUtils;
/**
* An XML based encoder
* The underlying transfer encoding is an XML document.
* The encoder is initialized with a StringBuilder which will receive the XML document as calls
* are made on the encoder.
*/
public class XmlEncode implements Encoder {
private StringBuilder buffer;
private boolean elementTagIsOpen;
public XmlEncode() {
buffer = new StringBuilder();
elementTagIsOpen = false;
}
@Override
public String toString() {
return buffer.toString();
}
@Override
public void clear() {
buffer = new StringBuilder();
elementTagIsOpen = false;
}
@Override
public void openElement(ElementId elemId) throws IOException {
if (elementTagIsOpen) {
buffer.append('>');
}
else {
elementTagIsOpen = true;
}
buffer.append('<');
buffer.append(elemId.getName());
}
@Override
public void closeElement(ElementId elemId) throws IOException {
if (elementTagIsOpen) {
buffer.append("/>");
elementTagIsOpen = false;
}
else {
buffer.append("</");
buffer.append(elemId.getName());
buffer.append('>');
}
}
@Override
public void writeBool(AttributeId attribId, boolean val) throws IOException {
if (attribId == AttributeId.ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
buffer.append('>');
elementTagIsOpen = false;
}
buffer.append(val ? "true" : "false");
return;
}
buffer.append(' ');
buffer.append(attribId.getName());
buffer.append("=\"");
buffer.append(val ? "true" : "false");
buffer.append("\"");
}
@Override
public void writeSignedInteger(AttributeId attribId, long val) throws IOException {
if (attribId == AttributeId.ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
buffer.append('>');
elementTagIsOpen = false;
}
buffer.append(Long.toString(val, 10));
return;
}
buffer.append(' ');
buffer.append(attribId.getName());
buffer.append("=\"");
buffer.append(Long.toString(val, 10));
buffer.append("\"");
}
@Override
public void writeUnsignedInteger(AttributeId attribId, long val) throws IOException {
if (attribId == AttributeId.ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
buffer.append('>');
elementTagIsOpen = false;
}
buffer.append("0x");
buffer.append(Long.toHexString(val));
return;
}
buffer.append(' ');
buffer.append(attribId.getName());
buffer.append("=\"0x");
buffer.append(Long.toHexString(val));
buffer.append("\"");
}
@Override
public void writeString(AttributeId attribId, String val) throws IOException {
if (attribId == AttributeId.ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
buffer.append('>');
elementTagIsOpen = false;
}
SpecXmlUtils.xmlEscape(buffer, val);
return;
}
buffer.append(' ');
buffer.append(attribId.getName());
buffer.append("=\"");
SpecXmlUtils.xmlEscape(buffer, val);
buffer.append("\"");
}
@Override
public void writeSpace(AttributeId attribId, AddressSpace spc) throws IOException {
String spcName;
if (spc.getType() == AddressSpace.TYPE_VARIABLE) {
spcName = "join";
}
else {
spcName = spc.getName();
}
if (attribId == AttributeId.ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) {
buffer.append('>');
elementTagIsOpen = false;
}
SpecXmlUtils.xmlEscape(buffer, spcName);
return;
}
buffer.append(' ');
buffer.append(attribId.getName());
buffer.append("=\"");
SpecXmlUtils.xmlEscape(buffer, spcName);
buffer.append("\"");
}
@Override
public byte[] getBytes() {
return buffer.toString().getBytes();
}
}

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.util; package ghidra.program.util;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@ -22,6 +23,7 @@ import ghidra.program.model.data.DataOrganization;
import ghidra.program.model.data.GenericCallingConvention; import ghidra.program.model.data.GenericCallingConvention;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.Encoder;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.RangeMap; import ghidra.util.datastruct.RangeMap;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
@ -681,7 +683,7 @@ class TemporaryCompilerSpec implements CompilerSpec {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -28,8 +28,7 @@ import ghidra.program.model.lang.InjectContext;
import ghidra.program.model.lang.InjectPayload; import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -178,12 +177,12 @@ public class InjectPayloadDexParameters implements InjectPayload {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
// Provide a minimal tag so decompiler can call-back // Provide a minimal tag so decompiler can call-back
buffer.append("<pcode"); encoder.openElement(ElementId.ELEM_PCODE);
SpecXmlUtils.encodeStringAttribute(buffer, "inject", "uponentry"); encoder.writeString(AttributeId.ATTRIB_INJECT, "uponentry");
SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true); encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_PCODE);
} }
@Override @Override

View file

@ -28,8 +28,7 @@ import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.InjectContext; import ghidra.program.model.lang.InjectContext;
import ghidra.program.model.lang.InjectPayload; import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -111,12 +110,12 @@ public class InjectPayloadJavaParameters implements InjectPayload {
} }
@Override @Override
public void saveXml(StringBuilder buffer) { public void encode(Encoder encoder) throws IOException {
// Provide a minimal tag so decompiler can call-back // Provide a minimal tag so decompiler can call-back
buffer.append("<pcode"); encoder.openElement(ElementId.ELEM_PCODE);
SpecXmlUtils.encodeStringAttribute(buffer, "inject", "uponentry"); encoder.writeString(AttributeId.ATTRIB_INJECT, "uponentry");
SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true); encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true);
buffer.append("/>\n"); encoder.closeElement(ElementId.ELEM_PCODE);
} }
@Override @Override