From aa038c363609fe13402c71516ebf7277fdac864e Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Tue, 12 Jul 2022 19:07:37 -0400 Subject: [PATCH] GP-2262 Encoder --- .../src/decompile/cpp/architecture.cc | 80 +- .../src/decompile/cpp/architecture.hh | 2 + .../Decompiler/src/decompile/cpp/bfd_arch.cc | 2 +- .../Decompiler/src/decompile/cpp/block.cc | 18 +- .../Decompiler/src/decompile/cpp/callgraph.cc | 4 +- .../Decompiler/src/decompile/cpp/comment.cc | 6 +- .../Decompiler/src/decompile/cpp/cpool.cc | 16 +- .../Decompiler/src/decompile/cpp/database.cc | 40 +- .../Decompiler/src/decompile/cpp/fspec.cc | 60 +- .../Decompiler/src/decompile/cpp/funcdata.cc | 12 +- .../src/decompile/cpp/ghidra_process.cc | 2 +- .../src/decompile/cpp/globalcontext.cc | 14 +- .../Decompiler/src/decompile/cpp/jumptable.cc | 18 +- .../src/decompile/cpp/loadimage_xml.cc | 6 +- .../Decompiler/src/decompile/cpp/marshal.cc | 4 +- .../Decompiler/src/decompile/cpp/op.cc | 3 +- .../Decompiler/src/decompile/cpp/op.hh | 1 + .../Decompiler/src/decompile/cpp/options.cc | 74 +- .../Decompiler/src/decompile/cpp/override.cc | 14 +- .../Decompiler/src/decompile/cpp/paramid.cc | 6 +- .../src/decompile/cpp/pcodeinject.cc | 36 +- .../src/decompile/cpp/prefersplit.cc | 2 +- .../src/decompile/cpp/prettyprint.cc | 36 +- .../Decompiler/src/decompile/cpp/raw_arch.cc | 2 +- .../src/decompile/cpp/sleigh_arch.cc | 26 +- .../Decompiler/src/decompile/cpp/space.cc | 28 +- .../src/decompile/cpp/stringmanage.cc | 8 +- .../Decompiler/src/decompile/cpp/transform.cc | 2 +- .../Decompiler/src/decompile/cpp/translate.cc | 28 +- .../Decompiler/src/decompile/cpp/type.cc | 72 +- .../Decompiler/src/decompile/cpp/type.hh | 18 + .../Decompiler/src/decompile/cpp/userop.cc | 14 +- .../Decompiler/src/decompile/cpp/variable.cc | 8 +- .../Decompiler/src/decompile/cpp/varmap.cc | 6 +- .../Decompiler/src/decompile/cpp/varnode.cc | 10 +- .../Decompiler/src/decompile/cpp/xml_arch.cc | 2 +- .../app/decompiler/DecompInterface.java | 34 +- .../app/decompiler/DecompileCallback.java | 567 ++++++------- .../ghidra/app/decompiler/DecompileDebug.java | 166 ++-- .../app/decompiler/DecompileProcess.java | 75 +- .../core/decompile/SpecExtensionTest.java | 10 +- .../processors/sleigh/SleighLanguage.java | 143 +--- .../processors/sleigh/SpecExtensionPanel.java | 47 +- .../model/data/BitFieldPackingImpl.java | 28 +- .../model/data/DataOrganizationImpl.java | 116 +-- .../program/model/lang/BasicCompilerSpec.java | 180 +++-- .../program/model/lang/CompilerSpec.java | 11 +- .../program/model/lang/ConstantPool.java | 55 +- .../program/model/lang/ContextSetting.java | 34 +- .../program/model/lang/InjectPayload.java | 10 +- .../model/lang/InjectPayloadCallfixup.java | 20 +- .../model/lang/InjectPayloadCallother.java | 15 +- .../model/lang/InjectPayloadSegment.java | 33 +- .../model/lang/InjectPayloadSleigh.java | 39 +- .../ghidra/program/model/lang/ParamEntry.java | 23 +- .../ghidra/program/model/lang/ParamList.java | 4 +- .../program/model/lang/ParamListStandard.java | 25 +- .../model/lang/PcodeInjectLibrary.java | 16 +- .../program/model/lang/PrototypeModel.java | 114 ++- .../model/lang/PrototypeModelMerged.java | 18 +- .../program/model/pcode/AddressXML.java | 163 ++-- .../program/model/pcode/AttributeId.java | 282 +++---- .../program/model/pcode/BlockCondition.java | 11 +- .../ghidra/program/model/pcode/BlockCopy.java | 11 +- .../ghidra/program/model/pcode/BlockGoto.java | 21 +- .../program/model/pcode/BlockGraph.java | 23 +- .../program/model/pcode/BlockIfGoto.java | 21 +- .../program/model/pcode/BlockMultiGoto.java | 22 +- .../ghidra/program/model/pcode/Decoder.java | 4 +- .../program/model/pcode/DynamicEntry.java | 10 +- .../ghidra/program/model/pcode/ElementId.java | 546 +++++++------ .../ghidra/program/model/pcode/Encoder.java | 29 +- .../program/model/pcode/EquateSymbol.java | 20 +- .../model/pcode/FunctionPrototype.java | 79 +- .../model/pcode/HighExternalSymbol.java | 14 +- .../program/model/pcode/HighFunction.java | 95 ++- .../model/pcode/HighFunctionShellSymbol.java | 18 +- .../model/pcode/HighFunctionSymbol.java | 10 +- .../program/model/pcode/HighLabelSymbol.java | 10 +- .../program/model/pcode/HighSymbol.java | 63 +- .../ghidra/program/model/pcode/JumpTable.java | 35 +- .../program/model/pcode/LocalSymbolMap.java | 50 +- .../program/model/pcode/MappedEntry.java | 8 +- .../program/model/pcode/PcodeBlock.java | 82 +- .../program/model/pcode/PcodeBlockBasic.java | 20 +- .../model/pcode/PcodeDataTypeManager.java | 758 +++++++++--------- .../ghidra/program/model/pcode/PcodeOp.java | 34 +- .../program/model/pcode/SequenceNumber.java | 25 +- .../program/model/pcode/SymbolEntry.java | 28 +- .../program/model/pcode/UnionFacetSymbol.java | 16 +- .../ghidra/program/model/pcode/Varnode.java | 10 +- .../ghidra/program/model/pcode/XmlDecode.java | 2 + .../ghidra/program/model/pcode/XmlEncode.java | 172 ++++ .../util/LanguageTranslatorAdapter.java | 4 +- .../inject/InjectPayloadDexParameters.java | 13 +- .../InjectPayloadJavaParameters.java | 13 +- 96 files changed, 2701 insertions(+), 2484 deletions(-) create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc index 8f75e8fc5b..8245f76d64 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc @@ -29,46 +29,48 @@ vector ArchitectureCapability::thelist; const uint4 ArchitectureCapability::majorversion = 4; const uint4 ArchitectureCapability::minorversion = 1; -AttributeId ATTRIB_ADJUSTVMA = AttributeId("adjustvma",30); -AttributeId ATTRIB_ENABLE = AttributeId("enable",31); -AttributeId ATTRIB_GROUP = AttributeId("group",32); -AttributeId ATTRIB_GROWTH = AttributeId("growth",33); -AttributeId ATTRIB_LOADERSYMBOLS = AttributeId("loadersymbols",34); -AttributeId ATTRIB_PARENT = AttributeId("parent",35); -AttributeId ATTRIB_REGISTER = AttributeId("register",36); -AttributeId ATTRIB_REVERSEJUSTIFY = AttributeId("reversejustify",37); -AttributeId ATTRIB_SIGNEXT = AttributeId("signext",38); -AttributeId ATTRIB_STYLE = AttributeId("style",39); +AttributeId ATTRIB_ADJUSTVMA = AttributeId("adjustvma",103); +AttributeId ATTRIB_ENABLE = AttributeId("enable",104); +AttributeId ATTRIB_GROUP = AttributeId("group",105); +AttributeId ATTRIB_GROWTH = AttributeId("growth",106); +AttributeId ATTRIB_KEY = AttributeId("key",107); +AttributeId ATTRIB_LOADERSYMBOLS = AttributeId("loadersymbols",108); +AttributeId ATTRIB_PARENT = AttributeId("parent",109); +AttributeId ATTRIB_REGISTER = AttributeId("register",110); +AttributeId ATTRIB_REVERSEJUSTIFY = AttributeId("reversejustify",111); +AttributeId ATTRIB_SIGNEXT = AttributeId("signext",112); +AttributeId ATTRIB_STYLE = AttributeId("style",113); -ElementId ELEM_ADDRESS_SHIFT_AMOUNT = ElementId("address_shift_amount",17); -ElementId ELEM_AGGRESSIVETRIM = ElementId("aggressivetrim",18); -ElementId ELEM_COMPILER_SPEC = ElementId("compiler_spec",19); -ElementId ELEM_DATA_SPACE = ElementId("data_space",20); -ElementId ELEM_DEFAULT_MEMORY_BLOCKS = ElementId("default_memory_blocks",21); -ElementId ELEM_DEFAULT_PROTO = ElementId("default_proto",22); -ElementId ELEM_DEFAULT_SYMBOLS = ElementId("default_symbols",23); -ElementId ELEM_EVAL_CALLED_PROTOTYPE = ElementId("eval_called_prototype",24); -ElementId ELEM_EVAL_CURRENT_PROTOTYPE = ElementId("eval_current_prototype",25); -ElementId ELEM_EXPERIMENTAL_RULES = ElementId("experimental_rules",26); -ElementId ELEM_FLOWOVERRIDELIST = ElementId("flowoverridelist",27); -ElementId ELEM_FUNCPTR = ElementId("funcptr",28); -ElementId ELEM_GLOBAL = ElementId("global",29); -ElementId ELEM_INCIDENTALCOPY = ElementId("incidentalcopy",30); -ElementId ELEM_INFERPTRBOUNDS = ElementId("inferptrbounds",31); -ElementId ELEM_MODELALIAS = ElementId("modelalias",32); -ElementId ELEM_NOHIGHPTR = ElementId("nohighptr",33); -ElementId ELEM_PROCESSOR_SPEC = ElementId("processor_spec",34); -ElementId ELEM_PROGRAMCOUNTER = ElementId("programcounter",35); -ElementId ELEM_PROPERTIES = ElementId("properties",36); -ElementId ELEM_READONLY = ElementId("readonly",37); -ElementId ELEM_REGISTER_DATA = ElementId("register_data",38); -ElementId ELEM_RULE = ElementId("rule",39); -ElementId ELEM_SAVE_STATE = ElementId("save_state",40); -ElementId ELEM_SEGMENTED_ADDRESS = ElementId("segmented_address",41); -ElementId ELEM_SPACEBASE = ElementId("spacebase",42); -ElementId ELEM_SPECEXTENSIONS = ElementId("specextensions",43); -ElementId ELEM_STACKPOINTER = ElementId("stackpointer",44); -ElementId ELEM_VOLATILE = ElementId("volatile",45); +ElementId ELEM_ADDRESS_SHIFT_AMOUNT = ElementId("address_shift_amount",130); +ElementId ELEM_AGGRESSIVETRIM = ElementId("aggressivetrim",131); +ElementId ELEM_COMPILER_SPEC = ElementId("compiler_spec",132); +ElementId ELEM_DATA_SPACE = ElementId("data_space",133); +ElementId ELEM_DEFAULT_MEMORY_BLOCKS = ElementId("default_memory_blocks",134); +ElementId ELEM_DEFAULT_PROTO = ElementId("default_proto",135); +ElementId ELEM_DEFAULT_SYMBOLS = ElementId("default_symbols",136); +ElementId ELEM_EVAL_CALLED_PROTOTYPE = ElementId("eval_called_prototype",137); +ElementId ELEM_EVAL_CURRENT_PROTOTYPE = ElementId("eval_current_prototype",138); +ElementId ELEM_EXPERIMENTAL_RULES = ElementId("experimental_rules",139); +ElementId ELEM_FLOWOVERRIDELIST = ElementId("flowoverridelist",140); +ElementId ELEM_FUNCPTR = ElementId("funcptr",141); +ElementId ELEM_GLOBAL = ElementId("global",142); +ElementId ELEM_INCIDENTALCOPY = ElementId("incidentalcopy",143); +ElementId ELEM_INFERPTRBOUNDS = ElementId("inferptrbounds",144); +ElementId ELEM_MODELALIAS = ElementId("modelalias",145); +ElementId ELEM_NOHIGHPTR = ElementId("nohighptr",146); +ElementId ELEM_PROCESSOR_SPEC = ElementId("processor_spec",147); +ElementId ELEM_PROGRAMCOUNTER = ElementId("programcounter",148); +ElementId ELEM_PROPERTIES = ElementId("properties",149); +ElementId ELEM_PROPERTY = ElementId("property",150); +ElementId ELEM_READONLY = ElementId("readonly",151); +ElementId ELEM_REGISTER_DATA = ElementId("register_data",152); +ElementId ELEM_RULE = ElementId("rule",153); +ElementId ELEM_SAVE_STATE = ElementId("save_state",154); +ElementId ELEM_SEGMENTED_ADDRESS = ElementId("segmented_address",155); +ElementId ELEM_SPACEBASE = ElementId("spacebase",156); +ElementId ELEM_SPECEXTENSIONS = ElementId("specextensions",157); +ElementId ELEM_STACKPOINTER = ElementId("stackpointer",158); +ElementId ELEM_VOLATILE = ElementId("volatile",159); /// This builds a list of just the ArchitectureCapability extensions void ArchitectureCapability::initialize(void) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh index 6bc9772fbd..5951ad871f 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh @@ -65,6 +65,7 @@ extern AttributeId ATTRIB_ADJUSTVMA; ///< Marshaling attribute "adjustvma" extern AttributeId ATTRIB_ENABLE; ///< Marshaling attribute "enable" extern AttributeId ATTRIB_GROUP; ///< Marshaling attribute "group" extern AttributeId ATTRIB_GROWTH; ///< Marshaling attribute "growth" +extern AttributeId ATTRIB_KEY; ///< Marshaling attribute "key" extern AttributeId ATTRIB_LOADERSYMBOLS; ///< Marshaling attribute "loadersymbols" extern AttributeId ATTRIB_PARENT; ///< Marshaling attribute "parent" extern AttributeId ATTRIB_REGISTER; ///< Marshaling attribute "register" @@ -92,6 +93,7 @@ extern ElementId ELEM_NOHIGHPTR; ///< Marshaling element \ extern ElementId ELEM_PROCESSOR_SPEC; ///< Marshaling element \ extern ElementId ELEM_PROGRAMCOUNTER; ///< Marshaling element \ extern ElementId ELEM_PROPERTIES; ///< Marshaling element \ +extern ElementId ELEM_PROPERTY; ///< Marshaling element \ extern ElementId ELEM_READONLY; ///< Marshaling element \ extern ElementId ELEM_REGISTER_DATA; ///< Marshaling element \ extern ElementId ELEM_RULE; ///< Marshaling element \ diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/bfd_arch.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/bfd_arch.cc index 4660b988d2..b9a495500b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/bfd_arch.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/bfd_arch.cc @@ -19,7 +19,7 @@ // Constructing this object registers capability BfdArchitectureCapability BfdArchitectureCapability::bfdArchitectureCapability; -ElementId ELEM_BFD_SAVEFILE = ElementId("bfd_savefile",46); +ElementId ELEM_BFD_SAVEFILE = ElementId("bfd_savefile",238); BfdArchitectureCapability::BfdArchitectureCapability(void) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/block.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/block.cc index 2d6e823bad..5584dbf4d5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/block.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/block.cc @@ -17,16 +17,16 @@ #include "block.hh" #include "funcdata.hh" -AttributeId ATTRIB_ALTINDEX = AttributeId("altindex",40); -AttributeId ATTRIB_DEPTH = AttributeId("depth",41); -AttributeId ATTRIB_END = AttributeId("end",42); -AttributeId ATTRIB_OPCODE = AttributeId("opcode",43); -AttributeId ATTRIB_REV = AttributeId("rev",44); +AttributeId ATTRIB_ALTINDEX = AttributeId("altindex",75); +AttributeId ATTRIB_DEPTH = AttributeId("depth",76); +AttributeId ATTRIB_END = AttributeId("end",77); +AttributeId ATTRIB_OPCODE = AttributeId("opcode",78); +AttributeId ATTRIB_REV = AttributeId("rev",79); -ElementId ELEM_BHEAD = ElementId("bhead",47); -ElementId ELEM_BLOCK = ElementId("block",48); -ElementId ELEM_BLOCKEDGE = ElementId("blockedge",49); -ElementId ELEM_EDGE = ElementId("edge",50); +ElementId ELEM_BHEAD = ElementId("bhead",102); +ElementId ELEM_BLOCK = ElementId("block",103); +ElementId ELEM_BLOCKEDGE = ElementId("blockedge",104); +ElementId ELEM_EDGE = ElementId("edge",105); /// The edge is saved assuming we already know what block we are in. /// \param encoder is the stream encoder diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/callgraph.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/callgraph.cc index 2dd84a5b7b..26406c2880 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/callgraph.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/callgraph.cc @@ -16,8 +16,8 @@ #include "callgraph.hh" #include "funcdata.hh" -ElementId ELEM_CALLGRAPH = ElementId("callgraph",51); -ElementId ELEM_NODE = ElementId("node",52); +ElementId ELEM_CALLGRAPH = ElementId("callgraph",226); +ElementId ELEM_NODE = ElementId("node",227); void CallGraphEdge::encode(Encoder &encoder) const diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/comment.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/comment.cc index 14754a3eb6..b5bc0a16da 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/comment.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/comment.cc @@ -16,9 +16,9 @@ #include "comment.hh" #include "funcdata.hh" -ElementId ELEM_COMMENT = ElementId("comment",53); -ElementId ELEM_COMMENTDB = ElementId("commentdb",54); -ElementId ELEM_TEXT = ElementId("text",55); +ElementId ELEM_COMMENT = ElementId("comment",86); +ElementId ELEM_COMMENTDB = ElementId("commentdb",87); +ElementId ELEM_TEXT = ElementId("text",88); /// \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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/cpool.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/cpool.cc index 56041a3dfa..42b1531add 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/cpool.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/cpool.cc @@ -15,15 +15,15 @@ */ #include "cpool.hh" -AttributeId ATTRIB_A = AttributeId("a",45); -AttributeId ATTRIB_B = AttributeId("b",46); -AttributeId ATTRIB_LENGTH = AttributeId("length",47); -AttributeId ATTRIB_TAG = AttributeId("tag",48); +AttributeId ATTRIB_A = AttributeId("a",80); +AttributeId ATTRIB_B = AttributeId("b",81); +AttributeId ATTRIB_LENGTH = AttributeId("length",82); +AttributeId ATTRIB_TAG = AttributeId("tag",83); -ElementId ELEM_CONSTANTPOOL = ElementId("constantpool",56); -ElementId ELEM_CPOOLREC = ElementId("cpoolrec",57); -ElementId ELEM_REF = ElementId("ref",58); -ElementId ELEM_TOKEN = ElementId("token",59); +ElementId ELEM_CONSTANTPOOL = ElementId("constantpool",109); +ElementId ELEM_CPOOLREC = ElementId("cpoolrec",110); +ElementId ELEM_REF = ElementId("ref",111); +ElementId ELEM_TOKEN = ElementId("token",112); /// Encode the constant pool object description as a \ element. /// \param encoder is the stream encoder diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc index c63556de9c..28c7dbf36b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc @@ -18,27 +18,27 @@ #include "crc32.hh" #include -AttributeId ATTRIB_CAT = AttributeId("cat",49); -AttributeId ATTRIB_FIELD = AttributeId("field",50); -AttributeId ATTRIB_MERGE = AttributeId("merge",51); -AttributeId ATTRIB_SCOPEIDBYNAME = AttributeId("scopeidbyname",52); -AttributeId ATTRIB_VOLATILE = AttributeId("volatile",53); +AttributeId ATTRIB_CAT = AttributeId("cat",61); +AttributeId ATTRIB_FIELD = AttributeId("field",62); +AttributeId ATTRIB_MERGE = AttributeId("merge",63); +AttributeId ATTRIB_SCOPEIDBYNAME = AttributeId("scopeidbyname",64); +AttributeId ATTRIB_VOLATILE = AttributeId("volatile",65); -ElementId ELEM_COLLISION = ElementId("collision",60); -ElementId ELEM_DB = ElementId("db",61); -ElementId ELEM_EQUATESYMBOL = ElementId("equatesymbol",62); -ElementId ELEM_EXTERNREFSYMBOL = ElementId("externrefsymbol",63); -ElementId ELEM_FACETSYMBOL = ElementId("facetsymbol",64); -ElementId ELEM_FUNCTIONSHELL = ElementId("functionshell",65); -ElementId ELEM_HASH = ElementId("hash",66); -ElementId ELEM_HOLE = ElementId("hole",67); -ElementId ELEM_LABELSYM = ElementId("labelsym",68); -ElementId ELEM_MAPSYM = ElementId("mapsym",69); -ElementId ELEM_PARENT = ElementId("parent",70); -ElementId ELEM_PROPERTY_CHANGEPOINT = ElementId("property_changepoint",71); -ElementId ELEM_RANGEEQUALSSYMBOLS = ElementId("rangeequalssymbols",72); -ElementId ELEM_SCOPE = ElementId("scope",73); -ElementId ELEM_SYMBOLLIST = ElementId("symbollist",74); +ElementId ELEM_COLLISION = ElementId("collision",67); +ElementId ELEM_DB = ElementId("db",68); +ElementId ELEM_EQUATESYMBOL = ElementId("equatesymbol",69); +ElementId ELEM_EXTERNREFSYMBOL = ElementId("externrefsymbol",70); +ElementId ELEM_FACETSYMBOL = ElementId("facetsymbol",71); +ElementId ELEM_FUNCTIONSHELL = ElementId("functionshell",72); +ElementId ELEM_HASH = ElementId("hash",73); +ElementId ELEM_HOLE = ElementId("hole",74); +ElementId ELEM_LABELSYM = ElementId("labelsym",75); +ElementId ELEM_MAPSYM = ElementId("mapsym",76); +ElementId ELEM_PARENT = ElementId("parent",77); +ElementId ELEM_PROPERTY_CHANGEPOINT = ElementId("property_changepoint",78); +ElementId ELEM_RANGEEQUALSSYMBOLS = ElementId("rangeequalssymbols",79); +ElementId ELEM_SCOPE = ElementId("scope",80); +ElementId ELEM_SYMBOLLIST = ElementId("symbollist",81); uint8 Symbol::ID_BASE = 0x4000000000000000L; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc index 4d66dfd548..0526ed04c7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc @@ -16,37 +16,37 @@ #include "fspec.hh" #include "funcdata.hh" -AttributeId ATTRIB_CUSTOM = AttributeId("custom",54); -AttributeId ATTRIB_DOTDOTDOT = AttributeId("dotdotdot",55); -AttributeId ATTRIB_EXTENSION = AttributeId("extension",56); -AttributeId ATTRIB_HASTHIS = AttributeId("hasthis",57); -AttributeId ATTRIB_INLINE = AttributeId("inline",58); -AttributeId ATTRIB_KILLEDBYCALL = AttributeId("killedbycall",59); -AttributeId ATTRIB_MAXSIZE = AttributeId("maxsize",60); -AttributeId ATTRIB_MINSIZE = AttributeId("minsize",61); -AttributeId ATTRIB_MODELLOCK = AttributeId("modellock",62); -AttributeId ATTRIB_NORETURN = AttributeId("noreturn",63); -AttributeId ATTRIB_POINTERMAX = AttributeId("pointermax",64); -AttributeId ATTRIB_SEPARATEFLOAT = AttributeId("separatefloat",65); -AttributeId ATTRIB_STACKSHIFT = AttributeId("stackshift",66); -AttributeId ATTRIB_STRATEGY = AttributeId("strategy",67); -AttributeId ATTRIB_THISBEFORERETPOINTER = AttributeId("thisbeforeretpointer",68); -AttributeId ATTRIB_VOIDLOCK = AttributeId("voidlock",69); +AttributeId ATTRIB_CUSTOM = AttributeId("custom",114); +AttributeId ATTRIB_DOTDOTDOT = AttributeId("dotdotdot",115); +AttributeId ATTRIB_EXTENSION = AttributeId("extension",116); +AttributeId ATTRIB_HASTHIS = AttributeId("hasthis",117); +AttributeId ATTRIB_INLINE = AttributeId("inline",118); +AttributeId ATTRIB_KILLEDBYCALL = AttributeId("killedbycall",119); +AttributeId ATTRIB_MAXSIZE = AttributeId("maxsize",120); +AttributeId ATTRIB_MINSIZE = AttributeId("minsize",121); +AttributeId ATTRIB_MODELLOCK = AttributeId("modellock",122); +AttributeId ATTRIB_NORETURN = AttributeId("noreturn",123); +AttributeId ATTRIB_POINTERMAX = AttributeId("pointermax",124); +AttributeId ATTRIB_SEPARATEFLOAT = AttributeId("separatefloat",125); +AttributeId ATTRIB_STACKSHIFT = AttributeId("stackshift",126); +AttributeId ATTRIB_STRATEGY = AttributeId("strategy",127); +AttributeId ATTRIB_THISBEFORERETPOINTER = AttributeId("thisbeforeretpointer",128); +AttributeId ATTRIB_VOIDLOCK = AttributeId("voidlock",129); -ElementId ELEM_GROUP = ElementId("group",75); -ElementId ELEM_INTERNALLIST = ElementId("internallist",76); -ElementId ELEM_KILLEDBYCALL = ElementId("killedbycall",77); -ElementId ELEM_LIKELYTRASH = ElementId("likelytrash",78); -ElementId ELEM_LOCALRANGE = ElementId("localrange",79); -ElementId ELEM_MODEL = ElementId("model",80); -ElementId ELEM_PARAM = ElementId("param",81); -ElementId ELEM_PARAMRANGE = ElementId("paramrange",82); -ElementId ELEM_PENTRY = ElementId("pentry",83); -ElementId ELEM_PROTOTYPE = ElementId("prototype",84); -ElementId ELEM_RESOLVEPROTOTYPE = ElementId("resolveprototype",85); -ElementId ELEM_RETPARAM = ElementId("retparam",86); -ElementId ELEM_RETURNSYM = ElementId("returnsym",87); -ElementId ELEM_UNAFFECTED = ElementId("unaffected",88); +ElementId ELEM_GROUP = ElementId("group",160); +ElementId ELEM_INTERNALLIST = ElementId("internallist",161); +ElementId ELEM_KILLEDBYCALL = ElementId("killedbycall",162); +ElementId ELEM_LIKELYTRASH = ElementId("likelytrash",163); +ElementId ELEM_LOCALRANGE = ElementId("localrange",164); +ElementId ELEM_MODEL = ElementId("model",165); +ElementId ELEM_PARAM = ElementId("param",166); +ElementId ELEM_PARAMRANGE = ElementId("paramrange",167); +ElementId ELEM_PENTRY = ElementId("pentry",168); +ElementId ELEM_PROTOTYPE = ElementId("prototype",169); +ElementId ELEM_RESOLVEPROTOTYPE = ElementId("resolveprototype",170); +ElementId ELEM_RETPARAM = ElementId("retparam",171); +ElementId ELEM_RETURNSYM = ElementId("returnsym",172); +ElementId ELEM_UNAFFECTED = ElementId("unaffected",173); /// \brief Find a ParamEntry matching the given storage Varnode /// diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc index 13dbbc7cf1..02229662d5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc @@ -15,13 +15,13 @@ */ #include "funcdata.hh" -AttributeId ATTRIB_NOCODE = AttributeId("nocode",70); +AttributeId ATTRIB_NOCODE = AttributeId("nocode",84); -ElementId ELEM_AST = ElementId("ast",89); -ElementId ELEM_FUNCTION = ElementId("function",90); -ElementId ELEM_HIGHLIST = ElementId("highlist",91); -ElementId ELEM_JUMPTABLELIST = ElementId("jumptablelist",92); -ElementId ELEM_VARNODES = ElementId("varnodes",93); +ElementId ELEM_AST = ElementId("ast",115); +ElementId ELEM_FUNCTION = ElementId("function",116); +ElementId ELEM_HIGHLIST = ElementId("highlist",117); +ElementId ELEM_JUMPTABLELIST = ElementId("jumptablelist",118); +ElementId ELEM_VARNODES = ElementId("varnodes",119); /// \param nm is the (base) name of the function /// \param scope is Symbol scope associated with the function diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc index 67fe5e9652..32a721b9b9 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc @@ -63,7 +63,7 @@ void connect_to_console(Funcdata *fd) #endif -ElementId ELEM_DOC = ElementId("doc",218); +ElementId ELEM_DOC = ElementId("doc",229); vector archlist; // List of architectures currently running diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/globalcontext.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/globalcontext.cc index 3794724fdd..15badbad3d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/globalcontext.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/globalcontext.cc @@ -15,13 +15,13 @@ */ #include "globalcontext.hh" -ElementId ELEM_CONTEXT_DATA = ElementId("context_data",94); -ElementId ELEM_CONTEXT_POINTS = ElementId("context_points",95); -ElementId ELEM_CONTEXT_POINTSET = ElementId("context_pointset",96); -ElementId ELEM_CONTEXT_SET = ElementId("context_set",97); -ElementId ELEM_SET = ElementId("set",98); -ElementId ELEM_TRACKED_POINTSET = ElementId("tracked_pointset",99); -ElementId ELEM_TRACKED_SET = ElementId("tracked_set",100); +ElementId ELEM_CONTEXT_DATA = ElementId("context_data",120); +ElementId ELEM_CONTEXT_POINTS = ElementId("context_points",121); +ElementId ELEM_CONTEXT_POINTSET = ElementId("context_pointset",122); +ElementId ELEM_CONTEXT_SET = ElementId("context_set",123); +ElementId ELEM_SET = ElementId("set",124); +ElementId ELEM_TRACKED_POINTSET = ElementId("tracked_pointset",125); +ElementId ELEM_TRACKED_SET = ElementId("tracked_set",126); /// 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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/jumptable.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/jumptable.cc index 919bb14206..63126e06e3 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/jumptable.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/jumptable.cc @@ -17,16 +17,16 @@ #include "emulate.hh" #include "flow.hh" -AttributeId ATTRIB_LABEL = AttributeId("label",71); -AttributeId ATTRIB_NUM = AttributeId("num",72); +AttributeId ATTRIB_LABEL = AttributeId("label",131); +AttributeId ATTRIB_NUM = AttributeId("num",132); -ElementId ELEM_BASICOVERRIDE = ElementId("basicoverride",101); -ElementId ELEM_DEST = ElementId("dest",102); -ElementId ELEM_JUMPTABLE = ElementId("jumptable",103); -ElementId ELEM_LOADTABLE = ElementId("loadtable",104); -ElementId ELEM_NORMADDR = ElementId("normaddr",105); -ElementId ELEM_NORMHASH = ElementId("normhash",106); -ElementId ELEM_STARTVAL = ElementId("startval",107); +ElementId ELEM_BASICOVERRIDE = ElementId("basicoverride",211); +ElementId ELEM_DEST = ElementId("dest",212); +ElementId ELEM_JUMPTABLE = ElementId("jumptable",213); +ElementId ELEM_LOADTABLE = ElementId("loadtable",214); +ElementId ELEM_NORMADDR = ElementId("normaddr",215); +ElementId ELEM_NORMHASH = ElementId("normhash",216); +ElementId ELEM_STARTVAL = ElementId("startval",217); /// \param encoder is the stream encoder void LoadTable::encode(Encoder &encoder) const diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_xml.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_xml.cc index de62d2d341..b7a9a30c48 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_xml.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/loadimage_xml.cc @@ -16,10 +16,10 @@ #include "loadimage_xml.hh" #include "translate.hh" -AttributeId ATTRIB_ARCH = AttributeId("arch",73); +AttributeId ATTRIB_ARCH = AttributeId("arch",135); -ElementId ELEM_BINARYIMAGE = ElementId("binaryimage",108); -ElementId ELEM_BYTECHUNK = ElementId("bytechunk",109); +ElementId ELEM_BINARYIMAGE = ElementId("binaryimage",230); +ElementId ELEM_BYTECHUNK = ElementId("bytechunk",231); /// \param f is the (path to the) underlying XML file /// \param el is the parsed form of the file diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc index 94c4698f15..17a9c11ffb 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc @@ -500,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24); AttributeId ATTRIB_VALUE = AttributeId("value",25); 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_INPUT = ElementId("input",2); @@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8); ElementId ELEM_VALUE = ElementId("value",9); 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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc index e77a415603..b4f8a3f8ed 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc @@ -16,7 +16,8 @@ #include "op.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"; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh index c0f93456c4..2d29977583 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh @@ -21,6 +21,7 @@ #include "typeop.hh" extern ElementId ELEM_IOP; ///< Marshaling element \ +extern ElementId ELEM_UNIMPL; ///< Marshaling element \ /// \brief Space for storing internal PcodeOp pointers as addresses /// diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc index b6c2417719..cd7aaa4c35 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc @@ -18,43 +18,43 @@ #include "flow.hh" #include "printc.hh" -ElementId ELEM_ALIASBLOCK = ElementId("aliasblock",111); -ElementId ELEM_ALLOWCONTEXTSET = ElementId("allowcontextset",112); -ElementId ELEM_ANALYZEFORLOOPS = ElementId("analyzeforloops",113); -ElementId ELEM_COMMENTHEADER = ElementId("commentheader",114); -ElementId ELEM_COMMENTINDENT = ElementId("commentindent",115); -ElementId ELEM_COMMENTINSTRUCTION = ElementId("commentinstruction",116); -ElementId ELEM_COMMENTSTYLE = ElementId("commentstyle",117); -ElementId ELEM_CONVENTIONPRINTING = ElementId("conventionprinting",118); -ElementId ELEM_CURRENTACTION = ElementId("currentaction",119); -ElementId ELEM_DEFAULTPROTOTYPE = ElementId("defaultprototype",120); -ElementId ELEM_ERRORREINTERPRETED = ElementId("errorreinterpreted",121); -ElementId ELEM_ERRORTOOMANYINSTRUCTIONS = ElementId("errortoomanyinstructions",122); -ElementId ELEM_ERRORUNIMPLEMENTED = ElementId("errorunimplemented",123); -ElementId ELEM_EXTRAPOP = ElementId("extrapop",124); -ElementId ELEM_IGNOREUNIMPLEMENTED = ElementId("ignoreunimplemented",125); -ElementId ELEM_INDENTINCREMENT = ElementId("indentincrement",126); -ElementId ELEM_INFERCONSTPTR = ElementId("inferconstptr",127); -ElementId ELEM_INLINE = ElementId("inline",128); -ElementId ELEM_INPLACEOPS = ElementId("inplaceops",129); -ElementId ELEM_INTEGERFORMAT = ElementId("integerformat",130); -ElementId ELEM_JUMPLOAD = ElementId("jumpload",131); -ElementId ELEM_MAXINSTRUCTION = ElementId("maxinstruction",132); -ElementId ELEM_MAXLINEWIDTH = ElementId("maxlinewidth",133); -ElementId ELEM_NAMESPACESTRATEGY = ElementId("namespacestrategy",134); -ElementId ELEM_NOCASTPRINTING = ElementId("nocastprinting",135); -ElementId ELEM_NORETURN = ElementId("noreturn",136); -ElementId ELEM_NULLPRINTING = ElementId("nullprinting",137); -ElementId ELEM_OPTIONSLIST = ElementId("optionslist",138); -ElementId ELEM_PARAM1 = ElementId("param1",139); -ElementId ELEM_PARAM2 = ElementId("param2",140); -ElementId ELEM_PARAM3 = ElementId("param3",141); -ElementId ELEM_PROTOEVAL = ElementId("protoeval",142); -ElementId ELEM_SETACTION = ElementId("setaction",143); -ElementId ELEM_SETLANGUAGE = ElementId("setlanguage",144); -ElementId ELEM_STRUCTALIGN = ElementId("structalign",145); -ElementId ELEM_TOGGLERULE = ElementId("togglerule",146); -ElementId ELEM_WARNING = ElementId("warning",147); +ElementId ELEM_ALIASBLOCK = ElementId("aliasblock",174); +ElementId ELEM_ALLOWCONTEXTSET = ElementId("allowcontextset",175); +ElementId ELEM_ANALYZEFORLOOPS = ElementId("analyzeforloops",176); +ElementId ELEM_COMMENTHEADER = ElementId("commentheader",177); +ElementId ELEM_COMMENTINDENT = ElementId("commentindent",178); +ElementId ELEM_COMMENTINSTRUCTION = ElementId("commentinstruction",179); +ElementId ELEM_COMMENTSTYLE = ElementId("commentstyle",180); +ElementId ELEM_CONVENTIONPRINTING = ElementId("conventionprinting",181); +ElementId ELEM_CURRENTACTION = ElementId("currentaction",182); +ElementId ELEM_DEFAULTPROTOTYPE = ElementId("defaultprototype",183); +ElementId ELEM_ERRORREINTERPRETED = ElementId("errorreinterpreted",184); +ElementId ELEM_ERRORTOOMANYINSTRUCTIONS = ElementId("errortoomanyinstructions",185); +ElementId ELEM_ERRORUNIMPLEMENTED = ElementId("errorunimplemented",186); +ElementId ELEM_EXTRAPOP = ElementId("extrapop",187); +ElementId ELEM_IGNOREUNIMPLEMENTED = ElementId("ignoreunimplemented",188); +ElementId ELEM_INDENTINCREMENT = ElementId("indentincrement",189); +ElementId ELEM_INFERCONSTPTR = ElementId("inferconstptr",190); +ElementId ELEM_INLINE = ElementId("inline",191); +ElementId ELEM_INPLACEOPS = ElementId("inplaceops",192); +ElementId ELEM_INTEGERFORMAT = ElementId("integerformat",193); +ElementId ELEM_JUMPLOAD = ElementId("jumpload",194); +ElementId ELEM_MAXINSTRUCTION = ElementId("maxinstruction",195); +ElementId ELEM_MAXLINEWIDTH = ElementId("maxlinewidth",196); +ElementId ELEM_NAMESPACESTRATEGY = ElementId("namespacestrategy",197); +ElementId ELEM_NOCASTPRINTING = ElementId("nocastprinting",198); +ElementId ELEM_NORETURN = ElementId("noreturn",199); +ElementId ELEM_NULLPRINTING = ElementId("nullprinting",200); +ElementId ELEM_OPTIONSLIST = ElementId("optionslist",201); +ElementId ELEM_PARAM1 = ElementId("param1",202); +ElementId ELEM_PARAM2 = ElementId("param2",203); +ElementId ELEM_PARAM3 = ElementId("param3",204); +ElementId ELEM_PROTOEVAL = ElementId("protoeval",205); +ElementId ELEM_SETACTION = ElementId("setaction",206); +ElementId ELEM_SETLANGUAGE = ElementId("setlanguage",207); +ElementId ELEM_STRUCTALIGN = ElementId("structalign",208); +ElementId ELEM_TOGGLERULE = ElementId("togglerule",209); +ElementId ELEM_WARNING = ElementId("warning",210); /// If the parameter is "on" return \b true, if "off" return \b false. /// Any other value causes an exception. diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc index e1fb09aca5..f64cb03ca6 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc @@ -16,13 +16,13 @@ #include "override.hh" #include "funcdata.hh" -ElementId ELEM_DEADCODEDELAY = ElementId("deadcodedelay",148); -ElementId ELEM_FLOW = ElementId("flow",149); -ElementId ELEM_FORCEGOTO = ElementId("forcegoto",150); -ElementId ELEM_INDIRECTOVERRIDE = ElementId("indirectoverride",151); -ElementId ELEM_MULTISTAGEJUMP = ElementId("multistagejump",152); -ElementId ELEM_OVERRIDE = ElementId("override",153); -ElementId ELEM_PROTOOVERRIDE = ElementId("protooverride",154); +ElementId ELEM_DEADCODEDELAY = ElementId("deadcodedelay",218); +ElementId ELEM_FLOW = ElementId("flow",219); +ElementId ELEM_FORCEGOTO = ElementId("forcegoto",220); +ElementId ELEM_INDIRECTOVERRIDE = ElementId("indirectoverride",221); +ElementId ELEM_MULTISTAGEJUMP = ElementId("multistagejump",222); +ElementId ELEM_OVERRIDE = ElementId("override",223); +ElementId ELEM_PROTOOVERRIDE = ElementId("protooverride",224); void Override::clear(void) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/paramid.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/paramid.cc index 05a1900c6c..093a8b232d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/paramid.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/paramid.cc @@ -15,9 +15,9 @@ */ #include "paramid.hh" -ElementId ELEM_PARAMMEASURES = ElementId("parammeasures",155); -ElementId ELEM_PROTO = ElementId("proto",156); -ElementId ELEM_RANK = ElementId("rank",157); +ElementId ELEM_PARAMMEASURES = ElementId("parammeasures",106); +ElementId ELEM_PROTO = ElementId("proto",107); +ElementId ELEM_RANK = ElementId("rank",108); // NOTES FROM 20121206 W/Decompiler-Man // direct reads is for all opcodes, with special for these: diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeinject.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeinject.cc index d12c32679b..7a317f47fb 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeinject.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeinject.cc @@ -16,25 +16,25 @@ #include "pcodeinject.hh" #include "architecture.hh" -AttributeId ATTRIB_DYNAMIC = AttributeId("dynamic",74); -AttributeId ATTRIB_INCIDENTALCOPY = AttributeId("incidentalcopy",75); -AttributeId ATTRIB_INJECT = AttributeId("inject",76); -AttributeId ATTRIB_PARAMSHIFT = AttributeId("paramshift",77); -AttributeId ATTRIB_TARGETOP = AttributeId("targetop",78); +AttributeId ATTRIB_DYNAMIC = AttributeId("dynamic",70); +AttributeId ATTRIB_INCIDENTALCOPY = AttributeId("incidentalcopy",71); +AttributeId ATTRIB_INJECT = AttributeId("inject",72); +AttributeId ATTRIB_PARAMSHIFT = AttributeId("paramshift",73); +AttributeId ATTRIB_TARGETOP = AttributeId("targetop",74); -ElementId ELEM_ADDR_PCODE = ElementId("addr_pcode",158); -ElementId ELEM_BODY = ElementId("body",159); -ElementId ELEM_CALLFIXUP = ElementId("callfixup",160); -ElementId ELEM_CALLOTHERFIXUP = ElementId("callotherfixup",161); -ElementId ELEM_CASE_PCODE = ElementId("case_pcode",162); -ElementId ELEM_CONTEXT = ElementId("context",163); -ElementId ELEM_DEFAULT_PCODE = ElementId("default_pcode",164); -ElementId ELEM_INJECT = ElementId("inject",165); -ElementId ELEM_INJECTDEBUG = ElementId("injectdebug",166); -ElementId ELEM_INST = ElementId("inst",167); -ElementId ELEM_PAYLOAD = ElementId("payload",168); -ElementId ELEM_PCODE = ElementId("pcode",169); -ElementId ELEM_SIZE_PCODE = ElementId("size_pcode",170); +ElementId ELEM_ADDR_PCODE = ElementId("addr_pcode",89); +ElementId ELEM_BODY = ElementId("body",90); +ElementId ELEM_CALLFIXUP = ElementId("callfixup",91); +ElementId ELEM_CALLOTHERFIXUP = ElementId("callotherfixup",92); +ElementId ELEM_CASE_PCODE = ElementId("case_pcode",93); +ElementId ELEM_CONTEXT = ElementId("context",94); +ElementId ELEM_DEFAULT_PCODE = ElementId("default_pcode",95); +ElementId ELEM_INJECT = ElementId("inject",96); +ElementId ELEM_INJECTDEBUG = ElementId("injectdebug",97); +ElementId ELEM_INST = ElementId("inst",98); +ElementId ELEM_PAYLOAD = ElementId("payload",99); +ElementId ELEM_PCODE = ElementId("pcode",100); +ElementId ELEM_SIZE_PCODE = ElementId("size_pcode",101); /// \brief Parse an \ or \ element describing an injection parameter /// diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prefersplit.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/prefersplit.cc index aa20a71f18..6359418856 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/prefersplit.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prefersplit.cc @@ -16,7 +16,7 @@ #include "prefersplit.hh" #include "funcdata.hh" -ElementId ELEM_PREFERSPLIT = ElementId("prefersplit",171); +ElementId ELEM_PREFERSPLIT = ElementId("prefersplit",225); bool PreferSplitRecord::operator<(const PreferSplitRecord &op2) const diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc index 90fd8c14fd..00f891bfae 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc @@ -16,24 +16,24 @@ #include "prettyprint.hh" #include "funcdata.hh" -AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",136); -AttributeId ATTRIB_CLOSE = AttributeId("close",137); -AttributeId ATTRIB_COLOR = AttributeId("color",138); -AttributeId ATTRIB_INDENT = AttributeId("indent",139); -AttributeId ATTRIB_OFF = AttributeId("off",140); -AttributeId ATTRIB_OPEN = AttributeId("open",141); -AttributeId ATTRIB_OPREF = AttributeId("opref",142); -AttributeId ATTRIB_VARREF = AttributeId("varref",143); -ElementId ELEM_BREAK = ElementId("break",208); -ElementId ELEM_CLANG_DOCUMENT = ElementId("clang_document",209); -ElementId ELEM_FUNCNAME = ElementId("funcname",210); -ElementId ELEM_FUNCPROTO = ElementId("funcproto",211); -ElementId ELEM_LABEL = ElementId("label",212); -ElementId ELEM_RETURN_TYPE = ElementId("return_type",213); -ElementId ELEM_STATEMENT = ElementId("statement",214); -ElementId ELEM_SYNTAX = ElementId("syntax",215); -ElementId ELEM_VARDECL = ElementId("vardecl",216); -ElementId ELEM_VARIABLE = ElementId("variable",217); +AttributeId ATTRIB_BLOCKREF = AttributeId("blockref",35); +AttributeId ATTRIB_CLOSE = AttributeId("close",36); +AttributeId ATTRIB_COLOR = AttributeId("color",37); +AttributeId ATTRIB_INDENT = AttributeId("indent",38); +AttributeId ATTRIB_OFF = AttributeId("off",39); +AttributeId ATTRIB_OPEN = AttributeId("open",40); +AttributeId ATTRIB_OPREF = AttributeId("opref",41); +AttributeId ATTRIB_VARREF = AttributeId("varref",42); +ElementId ELEM_BREAK = ElementId("break",17); +ElementId ELEM_CLANG_DOCUMENT = ElementId("clang_document",18); +ElementId ELEM_FUNCNAME = ElementId("funcname",19); +ElementId ELEM_FUNCPROTO = ElementId("funcproto",20); +ElementId ELEM_LABEL = ElementId("label",21); +ElementId ELEM_RETURN_TYPE = ElementId("return_type",22); +ElementId ELEM_STATEMENT = ElementId("statement",23); +ElementId ELEM_SYNTAX = ElementId("syntax",24); +ElementId ELEM_VARDECL = ElementId("vardecl",25); +ElementId ELEM_VARIABLE = ElementId("variable",26); const string Emit::EMPTY_STRING = ""; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/raw_arch.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/raw_arch.cc index b3d440bd7a..3b83cf3ce7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/raw_arch.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/raw_arch.cc @@ -15,7 +15,7 @@ */ #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 RawBinaryArchitectureCapability RawBinaryArchitectureCapability::rawBinaryArchitectureCapability; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/sleigh_arch.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/sleigh_arch.cc index f383b688e0..b7dc79cf08 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/sleigh_arch.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/sleigh_arch.cc @@ -16,20 +16,20 @@ #include "sleigh_arch.hh" #include "inject_sleigh.hh" -AttributeId ATTRIB_DEPRECATED = AttributeId("deprecated",79); -AttributeId ATTRIB_ENDIAN = AttributeId("endian",80); -AttributeId ATTRIB_PROCESSOR = AttributeId("processor",81); -AttributeId ATTRIB_PROCESSORSPEC = AttributeId("processorspec",82); -AttributeId ATTRIB_SLAFILE = AttributeId("slafile",83); -AttributeId ATTRIB_SPEC = AttributeId("spec",84); -AttributeId ATTRIB_TARGET = AttributeId("target",85); -AttributeId ATTRIB_VARIANT = AttributeId("variant",86); -AttributeId ATTRIB_VERSION = AttributeId("version",87); +AttributeId ATTRIB_DEPRECATED = AttributeId("deprecated",136); +AttributeId ATTRIB_ENDIAN = AttributeId("endian",137); +AttributeId ATTRIB_PROCESSOR = AttributeId("processor",138); +AttributeId ATTRIB_PROCESSORSPEC = AttributeId("processorspec",139); +AttributeId ATTRIB_SLAFILE = AttributeId("slafile",140); +AttributeId ATTRIB_SPEC = AttributeId("spec",141); +AttributeId ATTRIB_TARGET = AttributeId("target",142); +AttributeId ATTRIB_VARIANT = AttributeId("variant",143); +AttributeId ATTRIB_VERSION = AttributeId("version",144); -ElementId ELEM_COMPILER = ElementId("compiler",173); -ElementId ELEM_DESCRIPTION = ElementId("description",174); -ElementId ELEM_LANGUAGE = ElementId("language",175); -ElementId ELEM_LANGUAGE_DEFINITIONS = ElementId("language_definitions",176); +ElementId ELEM_COMPILER = ElementId("compiler",232); +ElementId ELEM_DESCRIPTION = ElementId("description",233); +ElementId ELEM_LANGUAGE = ElementId("language",234); +ElementId ELEM_LANGUAGE_DEFINITIONS = ElementId("language_definitions",235); map SleighArchitecture::translators; vector SleighArchitecture::description; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/space.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/space.cc index 54bf06c21d..c51e58560e 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/space.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/space.cc @@ -16,20 +16,20 @@ #include "space.hh" #include "translate.hh" -AttributeId ATTRIB_BASE = AttributeId("base",88); -AttributeId ATTRIB_DEADCODEDELAY = AttributeId("deadcodedelay",89); -AttributeId ATTRIB_DELAY = AttributeId("delay", 90); -AttributeId ATTRIB_LOGICALSIZE = AttributeId("logicalsize",91); -AttributeId ATTRIB_PHYSICAL = AttributeId("physical",92); -AttributeId ATTRIB_PIECE1 = AttributeId("piece1",93); // piece attributes must have sequential ids -AttributeId ATTRIB_PIECE2 = AttributeId("piece2",94); -AttributeId ATTRIB_PIECE3 = AttributeId("piece3",95); -AttributeId ATTRIB_PIECE4 = AttributeId("piece4",96); -AttributeId ATTRIB_PIECE5 = AttributeId("piece5",97); -AttributeId ATTRIB_PIECE6 = AttributeId("piece6",98); -AttributeId ATTRIB_PIECE7 = AttributeId("piece7",99); -AttributeId ATTRIB_PIECE8 = AttributeId("piece8",100); -AttributeId ATTRIB_PIECE9 = AttributeId("piece9",101); +AttributeId ATTRIB_BASE = AttributeId("base",89); +AttributeId ATTRIB_DEADCODEDELAY = AttributeId("deadcodedelay",90); +AttributeId ATTRIB_DELAY = AttributeId("delay", 91); +AttributeId ATTRIB_LOGICALSIZE = AttributeId("logicalsize",92); +AttributeId ATTRIB_PHYSICAL = AttributeId("physical",93); +AttributeId ATTRIB_PIECE1 = AttributeId("piece1",94); // piece attributes must have sequential ids +AttributeId ATTRIB_PIECE2 = AttributeId("piece2",95); +AttributeId ATTRIB_PIECE3 = AttributeId("piece3",96); +AttributeId ATTRIB_PIECE4 = AttributeId("piece4",97); +AttributeId ATTRIB_PIECE5 = AttributeId("piece5",98); +AttributeId ATTRIB_PIECE6 = AttributeId("piece6",99); +AttributeId ATTRIB_PIECE7 = AttributeId("piece7",100); +AttributeId ATTRIB_PIECE8 = AttributeId("piece8",101); +AttributeId ATTRIB_PIECE9 = AttributeId("piece9",102); /// Calculate \e highest based on \e addressSize, and \e wordsize. /// This also calculates the default pointerLowerBound diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/stringmanage.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/stringmanage.cc index 901e1c6e3a..220210a1cf 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/stringmanage.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/stringmanage.cc @@ -16,11 +16,11 @@ #include "stringmanage.hh" #include "architecture.hh" -AttributeId ATTRIB_TRUNC = AttributeId("trunc",102); +AttributeId ATTRIB_TRUNC = AttributeId("trunc",69); -ElementId ELEM_BYTES = ElementId("bytes",177); -ElementId ELEM_STRING = ElementId("string",178); -ElementId ELEM_STRINGMANAGE = ElementId("stringmanage",179); +ElementId ELEM_BYTES = ElementId("bytes",83); +ElementId ELEM_STRING = ElementId("string",84); +ElementId ELEM_STRINGMANAGE = ElementId("stringmanage",85); /// \param max is the maximum number of characters to allow before truncating string StringManager::StringManager(int4 max) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc index 56258ac4c3..3c594169d4 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc @@ -16,7 +16,7 @@ #include "transform.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 LaneDescription::LaneDescription(const LaneDescription &op2) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc index 5db89bde1b..bf49c06f9e 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc @@ -15,21 +15,21 @@ */ #include "translate.hh" -AttributeId ATTRIB_CODE = AttributeId("code",104); -AttributeId ATTRIB_CONTAIN = AttributeId("contain",105); -AttributeId ATTRIB_DEFAULTSPACE = AttributeId("defaultspace",106); -AttributeId ATTRIB_UNIQBASE = AttributeId("uniqbase",107); +AttributeId ATTRIB_CODE = AttributeId("code",43); +AttributeId ATTRIB_CONTAIN = AttributeId("contain",44); +AttributeId ATTRIB_DEFAULTSPACE = AttributeId("defaultspace",45); +AttributeId ATTRIB_UNIQBASE = AttributeId("uniqbase",46); -ElementId ELEM_OP = ElementId("op",180); -ElementId ELEM_SLEIGH = ElementId("sleigh",181); -ElementId ELEM_SPACE = ElementId("space",182); -ElementId ELEM_SPACEID = ElementId("spaceid",183); -ElementId ELEM_SPACES = ElementId("spaces",184); -ElementId ELEM_SPACE_BASE = ElementId("space_base",185); -ElementId ELEM_SPACE_OTHER = ElementId("space_other",186); -ElementId ELEM_SPACE_OVERLAY = ElementId("space_overlay",187); -ElementId ELEM_SPACE_UNIQUE = ElementId("space_unique",188); -ElementId ELEM_TRUNCATE_SPACE = ElementId("truncate_space",189); +ElementId ELEM_OP = ElementId("op",27); +ElementId ELEM_SLEIGH = ElementId("sleigh",28); +ElementId ELEM_SPACE = ElementId("space",29); +ElementId ELEM_SPACEID = ElementId("spaceid",30); +ElementId ELEM_SPACES = ElementId("spaces",31); +ElementId ELEM_SPACE_BASE = ElementId("space_base",32); +ElementId ELEM_SPACE_OTHER = ElementId("space_other",33); +ElementId ELEM_SPACE_OVERLAY = ElementId("space_overlay",34); +ElementId ELEM_SPACE_UNIQUE = ElementId("space_unique",35); +ElementId ELEM_TRUNCATE_SPACE = ElementId("truncate_space",36); /// Parse a \ element to configure \b this object /// \param decoder is the stream decoder diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index 4583d48143..bd024bc203 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -23,33 +23,51 @@ sub_metatype Datatype::base2sub[14] = { SUB_UINT_PLAIN, SUB_INT_PLAIN, SUB_UNKNOWN, SUB_SPACEBASE, SUB_VOID }; -AttributeId ATTRIB_ALIGNMENT = AttributeId("alignment",108); -AttributeId ATTRIB_ARRAYSIZE = AttributeId("arraysize",109); -AttributeId ATTRIB_CHAR = AttributeId("char",110); -AttributeId ATTRIB_CORE = AttributeId("core",111); -AttributeId ATTRIB_ENUM = AttributeId("enum",112); -AttributeId ATTRIB_ENUMSIGNED = AttributeId("enumsigned",113); -AttributeId ATTRIB_ENUMSIZE = AttributeId("enumsize",114); -AttributeId ATTRIB_INTSIZE = AttributeId("intsize",115); -AttributeId ATTRIB_LONGSIZE = AttributeId("longsize",116); -AttributeId ATTRIB_OPAQUESTRING = AttributeId("opaquestring",117); -AttributeId ATTRIB_SIGNED = AttributeId("signed",118); -AttributeId ATTRIB_STRUCTALIGN = AttributeId("structalign",119); -AttributeId ATTRIB_UTF = AttributeId("utf",120); -AttributeId ATTRIB_VARLENGTH = AttributeId("varlength",121); +AttributeId ATTRIB_ALIGNMENT = AttributeId("alignment",47); +AttributeId ATTRIB_ARRAYSIZE = AttributeId("arraysize",48); +AttributeId ATTRIB_CHAR = AttributeId("char",49); +AttributeId ATTRIB_CORE = AttributeId("core",50); +AttributeId ATTRIB_ENUM = AttributeId("enum",51); +AttributeId ATTRIB_ENUMSIGNED = AttributeId("enumsigned",52); +AttributeId ATTRIB_ENUMSIZE = AttributeId("enumsize",53); +AttributeId ATTRIB_INTSIZE = AttributeId("intsize",54); +AttributeId ATTRIB_LONGSIZE = AttributeId("longsize",55); +AttributeId ATTRIB_OPAQUESTRING = AttributeId("opaquestring",56); +AttributeId ATTRIB_SIGNED = AttributeId("signed",57); +AttributeId ATTRIB_STRUCTALIGN = AttributeId("structalign",58); +AttributeId ATTRIB_UTF = AttributeId("utf",59); +AttributeId ATTRIB_VARLENGTH = AttributeId("varlength",60); -ElementId ELEM_CORETYPES = ElementId("coretypes",190); -ElementId ELEM_DATA_ORGANIZATION = ElementId("data_organization",191); -ElementId ELEM_DEF = ElementId("def",192); -ElementId ELEM_ENTRY = ElementId("entry",193); -ElementId ELEM_ENUM = ElementId("enum",194); -ElementId ELEM_FIELD = ElementId("field",195); -ElementId ELEM_INTEGER_SIZE = ElementId("integer_size",196); -ElementId ELEM_LONG_SIZE = ElementId("long_size",197); -ElementId ELEM_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map",198); -ElementId ELEM_TYPE = ElementId("type",199); -ElementId ELEM_TYPEGRP = ElementId("typegrp",200); -ElementId ELEM_TYPEREF = ElementId("typeref",201); +//ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT = ElementId("absolute_max_alignment", 37); +//ElementId ELEM_BITFIELD_PACKING = ElementId("bitfield_packing", 38); +//ElementId ELEM_CHAR_SIZE = ElementId("char_size", 39); +//ElementId ELEM_CHAR_TYPE = ElementId("char_type", 40); +ElementId ELEM_CORETYPES = ElementId("coretypes",41); +ElementId ELEM_DATA_ORGANIZATION = ElementId("data_organization", 42); +ElementId ELEM_DEF = ElementId("def",43); +//ElementId ELEM_DEFAULT_ALIGNMENT = ElementId("default_alignment", 44); +//ElementId ELEM_DEFAULT_POINTER_ALIGNMENT = ElementId("default_pointer_alignment", 45); +//ElementId ELEM_DOUBLE_SIZE = ElementId("double_size", 46); +ElementId ELEM_ENTRY = ElementId("entry",47); +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 @@ -3344,7 +3362,7 @@ Datatype *TypeFactory::decodeType(Decoder &decoder) if (attribId == ATTRIB_ID) { 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(); } } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh index 450d4f472a..3ec138a1dc 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh @@ -36,18 +36,36 @@ extern AttributeId ATTRIB_STRUCTALIGN; ///< Marshaling attribute "structalign" extern AttributeId ATTRIB_UTF; ///< Marshaling attribute "utf" extern AttributeId ATTRIB_VARLENGTH; ///< Marshaling attribute "varlength" +//extern ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT; ///< Marshaling element \ +//extern ElementId ELEM_BITFIELD_PACKING; ///< Marshaling element \ +//extern ElementId ELEM_CHAR_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_CHAR_TYPE; ///< Marshaling element \ extern ElementId ELEM_CORETYPES; ///< Marshaling element \ extern ElementId ELEM_DATA_ORGANIZATION; ///< Marshaling element \ extern ElementId ELEM_DEF; ///< Marshaling element \ +//extern ElementId ELEM_DEFAULT_ALIGNMENT; ///< Marshaling element \ +//extern ElementId ELEM_DEFAULT_POINTER_ALIGNMENT; ///< Marshaling element \ +//extern ElementId ELEM_DOUBLE_SIZE; ///< Marshaling element \ extern ElementId ELEM_ENTRY; ///< Marshaling element \ extern ElementId ELEM_ENUM; ///< Marshaling element \ extern ElementId ELEM_FIELD; ///< Marshaling element \ +//extern ElementId ELEM_FLOAT_SIZE; ///< Marshaling element \ extern ElementId ELEM_INTEGER_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_LONG_DOUBLE_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_LONG_LONG_SIZE; ///< Marshaling element \ extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_MACHINE_ALIGNMENT; ///< Marshaling element \ +//extern ElementId ELEM_POINTER_SHIFT; ///< Marshaling element \ +//extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_SHORT_SIZE; ///< Marshaling element \ extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \ extern ElementId ELEM_TYPE; ///< Marshaling element \ +//extern ElementId ELEM_TYPE_ALIGNMENT_ENABLED; ///< Marshaling element \ extern ElementId ELEM_TYPEGRP; ///< Marshaling element \ extern ElementId ELEM_TYPEREF; ///< Marshaling element \ +//extern ElementId ELEM_USE_MS_CONVENTION; ///< Marshaling element \ +//extern ElementId ELEM_WCHAR_SIZE; ///< Marshaling element \ +//extern ElementId ELEM_ZERO_LENGTH_BOUNDARY; ///< Marshaling element \ /// Print a hex dump of a data buffer to stream extern void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/userop.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/userop.cc index ff03b28b75..6aa3cbaf8a 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/userop.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/userop.cc @@ -16,14 +16,14 @@ #include "userop.hh" #include "funcdata.hh" -AttributeId ATTRIB_FARPOINTER = AttributeId("farpointer",122); -AttributeId ATTRIB_INPUTOP = AttributeId("inputop",123); -AttributeId ATTRIB_OUTPUTOP = AttributeId("outputop",124); -AttributeId ATTRIB_USEROP = AttributeId("userop",125); +AttributeId ATTRIB_FARPOINTER = AttributeId("farpointer",85); +AttributeId ATTRIB_INPUTOP = AttributeId("inputop",86); +AttributeId ATTRIB_OUTPUTOP = AttributeId("outputop",87); +AttributeId ATTRIB_USEROP = AttributeId("userop",88); -ElementId ELEM_CONSTRESOLVE = ElementId("constresolve",202); -ElementId ELEM_JUMPASSIST = ElementId("jumpassist",203); -ElementId ELEM_SEGMENTOP = ElementId("segmentop",204); +ElementId ELEM_CONSTRESOLVE = ElementId("constresolve",127); +ElementId ELEM_JUMPASSIST = ElementId("jumpassist",128); +ElementId ELEM_SEGMENTOP = ElementId("segmentop",129); void InjectedUserOp::decode(Decoder &decoder) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc index c30cb9c2bf..c8c886d272 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/variable.cc @@ -17,11 +17,11 @@ #include "op.hh" #include "database.hh" -AttributeId ATTRIB_CLASS = AttributeId("class",126); -AttributeId ATTRIB_REPREF = AttributeId("repref",127); -AttributeId ATTRIB_SYMREF = AttributeId("symref",128); +AttributeId ATTRIB_CLASS = AttributeId("class",66); +AttributeId ATTRIB_REPREF = AttributeId("repref",67); +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. /// \param vn is the single Varnode member diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc index e482806d96..b7d80e282c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc @@ -16,10 +16,10 @@ #include "varmap.hh" #include "funcdata.hh" -AttributeId ATTRIB_LOCK = AttributeId("lock",129); -AttributeId ATTRIB_MAIN = AttributeId("main",130); +AttributeId ATTRIB_LOCK = AttributeId("lock",133); +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 /// diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/varnode.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/varnode.cc index bff6146f5c..c2b1b6d41d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/varnode.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/varnode.cc @@ -16,11 +16,11 @@ #include "varnode.hh" #include "funcdata.hh" -AttributeId ATTRIB_ADDRTIED = AttributeId("addrtied",131); -AttributeId ATTRIB_GRP = AttributeId("grp",132); -AttributeId ATTRIB_INPUT = AttributeId("input",133); -AttributeId ATTRIB_PERSISTS = AttributeId("persists",134); -AttributeId ATTRIB_UNAFF = AttributeId("unaff",135); +AttributeId ATTRIB_ADDRTIED = AttributeId("addrtied",30); +AttributeId ATTRIB_GRP = AttributeId("grp",31); +AttributeId ATTRIB_INPUT = AttributeId("input",32); +AttributeId ATTRIB_PERSISTS = AttributeId("persists",33); +AttributeId ATTRIB_UNAFF = AttributeId("unaff",34); /// Compare by location then by definition. /// This is the same as the normal varnode compare, but we distinguish identical frees by their diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/xml_arch.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/xml_arch.cc index c87a175c5f..c5c533ba94 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/xml_arch.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/xml_arch.cc @@ -15,7 +15,7 @@ */ #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 XmlArchitectureCapability XmlArchitectureCapability::xmlArchitectureCapability; diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompInterface.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompInterface.java index 16d0f81219..f65994aa5e 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompInterface.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompInterface.java @@ -88,6 +88,7 @@ public class DecompInterface { protected CompilerSpec compilerSpec; protected DecompileProcess decompProcess; protected DecompileCallback decompCallback; + protected Encoder encoder; private DecompileDebug debug; protected CancelledListener monitorListener = new CancelledListener() { @Override @@ -110,6 +111,7 @@ public class DecompInterface { dtmanage = null; decompCallback = null; xmlOptions = null; + encoder = null; debug = null; decompileMessage = ""; compilerSpec = null; @@ -213,16 +215,19 @@ public class DecompInterface { decompProcess = DecompileProcessFactory.get(); } long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage); - String tspec = - pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null); - String coretypes = dtmanage.buildCoreTypes(); + encoder.clear(); + pcodelanguage.encodeTranslator(encoder, program.getAddressFactory(), uniqueBase); + String tspec = encoder.toString(); + encoder.clear(); + dtmanage.encodeCoreTypes(encoder); + String coretypes = encoder.toString(); SleighLanguageDescription sleighdescription = (SleighLanguageDescription) pcodelanguage.getLanguageDescription(); ResourceFile pspecfile = sleighdescription.getSpecFile(); String pspecxml = fileToString(pspecfile); - StringBuilder buffer = new StringBuilder(); - compilerSpec.saveXml(buffer); - String cspecxml = buffer.toString(); + XmlEncode xmlEncode = new XmlEncode(); + compilerSpec.encode(xmlEncode); + String cspecxml = xmlEncode.toString(); decompCallback.setNativeMessage(null); decompProcess.registerProgram(decompCallback, pspecxml, cspecxml, tspec, coretypes); @@ -317,6 +322,7 @@ public class DecompInterface { compilerSpec = spec; dtmanage = new PcodeDataTypeManager(prog); + encoder = new XmlEncode(); try { decompCallback = new DecompileCallback(prog, pcodelanguage, program.getCompilerSpec(), dtmanage); @@ -338,6 +344,7 @@ public class DecompInterface { } program = null; decompCallback = null; + encoder = null; return false; } @@ -353,6 +360,7 @@ public class DecompInterface { if (program != null) { program = null; decompCallback = null; + encoder = null; try { if ((decompProcess != null) && decompProcess.isReady()) { decompProcess.deregisterProgram(); @@ -661,17 +669,17 @@ public class DecompInterface { LimitedByteBuffer res = null; BlockGraph resgraph = null; try { - StringWriter writer = new StringWriter(); - ingraph.saveXml(writer); + encoder.clear(); + ingraph.encode(encoder); verifyProcess(); - res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(), + res = decompProcess.sendCommand1ParamTimeout("structureGraph", encoder.toString(), timeoutSecs); decompileMessage = decompCallback.getNativeMessage(); if (res != null) { XmlDecode decoder = new XmlDecode(factory); decoder.ingestStream(res.getInputStream(), "structureGraph results"); resgraph = new BlockGraph(); - resgraph.restoreXml(decoder); + resgraph.decode(decoder); resgraph.transferObjectRef(ingraph); } } @@ -718,10 +726,10 @@ public class DecompInterface { debug.setFunction(func); } decompCallback.setFunction(func, funcEntry, debug); - StringBuilder addrBuf = new StringBuilder(); - AddressXML.buildXML(addrBuf, funcEntry); + encoder.clear(); + AddressXML.encode(encoder, funcEntry); verifyProcess(); - res = decompProcess.sendCommand1ParamTimeout("decompileAt", addrBuf.toString(), + res = decompProcess.sendCommand1ParamTimeout("decompileAt", encoder.toString(), timeoutSecs); decompileMessage = decompCallback.getNativeMessage(); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java index 45f5e19af6..2785e22af8 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java @@ -16,16 +16,8 @@ package ghidra.app.decompiler; import java.io.IOException; -import java.io.StringReader; import java.math.BigInteger; 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.docking.settings.Settings; @@ -44,7 +36,6 @@ import ghidra.util.UndefinedFunction; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskMonitor; import ghidra.util.xml.SpecXmlUtils; -import ghidra.util.xml.XmlUtilities; /** * @@ -55,6 +46,7 @@ import ghidra.util.xml.XmlUtilities; public class DecompileCallback { 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 @@ -81,6 +73,7 @@ public class DecompileCallback { private String nativeMessage; private XmlDecodeLight lightDecoder; + private XmlEncode resultEncode; private InstructionBlock lastPseudoInstructionBlock; private Disassembler pseudoDisassembler; @@ -98,19 +91,7 @@ public class DecompileCallback { debug = null; utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8); lightDecoder = new XmlDecodeLight(addrfactory); - } - - 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); - } + resultEncode = new XmlEncode(); } /** @@ -156,20 +137,6 @@ public class DecompileCallback { nativeMessage = msg; } - public synchronized ArrayList 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) { try { lightDecoder.ingestString(addrxml); @@ -218,9 +185,10 @@ public class DecompileCallback { * * @param addrstring is the XML rep of function address * @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; int flags; try { @@ -232,37 +200,21 @@ public class DecompileCallback { } catch (PcodeXMLException e) { Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return null; + return EMPTY_BYTE_ARRAY; } flags = SpecXmlUtils.decodeInt(types); Function func = getFunctionAt(addr); if (func == null) { - return null; + return EMPTY_BYTE_ARRAY; } - AddressSetView addrset = func.getBody(); - StringBuilder buf = new StringBuilder(); - buf.append("\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("\n"); - String res = buf.toString(); + resultEncode.clear(); + encodeComments(resultEncode, addr, func, flags); 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) { @@ -314,45 +266,42 @@ public class DecompileCallback { } /** - * Build an XML representation of all the pcode op's a given Instruction is - * defined to perform. + * Encode a list of pcode, representing an entire Instruction, to the stream * + * @param encoder is the stream encoder * @param ops pcode ops * @param fallthruoffset number of bytes after instruction start that pcode * flow falls into * @param paramshift special instructions for injection use * @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, - AddressFactory addrFactory) { - StringBuilder resBuf = new StringBuilder(); + public static void encodeInstruction(Encoder encoder, PcodeOp[] ops, int fallthruoffset, + int paramshift, AddressFactory addrFactory) throws IOException { if ((ops.length == 1) && (ops[0].getOpcode() == PcodeOp.UNIMPLEMENTED)) { - resBuf.append("\n"); - return resBuf.toString(); + encoder.openElement(ElementId.ELEM_UNIMPL); + encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, fallthruoffset); + encoder.closeElement(ElementId.ELEM_UNIMPL); + return; } - resBuf.append("'); for (PcodeOp op : ops) { - op.buildXML(resBuf, addrFactory); + op.encode(encoder, addrFactory); } - resBuf.append("\n"); - return resBuf.toString(); + encoder.closeElement(ElementId.ELEM_INST); } - public String getPcodeInject(String nm, String context, int type) { + public byte[] getPcodeInject(String nm, String context, int type) { PcodeInjectLibrary snippetLibrary = pcodecompilerspec.getPcodeInjectLibrary(); InjectPayload payload = snippetLibrary.getPayload(type, nm); if (payload == null) { 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(); PcodeOp[] pcode; @@ -362,7 +311,7 @@ public class DecompileCallback { } catch (PcodeXMLException e) { Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return null; + return EMPTY_BYTE_ARRAY; } try { int fallThruOffset; @@ -377,7 +326,7 @@ public class DecompileCallback { if (instr == null) { Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr + ": instruction not found"); - return null; + return EMPTY_BYTE_ARRAY; } // get next inst addr for inst_next pcode variable @@ -395,14 +344,18 @@ public class DecompileCallback { } pcode = payload.getPcode(program, con); 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 = - buildInstruction(pcode, fallThruOffset, payload.getParamShift(), addrfactory); + resultEncode.clear(); + encodeInstruction(resultEncode, pcode, fallThruOffset, payload.getParamShift(), + addrfactory); 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) { 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 + ": " + 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) { cpool = pcodecompilerspec.getPcodeInjectLibrary().getConstantPool(program); } Record record = cpool.getRecord(refs); - String res = record.build(refs[0], dtmanage).toString(); + resultEncode.clear(); + record.encode(resultEncode, refs[0], dtmanage); 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 { @@ -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 - * @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); - StringBuilder buf = new StringBuilder(); - HighFunction.createNamespaceTag(buf, namespace); + resultEncode.clear(); + HighFunction.encodeNamespace(resultEncode, namespace); if (debug != null) { 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(); String text = listing.getComment(CodeUnit.PLATE_COMMENT, addr); if (text != null) { - buf.append("\n"); - AddressXML.buildXML(buf, addr); - AddressXML.buildXML(buf, addr); - buf.append("\n"); - SpecXmlUtils.xmlEscape(buf, text); - buf.append("\n"); - buf.append("\n"); - + encoder.openElement(ElementId.ELEM_COMMENT); + encoder.writeString(AttributeId.ATTRIB_TYPE, "header"); + AddressXML.encode(encoder, addr); + AddressXML.encode(encoder, addr); + encoder.openElement(ElementId.ELEM_TEXT); + encoder.writeString(AttributeId.ATTRIB_CONTENT, text); + encoder.closeElement(ElementId.ELEM_TEXT); + encoder.closeElement(ElementId.ELEM_COMMENT); } } /** - * 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 buf = StringBuilder where XML should be written - * @param commenttype = type of comment + * @param encoder is the stream encoder + * @param addrset is the address set over which to search + * @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, - int commenttype) { + private void encodeCommentsType(Encoder encoder, AddressSetView addrset, Address addr, + int commenttype) throws IOException { String typename; switch (commenttype) { case CodeUnit.EOL_COMMENT: @@ -684,29 +644,50 @@ public class DecompileCallback { continue; } } - - buf.append("\n"); - AddressXML.buildXML(buf, addr); - AddressXML.buildXML(buf, commaddr); - buf.append("\n"); - SpecXmlUtils.xmlEscape(buf, text); - buf.append("\n"); - buf.append("\n"); + encoder.openElement(ElementId.ELEM_COMMENT); + encoder.writeString(AttributeId.ATTRIB_TYPE, typename); + AddressXML.encode(encoder, addr); + AddressXML.encode(encoder, commaddr); + encoder.openElement(ElementId.ELEM_TEXT); + encoder.writeString(AttributeId.ATTRIB_CONTENT, text); + encoder.closeElement(ElementId.ELEM_TEXT); + encoder.closeElement(ElementId.ELEM_COMMENT); } } } + 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 * symbols at the given address. * * @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; try { lightDecoder.ingestString(addrstring); @@ -716,43 +697,50 @@ public class DecompileCallback { } if (addr == Address.NO_ADDRESS) { // Unknown spaces may result from "spacebase" registers defined in cspec - return null; + return EMPTY_BYTE_ARRAY; } } catch (PcodeXMLException e) { Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return null; + return EMPTY_BYTE_ARRAY; } try { - String res = null; Object obj = lookupSymbol(addr); + resultEncode.clear(); if (obj instanceof Function) { boolean includeDefaults = addr.equals(funcEntry); - res = buildFunctionXML((Function) obj, addr, includeDefaults); + encodeFunction(resultEncode, (Function) obj, addr, includeDefaults); } else if (obj instanceof Data) { - res = buildData((Data) obj); + if (!encodeData(resultEncode, (Data) obj)) { + encodeHole(resultEncode, addr); + } } else if (obj instanceof ExternalReference) { - res = buildExternalRef(addr, (ExternalReference) obj); + encodeExternalRef(resultEncode, addr, (ExternalReference) obj); } 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 - res = buildHole(addr).toString(); + else { + encodeHole(resultEncode, addr); // There is a hole, describe the extent of the hole } - return res; + return resultEncode.getBytes(); } catch (Exception e) { Msg.error(this, "Decompiling " + funcEntry + ", mapped symbol error for " + addrstring + ": " + 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; try { lightDecoder.ingestString(addrstring); @@ -763,7 +751,7 @@ public class DecompileCallback { } catch (PcodeXMLException e) { Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return null; + return EMPTY_BYTE_ARRAY; } try { @@ -787,7 +775,9 @@ public class DecompileCallback { } HighSymbol shellSymbol = new HighFunctionShellSymbol(extId, extRef.getLabel(), addr, dtmanage); - return buildResult(shellSymbol, null); + resultEncode.clear(); + encodeResult(resultEncode, shellSymbol, null); + return resultEncode.getBytes(); } } else { @@ -796,7 +786,7 @@ public class DecompileCallback { } if (func == null) { // 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); @@ -810,38 +800,38 @@ public class DecompileCallback { debug.getFNTypes(hfunc); debug.addPossiblePrototypeExtension(func); } - return buildResult(funcSymbol, namespc); + resultEncode.clear(); + encodeResult(resultEncode, funcSymbol, namespc); + return resultEncode.getBytes(); } catch (Exception e) { Msg.error(this, "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); if (type == null) { - return null; + return EMPTY_BYTE_ARRAY; } - StringBuilder resBuf = new StringBuilder(); - dtmanage.buildType(resBuf, type, 0); - resBuf.append("\n"); // Make into official XML document - String res = resBuf.toString(); + resultEncode.clear(); + dtmanage.encodeType(resultEncode, type, 0); if (debug != null) { 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); if (reg == null) { throw new RuntimeException("No Register Defined: " + name); } - StringBuilder resBuf = buildRegister(reg); - resBuf.append("\n"); - return resBuf.toString(); + resultEncode.clear(); + encodeRegister(resultEncode, reg); + return resultEncode.getBytes(); } public String getRegisterName(String addrstring) { @@ -852,7 +842,7 @@ public class DecompileCallback { int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE); Register reg = pcodelanguage.getRegister(addr, size); if (reg == null) { - return null; + return ""; } return reg.getName(); } @@ -860,10 +850,10 @@ public class DecompileCallback { Msg.error(this, "Decompiling " + funcEntry + ", 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; try { lightDecoder.ingestString(addrstring); @@ -874,30 +864,18 @@ public class DecompileCallback { } catch (PcodeXMLException e) { Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return null; + return EMPTY_BYTE_ARRAY; } ProgramContext context = program.getProgramContext(); - StringBuilder stringBuf = new StringBuilder(); - - 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("\n"); - String res = stringBuf.toString(); + resultEncode.clear(); + encodeTrackedPointSet(resultEncode, addr, context); 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) { @@ -906,7 +884,8 @@ public class DecompileCallback { return name; } - private String buildResult(HighSymbol highSymbol, Namespace namespc) { + private void encodeResult(Encoder encoder, HighSymbol highSymbol, Namespace namespc) + throws IOException { long namespaceId; if (namespc == null || namespc instanceof Library) { namespaceId = Namespace.GLOBAL_NAMESPACE_ID; @@ -914,26 +893,26 @@ public class DecompileCallback { else { namespaceId = namespc.getID(); } - StringBuilder res = new StringBuilder(); - res.append("\n"); + encoder.openElement(ElementId.ELEM_DOC); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, namespaceId); if (debug != null) { - StringBuilder res2 = new StringBuilder(); - HighSymbol.buildMapSymXML(res2, highSymbol); - String res2string = res2.toString(); + XmlEncode debugEncode = new XmlEncode(); + HighSymbol.encodeMapSym(debugEncode, highSymbol); + String res2string = debugEncode.toString(); debug.getMapped(namespc, res2string); - res.append(res2string); } - else { - HighSymbol.buildMapSymXML(res, highSymbol); - } - res.append("\n"); - - return res.toString(); + HighSymbol.encodeMapSym(encoder, highSymbol); + encoder.closeElement(ElementId.ELEM_DOC); } - 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(); HighCodeSymbol highSymbol; if (sym != null) { @@ -945,36 +924,36 @@ public class DecompileCallback { SymbolEntry entry = highSymbol.getFirstWholeMap(); if (data.getDataType() == DataType.DEFAULT && !entry.isReadOnly() && !entry.isVolatile()) { - return null; + return false; } } if (debug != null) { debug.getType(highSymbol.getDataType()); } Namespace namespc = (sym != null) ? sym.getParentNamespace() : null; - return buildResult(highSymbol, namespc); + encodeResult(encoder, highSymbol, namespc); + return true; } - private StringBuilder buildRegister(Register reg) { - StringBuilder resBuf = new StringBuilder(); - resBuf.append(""); - return resBuf; + private static void encodeRegister(Encoder encoder, Register reg) throws IOException { + encoder.openElement(ElementId.ELEM_ADDR); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, reg.getAddressSpace()); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, reg.getOffset()); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, reg.getMinimumByteSize()); + encoder.closeElement(ElementId.ELEM_ADDR); } /** - * 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 - * @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); 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 * address * + * @param encoder is the stream encoder * @param func Function whose body contains the address * @param addr The queried address * @param includeDefaultNames true if default parameter names should be * 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(); if (entry.getAddressSpace().equals(addr.getAddressSpace())) { long diff = addr.getOffset() - entry.getOffset(); @@ -1056,7 +1037,8 @@ public class DecompileCallback { debug.getFNTypes(hfunc); debug.addPossiblePrototypeExtension(func); } - return buildResult(functionSymbol, namespc); + encodeResult(encoder, functionSymbol, namespc); + return; } } @@ -1067,14 +1049,15 @@ public class DecompileCallback { Address first = range.getMinAddress(); Address last = range.getMaxAddress(); 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); + return; } } // There is probably some sort of error, just return a block // containing the single queried address - return buildHoleXML(addr.getAddressSpace().getPhysicalSpace().getName(), - addr.getUnsignedOffset(), addr.getUnsignedOffset(), true, false); + encodeHole(encoder, addr.getAddressSpace().getPhysicalSpace(), addr.getUnsignedOffset(), + addr.getUnsignedOffset(), true, false); } private int getExtraPopOverride(Function func, Address addr) { @@ -1110,17 +1093,15 @@ public class DecompileCallback { return extrapop; } - private String buildHoleXML(String nm, long first, long last, boolean readonly, - boolean isVolatile) { - StringBuilder resBuf = new StringBuilder(); - resBuf.append("\n"); - return resBuf.toString(); + private void encodeHole(Encoder encoder, AddressSpace spc, long first, long last, + boolean readonly, boolean isVolatile) throws IOException { + encoder.openElement(ElementId.ELEM_HOLE); + encoder.writeBool(AttributeId.ATTRIB_READONLY, readonly); + encoder.writeBool(AttributeId.ATTRIB_VOLATILE, isVolatile); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, spc); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last); + encoder.closeElement(ElementId.ELEM_HOLE); } /** @@ -1132,64 +1113,20 @@ public class DecompileCallback { * readonly properties don't vary * * So now we assume that biggest hole we can find is just 1 byte - * - * @param addr = Address around which to find region - * @return String tag + * + * @param encoder is the stream encoder + * @param addr is the Address around which to find region + * @throws IOException for errors in the underlying stream */ - private String buildHole(Address addr) { -// 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() 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()\n"); + encoder.openElement(ElementId.ELEM_SET); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, spc); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, offset); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_VAL, val); + 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) { @@ -1422,46 +1375,4 @@ public class DecompileCallback { } return stringData; } - -//================================================================================================== -// Inner Classes -//================================================================================================== - - private class NameListHandler extends DefaultHandler { - private ArrayList 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 getList() { - return res; - } - } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileDebug.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileDebug.java index 163d46653f..852118013c 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileDebug.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileDebug.java @@ -288,14 +288,14 @@ public class DecompileDebug { if (stringmap.isEmpty()) { return; } - StringBuilder buf = new StringBuilder(); - buf.append("\n"); + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_STRINGMANAGE); for (Map.Entry entry : stringmap.entrySet()) { - buf.append("\n"); - AddressXML.buildXML(buf, entry.getKey()); - buf.append("\n\n "); + encoder.openElement(ElementId.ELEM_STRING); + AddressXML.encode(encoder, entry.getKey()); + encoder.openElement(ElementId.ELEM_BYTES); + encoder.writeBool(AttributeId.ATTRIB_TRUNC, entry.getValue().isTruncated); + StringBuilder buf = new StringBuilder(); int count = 0; for (byte element : entry.getValue().byteData) { int hi = (element >> 4) & 0xf; @@ -318,46 +318,41 @@ public class DecompileDebug { buf.append("\n "); } } - buf.append("00\n\n"); - buf.append("\n"); + buf.append("00\n"); + encoder.writeString(AttributeId.ATTRIB_CONTENT, buf.toString()); + encoder.closeElement(ElementId.ELEM_BYTES); + encoder.closeElement(ElementId.ELEM_STRING); } - buf.append("\n"); - debugStream.write(buf.toString().getBytes()); + encoder.closeElement(ElementId.ELEM_STRINGMANAGE); + debugStream.write(encoder.getBytes()); } private void dumpDataTypes(OutputStream debugStream) throws IOException { DataOrganization dataOrganization = program.getCompilerSpec().getDataOrganization(); int intSize = dataOrganization.getIntegerSize(); int longSize = dataOrganization.getLongSize(); - StringBuilder buf = new StringBuilder(); - buf.append("\n"); + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_TYPEGRP); + encoder.writeSignedInteger(AttributeId.ATTRIB_INTSIZE, intSize); + encoder.writeSignedInteger(AttributeId.ATTRIB_LONGSIZE, longSize); + encoder.writeSignedInteger(AttributeId.ATTRIB_STRUCTALIGN, 4); + encoder.writeSignedInteger(AttributeId.ATTRIB_ENUMSIZE, 4); + encoder.writeBool(AttributeId.ATTRIB_ENUMSIGNED, false); // structalign should come out of pcodelanguage.getCompilerSpec() - debugStream.write(buf.toString().getBytes()); DataTypeDependencyOrderer TypeOrderer = new DataTypeDependencyOrderer(program.getDataTypeManager(), dtypes); //First output all structures as zero size so to avoid any cyclic dependencies. for (DataType dataType : TypeOrderer.getCompositeList()) { - debugStream - .write((dtmanage.buildCompositeZeroSizePlaceholder(dataType) + "\n").toString() - .getBytes()); + dtmanage.encodeCompositeZeroSizePlaceholder(encoder, dataType); } //Next, use the dependency stack to output types. for (DataType dataType : TypeOrderer.getDependencyList()) { if (!(dataType instanceof BuiltIn)) { - StringBuilder typeBuf = new StringBuilder(); - - dtmanage.buildType(typeBuf, dataType, dataType.getLength()); - typeBuf.append('\n'); - debugStream.write(typeBuf.toString().getBytes()); + dtmanage.encodeType(encoder, dataType, dataType.getLength()); } } - debugStream.write("\n".getBytes()); + encoder.closeElement(ElementId.ELEM_TYPEGRP); + debugStream.write(encoder.getBytes()); } private void dumpTrackedContext(OutputStream debugStream) throws IOException { @@ -428,7 +423,6 @@ public class DecompileDebug { Address addr = iter.next(); ProgramProcessorContext procctx = new ProgramProcessorContext(progctx, addr); ctxcache.getContext(procctx, buf); - StringBuilder stringBuf = new StringBuilder(); if (lastbuf != null) { // Check to make sure we don't have identical context data int i; for (i = 0; i < buf.length; ++i) { @@ -447,9 +441,9 @@ public class DecompileDebug { lastbuf[i] = buf[i]; } - stringBuf.append("\n"); + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_CONTEXT_POINTSET); + AddressXML.encodeAttributes(encoder, addr); for (ContextSymbol sym : ctxsymbols) { int sbit = sym.getInternalLow(); int ebit = sym.getInternalHigh(); @@ -459,14 +453,13 @@ public class DecompileDebug { int shift = (8 * 4) - endbit - 1; int mask = -1 >>> (startbit + shift); int val = (buf[word] >>> shift) & mask; - stringBuf.append(" \n"); + encoder.openElement(ElementId.ELEM_SET); + encoder.writeString(AttributeId.ATTRIB_NAME, sym.getName()); + encoder.writeSignedInteger(AttributeId.ATTRIB_VAL, val); + encoder.closeElement(ElementId.ELEM_SET); } - stringBuf.append("\n"); - String end = stringBuf.toString(); - debugStream.write(end.getBytes()); + encoder.closeElement(ElementId.ELEM_CONTEXT_POINTSET); + debugStream.write(encoder.getBytes()); } } @@ -606,28 +599,26 @@ public class DecompileDebug { return; } PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary(); - debugStream.write("\n".getBytes()); + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_SPECEXTENSIONS); for (Object obj : specExtensions.values()) { if (obj instanceof PrototypeModel) { PrototypeModel model = (PrototypeModel) obj; - StringBuilder buffer = new StringBuilder(); - model.saveXml(buffer, library); - String modelString = buffer.toString(); - debugStream.write(modelString.getBytes()); + model.encode(encoder, library); } else if (obj instanceof InjectPayload) { InjectPayload payload = (InjectPayload) obj; - StringBuilder buffer = new StringBuilder(); - payload.saveXml(buffer); - String payloadString = buffer.toString(); - debugStream.write(payloadString.getBytes()); + payload.encode(encoder); } } - debugStream.write("\n".getBytes()); + encoder.closeElement(ElementId.ELEM_SPECEXTENSIONS); + debugStream.write(encoder.getBytes()); } 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) { @@ -694,17 +685,19 @@ public class DecompileDebug { comments = comm; // Already in XML form } - public void getCodeSymbol(Address addr, long id, String name, Namespace namespace) { - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - buf.append(" \n "); - AddressXML.buildXML(buf, addr); - buf.append("\n \n"); - buf.append("\n"); - getMapped(namespace, buf.toString()); + public void getCodeSymbol(Address addr, long id, String name, Namespace namespace) + throws IOException { + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_MAPSYM); + encoder.openElement(ElementId.ELEM_LABELSYM); + encoder.writeString(AttributeId.ATTRIB_NAME, name); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id); + encoder.closeElement(ElementId.ELEM_LABELSYM); + AddressXML.encode(encoder, addr); + encoder.openElement(ElementId.ELEM_RANGELIST); + encoder.closeElement(ElementId.ELEM_RANGELIST); + encoder.closeElement(ElementId.ELEM_MAPSYM); + getMapped(namespace, encoder.toString()); } public void getNamespacePath(Namespace namespace) { @@ -765,43 +758,42 @@ public class DecompileDebug { getMapped(spc, buffer.toString()); } - public void addFlowOverride(Address addr, FlowOverride fo) { - StringBuilder buf = new StringBuilder(); - buf.append(""); - AddressXML.buildXML(buf, func.getEntryPoint()); - AddressXML.buildXML(buf, addr); - buf.append("\n"); - flowoverride.add(buf.toString()); + AddressXML.encode(encoder, func.getEntryPoint()); + AddressXML.encode(encoder, addr); + encoder.closeElement(ElementId.ELEM_FLOW); + flowoverride.add(encoder.toString()); } - public void addInject(Address addr, String name, int injectType, String payload) { - StringBuilder buf = new StringBuilder(); - buf.append("\n "); - AddressXML.buildXML(buf, addr); - buf.append("\n \n\n"); - inject.add(buf.toString()); + public void addInject(Address addr, String name, int injectType, String payload) + throws IOException { + XmlEncode encoder = new XmlEncode(); + encoder.openElement(ElementId.ELEM_INJECT); + encoder.writeString(AttributeId.ATTRIB_NAME, name); + encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, injectType); + AddressXML.encode(encoder, addr); + encoder.openElement(ElementId.ELEM_PAYLOAD); + encoder.writeString(AttributeId.ATTRIB_CONTENT, payload); + encoder.closeElement(ElementId.ELEM_PAYLOAD); + encoder.closeElement(ElementId.ELEM_INJECT); + inject.add(encoder.toString()); PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary(); if (library.hasProgramPayload(name, injectType)) { diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java index 832d0f8e73..b2b72a924f 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java @@ -233,6 +233,12 @@ public class DecompileProcess { 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 * @param out has the collected byte for this write @@ -628,10 +634,10 @@ public class DecompileProcess { private void getRegister() throws IOException { String name = readQueryString(); - String res = callback.getRegister(name); + byte[] res = callback.getRegister(name); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -640,9 +646,6 @@ public class DecompileProcess { String addr = readQueryString(); String res = callback.getRegisterName(addr); - if (res == null) { - res = ""; - } write(query_response_start); writeString(res); write(query_response_end); @@ -650,12 +653,9 @@ public class DecompileProcess { private void getTrackedRegisters() throws IOException { String addr = readQueryString(); - String res = callback.getTrackedRegisters(addr); - if (res == null) { - res = ""; - } + byte[] res = callback.getTrackedRegisters(addr); write(query_response_start); - writeString(res); + writeBytes(res); write(query_response_end); } @@ -683,10 +683,10 @@ public class DecompileProcess { private void getPcodeInject(int type) throws IOException { String name = readQueryString(); String context = readQueryString(); - String res = callback.getPcodeInject(name, context, type); + byte[] res = callback.getPcodeInject(name, context, type); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -698,10 +698,10 @@ public class DecompileProcess { for (int i = 0; i < split.length; ++i) { refs[i] = Long.parseUnsignedLong(split[i], 16); } - String res = callback.getCPoolRef(refs); + byte[] res = callback.getCPoolRef(refs); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -709,10 +709,10 @@ public class DecompileProcess { private void getMappedSymbolsXML() throws IOException { String addr = readQueryString(); - String res = callback.getMappedSymbolsXML(addr); + byte[] res = callback.getMappedSymbolsXML(addr); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -720,10 +720,10 @@ public class DecompileProcess { private void getNamespacePath() throws IOException { String idString = readQueryString(); long id = Long.parseLong(idString, 16); - String res = callback.getNamespacePath(id); + byte[] res = callback.getNamespacePath(id); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -744,10 +744,10 @@ public class DecompileProcess { private void getExternalRefXML() throws IOException { String refaddr = readQueryString(); - String res = callback.getExternalRefXML(refaddr); + byte[] res = callback.getExternalRefXML(refaddr); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } @@ -767,32 +767,19 @@ public class DecompileProcess { private void getComments() throws IOException { String addr = readQueryString(); String flags = readQueryString(); - String res = callback.getComments(addr, flags); - if (res == null) { - res = ""; - } + byte[] res = callback.getComments(addr, flags); write(query_response_start); - writeString(res); + writeBytes(res); 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 { String name = readQueryString(); long id = SpecXmlUtils.decodeLong(readQueryString()); - String res = callback.getType(name, id); + byte[] res = callback.getType(name, id); write(query_response_start); - if ((res != null) && (res.length() != 0)) { - writeString(res); + if (res.length != 0) { + writeBytes(res); } write(query_response_end); } diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/SpecExtensionTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/SpecExtensionTest.java index 02ee7a67a5..a24f39cc8c 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/SpecExtensionTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/SpecExtensionTest.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.decompile; import static org.junit.Assert.*; +import java.io.IOException; import java.util.List; import org.junit.Test; @@ -32,6 +33,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.lang.*; import ghidra.program.model.lang.CompilerSpec.EvaluationModelType; import ghidra.program.model.listing.Function; +import ghidra.program.model.pcode.XmlEncode; import ghidra.program.model.symbol.SourceType; import ghidra.util.exception.CancelledException; import ghidra.util.exception.InvalidInputException; @@ -125,15 +127,15 @@ public class SpecExtensionTest extends AbstractDecompilerTest { } @Test - public void test_PrototypeExtension() { + public void test_PrototypeExtension() throws IOException { decompile("100272e"); ClangTextField line = getLineContaining("FUN_010026a7(pHVar1);"); assertNotNull(line); CompilerSpec cspec = program.getCompilerSpec(); PrototypeModel defaultModel = cspec.getDefaultCallingConvention(); - StringBuilder buffer = new StringBuilder(); - defaultModel.saveXml(buffer, cspec.getPcodeInjectLibrary()); - String defaultString = buffer.toString(); + XmlEncode encoder = new XmlEncode(); + defaultModel.encode(encoder, cspec.getPcodeInjectLibrary()); + String defaultString = encoder.toString(); // Replace the output register EAX with ECX defaultString = defaultString.replace("", ""); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java index 8ed8d91d5d..06c5e141bd 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java @@ -40,6 +40,7 @@ import ghidra.program.model.lang.*; import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemoryAccessException; +import ghidra.program.model.pcode.*; import ghidra.program.model.symbol.SourceType; import ghidra.program.model.util.AddressLabelInfo; 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. - * @param factory address factory + * Encode limited information to the stream about the SLEIGH translator for the specified + * 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 optionalSymTab optional symbol table to be passed (may be null to omit). Only non-context registers - * and user-defined pcodeop's are included. - * @return the entire XML tag as a String + * @throws IOException for errors writing to the underlying stream */ - public String buildTranslatorTag(AddressFactory factory, long uniqueOffset, - SymbolTable optionalSymTab) { + public void encodeTranslator(Encoder encoder, AddressFactory factory, long uniqueOffset) + throws IOException { AddressSpace[] spclist = factory.getAllAddressSpaces(); - StringBuilder resBuf = new StringBuilder(); - - resBuf.append("\n"); - resBuf.append("\n"); - String tag; + ElementId tag; int delay; boolean physical; for (AddressSpace element : spclist) { if ((element instanceof OverlayAddressSpace)) { OverlayAddressSpace ospace = (OverlayAddressSpace) element; - resBuf.append("\n"); + encoder.openElement(ElementId.ELEM_SPACE_OVERLAY); + encoder.writeString(AttributeId.ATTRIB_NAME, ospace.getName()); + encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, ospace.getUnique()); + encoder.writeSpace(AttributeId.ATTRIB_BASE, ospace.getOverlayedSpace()); + encoder.closeElement(ElementId.ELEM_SPACE_OVERLAY); continue; } switch (element.getType()) { case AddressSpace.TYPE_RAM: - tag = "space"; + tag = ElementId.ELEM_SPACE; delay = 1; physical = true; break; case AddressSpace.TYPE_REGISTER: - tag = "space"; + tag = ElementId.ELEM_SPACE; delay = 0; physical = true; break; case AddressSpace.TYPE_UNIQUE: - tag = "space_unique"; + tag = ElementId.ELEM_SPACE_UNIQUE; delay = 0; physical = true; break; case AddressSpace.TYPE_OTHER: - tag = "space_other"; + tag = ElementId.ELEM_SPACE_OTHER; delay = 0; physical = true; break; default: continue; } - resBuf.append("<").append(tag); - SpecXmlUtils.encodeStringAttribute(resBuf, "name", element.getName()); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique()); + encoder.openElement(tag); + encoder.writeString(AttributeId.ATTRIB_NAME, element.getName()); + encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, element.getUnique()); int size = element.getSize(); // Size in bits if (element instanceof SegmentedAddressSpace) { @@ -1476,20 +1472,19 @@ public class SleighLanguage implements Language { size = 64; } int bytesize = (size + 7) / 8; // Convert bits to bytes - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", bytesize); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, bytesize); if (element.getAddressableUnitSize() > 1) { - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "wordsize", + encoder.writeSignedInteger(AttributeId.ATTRIB_WORDSIZE, element.getAddressableUnitSize()); } - SpecXmlUtils.encodeBooleanAttribute(resBuf, "bigendian", isBigEndian()); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "delay", delay); - SpecXmlUtils.encodeBooleanAttribute(resBuf, "physical", physical); - - resBuf.append("/>\n"); + encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian()); + encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, delay); + encoder.writeBool(AttributeId.ATTRIB_PHYSICAL, physical); + encoder.closeElement(tag); } - resBuf.append("\n"); + encoder.closeElement(ElementId.ELEM_SPACES); SleighLanguageDescription sleighDescription = (SleighLanguageDescription) getLanguageDescription(); @@ -1497,75 +1492,13 @@ public class SleighLanguage implements Language { if (!truncatedSpaceNames.isEmpty()) { for (String spaceName : truncatedSpaceNames) { int sz = sleighDescription.getTruncatedSpaceSize(spaceName); - resBuf.append("\n"); + encoder.openElement(ElementId.ELEM_TRUNCATE_SPACE); + encoder.writeString(AttributeId.ATTRIB_SPACE, spaceName); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz); + encoder.closeElement(ElementId.ELEM_TRUNCATE_SPACE); } } - if (optionalSymTab != null) { - resBuf.append(buildSymbolsXml(optionalSymTab)); - } - - resBuf.append("\n"); - return resBuf.toString(); - } - - private static String buildSymbolsXml(SymbolTable symtab) { - - ArrayList 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("\n"); - s.append("\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("\n"); - } - else { - VarnodeSymbol vnSym = (VarnodeSymbol) sym; - VarnodeData vn = vnSym.getFixedVarnode(); - s.append( - "\n"); - } - } - s.append("\n"); - return s.toString(); + encoder.closeElement(ElementId.ELEM_SLEIGH); } private void initParallelHelper() { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SpecExtensionPanel.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SpecExtensionPanel.java index ed455d65e7..a60ac1357a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SpecExtensionPanel.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SpecExtensionPanel.java @@ -38,6 +38,7 @@ import ghidra.program.database.ProgramDB; import ghidra.program.database.SpecExtension; import ghidra.program.database.SpecExtension.DocInfo; import ghidra.program.model.lang.*; +import ghidra.program.model.pcode.XmlEncode; import ghidra.util.Msg; import ghidra.util.Swing; 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(); PcodeInjectLibrary injectLibrary = compilerSpec.getPcodeInjectLibrary(); InjectPayload payload; PrototypeModel model; - String resultString = null; + String resultString; if (element.status == Status.CORE) { - StringBuilder buffer = new StringBuilder(); + XmlEncode encoder = new XmlEncode(); switch (element.type) { case CALL_FIXUP: payload = injectLibrary.getPayload(InjectPayload.CALLFIXUP_TYPE, element.name); if (payload != null) { - payload.saveXml(buffer); + payload.encode(encoder); } break; case CALLOTHER_FIXUP: payload = injectLibrary.getPayload(InjectPayload.CALLOTHERFIXUP_TYPE, element.name); if (payload != null) { - payload.saveXml(buffer); + payload.encode(encoder); } break; case PROTOTYPE_MODEL: case MERGE_MODEL: model = compilerSpec.getCallingConvention(element.name); if (model != null) { - model.saveXml(buffer, injectLibrary); + model.encode(encoder, injectLibrary); } break; } - resultString = buffer.toString(); - if (resultString.length() == 0) { - resultString = null; - } + resultString = encoder.toString(); } else { resultString = 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; } @@ -603,24 +604,16 @@ public class SpecExtensionPanel extends JPanel { return; } } - String exportString = getXmlString(compilerElement); - String errMessage = null; - if (exportString == null) { - errMessage = "Unable to build document for " + compilerElement.name; + FileWriter writer = null; + try { + String exportString = getXmlString(compilerElement); + writer = new FileWriter(outputFile); + writer.write(exportString); + writer.close(); } - else { - FileWriter writer = null; - try { - 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); + catch (IOException ex) { + Msg.showError(this, this, "Export Failure", + "Failed to write to file: " + ex.getMessage()); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldPackingImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldPackingImpl.java index 222da71e45..5c2681be0e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldPackingImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldPackingImpl.java @@ -15,6 +15,9 @@ */ package ghidra.program.model.data; +import java.io.IOException; + +import ghidra.program.model.pcode.*; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; @@ -70,26 +73,31 @@ public class BitFieldPackingImpl implements BitFieldPacking { } /** - * Write configuration to a stream as an XML \ tag - * @param buffer is the stream to write to + * Write configuration to a stream as a \ element + * @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) { return; // All defaults } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_BITFIELD_PACKING); if (useMSConvention) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_USE_MS_CONVENTION); + encoder.writeBool(AttributeId.ATTRIB_VALUE, true); + encoder.closeElement(ElementId.ELEM_USE_MS_CONVENTION); } if (!typeAlignmentEnabled) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_TYPE_ALIGNMENT_ENABLED); + encoder.writeBool(AttributeId.ATTRIB_VALUE, false); + encoder.closeElement(ElementId.ELEM_TYPE_ALIGNMENT_ENABLED); } if (zeroLengthBoundary != 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_ZERO_LENGTH_BOUNDARY); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, zeroLengthBoundary); + encoder.closeElement(ElementId.ELEM_ZERO_LENGTH_BOUNDARY); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_BITFIELD_PACKING); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java index 14a8b2cdbd..0a8a937a17 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java @@ -15,9 +15,11 @@ */ package ghidra.program.model.data; +import java.io.IOException; import java.util.*; import ghidra.program.model.lang.Language; +import ghidra.program.model.pcode.*; import ghidra.util.exception.NoValueException; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.XmlElement; @@ -551,99 +553,101 @@ public class DataOrganizationImpl implements DataOrganization { return (value2 != 0) ? getGreatestCommonDenominator(value2, value1 % value2) : value1; } - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_DATA_ORGANIZATION); if (absoluteMaxAlignment != NO_MAXIMUM_ALIGNMENT) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_ABSOLUTE_MAX_ALIGNMENT); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, absoluteMaxAlignment); + encoder.closeElement(ElementId.ELEM_ABSOLUTE_MAX_ALIGNMENT); } if (machineAlignment != 8) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_MACHINE_ALIGNMENT); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, machineAlignment); + encoder.closeElement(ElementId.ELEM_MACHINE_ALIGNMENT); } if (defaultAlignment != 1) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_DEFAULT_ALIGNMENT); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, defaultAlignment); + encoder.closeElement(ElementId.ELEM_DEFAULT_ALIGNMENT); } if (defaultPointerAlignment != 4) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_DEFAULT_POINTER_ALIGNMENT); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, defaultPointerAlignment); + encoder.closeElement(ElementId.ELEM_DEFAULT_POINTER_ALIGNMENT); } if (pointerSize != 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_POINTER_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, pointerSize); + encoder.closeElement(ElementId.ELEM_POINTER_SIZE); } if (pointerShift != 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_POINTER_SHIFT); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, pointerShift); + encoder.closeElement(ElementId.ELEM_POINTER_SHIFT); } if (!isSignedChar) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_CHAR_TYPE); + encoder.writeBool(AttributeId.ATTRIB_SIGNED, false); + encoder.closeElement(ElementId.ELEM_CHAR_TYPE); } if (charSize != 1) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_CHAR_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, charSize); + encoder.closeElement(ElementId.ELEM_CHAR_SIZE); } if (wideCharSize != 2) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_WCHAR_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, wideCharSize); + encoder.closeElement(ElementId.ELEM_WCHAR_SIZE); } if (shortSize != 2) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_SHORT_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, shortSize); + encoder.closeElement(ElementId.ELEM_SHORT_SIZE); } if (integerSize != 4) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_INTEGER_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, integerSize); + encoder.closeElement(ElementId.ELEM_INTEGER_SIZE); } if (longSize != 4) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_LONG_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longSize); + encoder.closeElement(ElementId.ELEM_LONG_SIZE); } if (longLongSize != 8) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_LONG_LONG_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longLongSize); + encoder.closeElement(ElementId.ELEM_LONG_LONG_SIZE); } if (floatSize != 4) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_FLOAT_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, floatSize); + encoder.closeElement(ElementId.ELEM_FLOAT_SIZE); } if (doubleSize != 8) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_DOUBLE_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, doubleSize); + encoder.closeElement(ElementId.ELEM_DOUBLE_SIZE); } if (longDoubleSize != 8) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_LONG_DOUBLE_SIZE); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, longDoubleSize); + encoder.closeElement(ElementId.ELEM_LONG_DOUBLE_SIZE); } if (sizeAlignmentMap.size() != 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_SIZE_ALIGNMENT_MAP); for (int key : sizeAlignmentMap.keySet()) { - buffer.append("\n"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, key); + encoder.writeSignedInteger(AttributeId.ATTRIB_ALIGNMENT, value); + encoder.closeElement(ElementId.ELEM_ENTRY); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_SIZE_ALIGNMENT_MAP); } - bitFieldPacking.saveXml(buffer); - buffer.append("\n"); + bitFieldPacking.encode(encoder); + encoder.closeElement(ElementId.ELEM_DATA_ORGANIZATION); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java index f340c80ee8..3bc21f911a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java @@ -32,8 +32,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.listing.Parameter; -import ghidra.program.model.pcode.AddressXML; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.exception.DuplicateNameException; @@ -508,64 +507,64 @@ public class BasicCompilerSpec implements CompilerSpec { } @Override - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); - saveProperties(buffer); - dataOrganization.saveXml(buffer); - ContextSetting.buildContextDataXml(buffer, ctxsetting); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_COMPILER_SPEC); + encodeProperties(encoder); + dataOrganization.encode(encoder); + ContextSetting.encodeContextData(encoder, ctxsetting); if (aggressiveTrim) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_AGGRESSIVETRIM); + encoder.writeBool(AttributeId.ATTRIB_SIGNEXT, aggressiveTrim); + encoder.closeElement(ElementId.ELEM_AGGRESSIVETRIM); } if (stackPointer != null) { - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_STACKPOINTER); } - saveSpaceBases(buffer); - saveMemoryTags(buffer, "global", globalSet); - saveReturnAddress(buffer); // Must come before PrototypeModels - pcodeInject.saveCompilerSpecXml(buffer); + encodeSpaceBases(encoder); + encodeMemoryTags(encoder, ElementId.ELEM_GLOBAL, globalSet); + encodeReturnAddress(encoder); // Must come before PrototypeModels + pcodeInject.encodeCompilerSpec(encoder); if (defaultModel != null) { - buffer.append("\n"); - defaultModel.saveXml(buffer, pcodeInject); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_DEFAULT_PROTO); + defaultModel.encode(encoder, pcodeInject); + encoder.closeElement(ElementId.ELEM_DEFAULT_PROTO); } for (PrototypeModel model : allmodels) { if (model == defaultModel) { continue; // Already emitted } - model.saveXml(buffer, pcodeInject); + model.encode(encoder, pcodeInject); } if (evalCurrentModel != null && evalCurrentModel != defaultModel) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_EVAL_CURRENT_PROTOTYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, evalCurrentModel.name); + encoder.closeElement(ElementId.ELEM_EVAL_CURRENT_PROTOTYPE); } if (evalCalledModel != null && evalCalledModel != defaultModel) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_EVAL_CALLED_PROTOTYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, evalCalledModel.name); + encoder.closeElement(ElementId.ELEM_EVAL_CALLED_PROTOTYPE); } - savePreferSplit(buffer); - saveMemoryTags(buffer, "nohighptr", noHighPtr); - saveMemoryTags(buffer, "readonly", readOnlySet); + encodePreferSplit(encoder); + encodeMemoryTags(encoder, ElementId.ELEM_NOHIGHPTR, noHighPtr); + encodeMemoryTags(encoder, ElementId.ELEM_READONLY, readOnlySet); if (funcPtrAlign != 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_FUNCPTR); + encoder.writeSignedInteger(AttributeId.ATTRIB_ALIGN, funcPtrAlign); + encoder.closeElement(ElementId.ELEM_FUNCPTR); } - saveDeadCodeDelay(buffer); - saveInferPtrBounds(buffer); - buffer.append(""); + encodeDeadCodeDelay(encoder); + encodeInferPtrBounds(encoder); + 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()) { return; } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PROPERTIES); for (Entry property : properties.entrySet()) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PROPERTY); + encoder.writeString(AttributeId.ATTRIB_KEY, property.getKey()); + encoder.writeString(AttributeId.ATTRIB_VALUE, property.getValue()); + encoder.closeElement(ElementId.ELEM_PROPERTY); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_PROPERTIES); } private void restoreProperties(XmlPullParser parser) { @@ -743,16 +742,16 @@ public class BasicCompilerSpec implements CompilerSpec { parser.end(); } - private void saveSpaceBases(StringBuilder buffer) { + private void encodeSpaceBases(Encoder encoder) throws IOException { if (spaceBases == null) { return; } for (Entry> entry : spaceBases.entrySet()) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_SPACEBASE); + encoder.writeString(AttributeId.ATTRIB_NAME, entry.getKey()); + encoder.writeString(AttributeId.ATTRIB_REGISTER, entry.getValue().second); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, entry.getValue().first); + encoder.closeElement(ElementId.ELEM_SPACEBASE); } } @@ -776,15 +775,15 @@ public class BasicCompilerSpec implements CompilerSpec { parser.end(el); } - private void saveReturnAddress(StringBuilder buffer) { + private void encodeReturnAddress(Encoder encoder) throws IOException { if (returnAddress == null) { return; } - buffer.append("\n"); - buffer.append("\n"); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_RETURNADDRESS); + encoder.openElement(ElementId.ELEM_VARNODE); + AddressXML.encodeAttributes(encoder, returnAddress.getAddress(), returnAddress.getSize()); + encoder.closeElement(ElementId.ELEM_VARNODE); + encoder.closeElement(ElementId.ELEM_RETURNADDRESS); } 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))); } - private void saveExtraRanges(StringBuilder buffer, String tagName) { + private void encodeExtraRanges(Encoder encoder, ElementId tag) throws IOException { if (extraRanges == null) { return; } for (Pair> entry : extraRanges) { - if (!entry.first.startsWith(tagName)) { + if (!entry.first.startsWith(tag.getName())) { continue; } String spcName = entry.first.substring(entry.first.indexOf('_') + 1); @@ -832,32 +831,34 @@ public class BasicCompilerSpec implements CompilerSpec { long last = entry.second.second; boolean useFirst = (first != 0); boolean useLast = (last != -1); - 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) { return; } - buffer.append('<').append(tagName).append(">\n"); + encoder.openElement(tag); AddressRangeIterator iter = addrSet.getAddressRanges(); while (iter.hasNext()) { AddressRange range = iter.next(); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_RANGE); + AddressXML.encodeAttributes(encoder, range.getMinAddress(), range.getMaxAddress()); + encoder.closeElement(ElementId.ELEM_RANGE); } - saveExtraRanges(buffer, tagName); - buffer.append("\n"); + encodeExtraRanges(encoder, tag); + encoder.closeElement(tag); } private void restoreMemoryTags(String tagName, XmlPullParser parser, AddressSet addrSet) @@ -903,17 +904,18 @@ public class BasicCompilerSpec implements CompilerSpec { parser.end(el); } - private void savePreferSplit(StringBuilder buffer) { + private void encodePreferSplit(Encoder encoder) throws IOException { if (preferSplit == null || preferSplit.isEmpty()) { return; } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PREFERSPLIT); + encoder.writeString(AttributeId.ATTRIB_STYLE, "inhalf"); for (Varnode varnode : preferSplit) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_VARNODE); + AddressXML.encodeAttributes(encoder, varnode.getAddress(), varnode.getSize()); + encoder.closeElement(ElementId.ELEM_VARNODE); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_PREFERSPLIT); } private void restoreDeadCodeDelay(XmlPullParser parser) { @@ -927,15 +929,15 @@ public class BasicCompilerSpec implements CompilerSpec { parser.end(el); } - private void saveDeadCodeDelay(StringBuilder buffer) { + private void encodeDeadCodeDelay(Encoder encoder) throws IOException { if (deadCodeDelay == null) { return; } for (Pair pair : deadCodeDelay) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_DEADCODEDELAY); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, pair.first); + encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, pair.second.intValue()); + encoder.closeElement(ElementId.ELEM_DEADCODEDELAY); } } @@ -955,18 +957,18 @@ public class BasicCompilerSpec implements CompilerSpec { parser.end(el); } - private void saveInferPtrBounds(StringBuilder buffer) { + private void encodeInferPtrBounds(Encoder encoder) throws IOException { if (inferPtrBounds == null) { return; } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_INFERPTRBOUNDS); for (AddressRange addrRange : inferPtrBounds) { - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_RANGE); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_INFERPTRBOUNDS); } private void setStackPointer(XmlPullParser parser) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java index c85b9ac7f4..f208ee8c33 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.Set; 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.listing.DefaultProgramContext; import ghidra.program.model.listing.Parameter; +import ghidra.program.model.pcode.Encoder; /** * Interface for requesting specific information about the compiler used to @@ -239,11 +241,12 @@ public interface CompilerSpec { public Set getPropertyKeys(); /** - * Marshal this entire specification to an XML stream. An XML document is written with - * root tag \. - * @param buffer is the XML stream + * Encode this entire specification to a stream. A document is written with + * root element \. + * @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 diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ConstantPool.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ConstantPool.java index 4e1698a2a2..5b16281348 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ConstantPool.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ConstantPool.java @@ -15,11 +15,11 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.nio.charset.Charset; import ghidra.program.model.data.DataType; -import ghidra.program.model.pcode.PcodeDataTypeManager; -import ghidra.util.xml.SpecXmlUtils; +import ghidra.program.model.pcode.*; /** * 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 boolean isConstructor = false; - public StringBuilder build(long ref, PcodeDataTypeManager dtmanage) { - StringBuilder buf = new StringBuilder(); - buf.append("\n"); if (tag == PRIMITIVE) { - buf.append(""); - buf.append(SpecXmlUtils.encodeUnsignedInteger(value)); - buf.append("\n"); + encoder.openElement(ElementId.ELEM_VALUE); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_CONTENT, value); + encoder.closeElement(ElementId.ELEM_VALUE); } if (byteData != null) { - buf.append("\n"); + encoder.openElement(ElementId.ELEM_DATA); + encoder.writeSignedInteger(AttributeId.ATTRIB_LENGTH, byteData.length); + StringBuilder buf = new StringBuilder(); int wrap = 0; for (byte val : byteData) { int hival = (val >> 4) & 0xf; @@ -95,16 +96,16 @@ public abstract class ConstantPool { wrap = 0; } } - buf.append("\n"); + encoder.writeString(AttributeId.ATTRIB_CONTENT, buf.toString()); + encoder.closeElement(ElementId.ELEM_DATA); } else { - buf.append(""); - SpecXmlUtils.xmlEscape(buf, token); - buf.append("\n"); + encoder.openElement(ElementId.ELEM_TOKEN); + encoder.writeString(AttributeId.ATTRIB_CONTENT, token); + encoder.closeElement(ElementId.ELEM_TOKEN); } - dtmanage.buildTypeRef(buf, type, type.getLength()); - buf.append("\n"); - return buf; + dtmanage.encodeTypeRef(encoder, type, type.getLength()); + encoder.closeElement(ElementId.ELEM_CPOOLREC); } public void setUTF8Data(String val) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ContextSetting.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ContextSetting.java index c8a8aa60b4..4300639734 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ContextSetting.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ContextSetting.java @@ -15,14 +15,14 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.math.BigInteger; import java.util.Iterator; import java.util.List; import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.program.model.address.Address; -import ghidra.program.model.pcode.AddressXML; -import ghidra.util.xml.SpecXmlUtils; +import ghidra.program.model.pcode.*; import ghidra.xml.*; /** @@ -101,11 +101,11 @@ public final class ContextSetting { } } - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_SET); + encoder.writeString(AttributeId.ATTRIB_NAME, register.getName()); + encoder.writeString(AttributeId.ATTRIB_VAL, value.toString()); + encoder.closeElement(ElementId.ELEM_SET); } /** @@ -164,21 +164,22 @@ public final class ContextSetting { parser.end(); } - public static void buildContextDataXml(StringBuilder buffer, List ctxList) { + public static void encodeContextData(Encoder encoder, List ctxList) + throws IOException { if (ctxList.isEmpty()) { return; } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_CONTEXT_DATA); Iterator iter = ctxList.iterator(); ContextSetting startContext = iter.next(); boolean isContextReg = startContext.register.isProcessorContext(); Address firstAddr = startContext.startAddr; Address lastAddr = startContext.endAddr; while (iter.hasNext()) { - buffer.append(isContextReg ? "\n"); - startContext.saveXml(buffer); + encoder.openElement( + isContextReg ? ElementId.ELEM_CONTEXT_SET : ElementId.ELEM_TRACKED_SET); + AddressXML.encodeAttributes(encoder, firstAddr, lastAddr); + startContext.encode(encoder); while (iter.hasNext()) { startContext = iter.next(); boolean nextIsContext = startContext.register.isProcessorContext(); @@ -198,10 +199,11 @@ public final class ContextSetting { if (shouldBreak) { break; } - startContext.saveXml(buffer); + startContext.encode(encoder); } - buffer.append(isContextReg ? "\n" : "\n"); + encoder.closeElement( + isContextReg ? ElementId.ELEM_CONTEXT_SET : ElementId.ELEM_TRACKED_SET); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_CONTEXT_DATA); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java index a2cb8bb498..6d87618af4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java @@ -15,9 +15,12 @@ */ package ghidra.program.model.lang; +import java.io.IOException; + import ghidra.app.plugin.processors.sleigh.PcodeEmit; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.program.model.listing.Program; +import ghidra.program.model.pcode.Encoder; import ghidra.program.model.pcode.PcodeOp; import ghidra.xml.XmlParseException; import ghidra.xml.XmlPullParser; @@ -142,10 +145,11 @@ public interface InjectPayload { public boolean isIncidentalCopy(); /** - * Write out configuration parameters as a \ XML tag - * @param buffer is the stream to write to + * Encode configuration parameters as a \ element to 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; /** * Restore the payload from an XML stream. The root expected document is diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallfixup.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallfixup.java index cecd3e51fb..ee9921c6c8 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallfixup.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallfixup.java @@ -15,12 +15,13 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; -import ghidra.util.xml.SpecXmlUtils; +import ghidra.program.model.pcode.*; import ghidra.xml.*; public class InjectPayloadCallfixup extends InjectPayloadSleigh { @@ -58,17 +59,16 @@ public class InjectPayloadCallfixup extends InjectPayloadSleigh { } @Override - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_CALLFIXUP); + encoder.writeString(AttributeId.ATTRIB_NAME, name); for (String nm : targetSymbolNames) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_TARGET); + encoder.writeString(AttributeId.ATTRIB_NAME, nm); + encoder.closeElement(ElementId.ELEM_TARGET); } - super.saveXml(buffer); - buffer.append("\n"); + super.encode(encoder); + encoder.closeElement(ElementId.ELEM_CALLFIXUP); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallother.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallother.java index 46cd16b70c..804df7e089 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallother.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadCallother.java @@ -15,9 +15,11 @@ */ package ghidra.program.model.lang; +import java.io.IOException; + import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; -import ghidra.util.xml.SpecXmlUtils; +import ghidra.program.model.pcode.*; import ghidra.xml.*; public class InjectPayloadCallother extends InjectPayloadSleigh { @@ -46,12 +48,11 @@ public class InjectPayloadCallother extends InjectPayloadSleigh { } @Override - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); - super.saveXml(buffer); - buffer.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_CALLOTHERFIXUP); + encoder.writeString(AttributeId.ATTRIB_TARGETOP, name); + super.encode(encoder); + encoder.closeElement(ElementId.ELEM_CALLOTHERFIXUP); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSegment.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSegment.java index 970e50a977..ca0073fb95 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSegment.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSegment.java @@ -15,9 +15,11 @@ */ package ghidra.program.model.lang; +import java.io.IOException; + import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.program.model.address.AddressSpace; -import ghidra.program.model.pcode.AddressXML; +import ghidra.program.model.pcode.*; import ghidra.util.SystemUtilities; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -41,29 +43,28 @@ public class InjectPayloadSegment extends InjectPayloadSleigh { } @Override - public void saveXml(StringBuilder buffer) { - buffer.append(" 0 ? name.substring(0, pos) : name; 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) { - SpecXmlUtils.encodeBooleanAttribute(buffer, "farpointer", supportsFarPointer); + encoder.writeBool(AttributeId.ATTRIB_FARPOINTER, supportsFarPointer); } - buffer.append(">\n"); - super.saveXml(buffer); + super.encode(encoder); if (constResolveSpace != null) { - buffer.append("\n"); - buffer.append("\n"); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_CONSTRESOLVE); + encoder.openElement(ElementId.ELEM_VARNODE); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, constResolveSpace); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, constResolveOffset); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, constResolveSize); + encoder.closeElement(ElementId.ELEM_VARNODE); + encoder.closeElement(ElementId.ELEM_CONSTRESOLVE); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_SEGMENTOP); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java index 6ae28981d7..9db7eac96a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -24,8 +25,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.MemoryAccessException; -import ghidra.program.model.pcode.PcodeOp; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -230,39 +230,40 @@ public class InjectPayloadSleigh implements InjectPayload { } @Override - public void saveXml(StringBuilder buffer) { - buffer.append("= 0) { - SpecXmlUtils.encodeStringAttribute(buffer, "inject", + encoder.writeString(AttributeId.ATTRIB_INJECT, (subType == 0) ? "uponentry" : "uponreturn"); } if (paramShift != 0) { - SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "paramshift", paramShift); + encoder.writeSignedInteger(AttributeId.ATTRIB_PARAMSHIFT, paramShift); } if (pcodeTemplate == null) { - SpecXmlUtils.encodeBooleanAttribute(buffer, "dynamic", true); + encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true); } if (incidentalCopy) { - SpecXmlUtils.encodeBooleanAttribute(buffer, "incidentalcopy", incidentalCopy); + encoder.writeBool(AttributeId.ATTRIB_INCIDENTALCOPY, incidentalCopy); } - buffer.append(">\n"); for (InjectParameter param : inputlist) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_INPUT); + encoder.writeString(AttributeId.ATTRIB_NAME, param.getName()); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, param.getSize()); + encoder.closeElement(ElementId.ELEM_INPUT); } for (InjectParameter param : output) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_OUTPUT); + encoder.writeString(AttributeId.ATTRIB_NAME, param.getName()); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, param.getSize()); + encoder.closeElement(ElementId.ELEM_OUTPUT); } if (pcodeTemplate != null) { // Decompiler will not read the tag - buffer.append(" local tmp:1 = 0; \n"); + encoder.openElement(ElementId.ELEM_BODY); + encoder.writeString(AttributeId.ATTRIB_CONTENT, " local tmp:1 = 0; "); + encoder.closeElement(ElementId.ELEM_BODY); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_PCODE); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java index c874425573..eeefbd071f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.*; 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.AddressSpace; import ghidra.program.model.data.*; -import ghidra.program.model.pcode.AddressXML; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.SystemUtilities; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -437,16 +437,16 @@ public class ParamEntry { flags |= OVERLAPPING; } - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); AddressXML addressSize; if (joinrec == null) { // Treat as unsized address with no size @@ -473,8 +472,8 @@ public class ParamEntry { else { addressSize = new AddressXML(spaceid, addressbase, size, joinrec); } - addressSize.saveXml(buffer); - buffer.append(""); + addressSize.encode(encoder); + encoder.closeElement(ElementId.ELEM_PENTRY); } public void restoreXml(XmlPullParser parser, CompilerSpec cspec, List curList, diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamList.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamList.java index 7ba013089d..ff1042f5ce 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamList.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamList.java @@ -15,12 +15,14 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.ArrayList; import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.Program; import ghidra.program.model.listing.VariableStorage; +import ghidra.program.model.pcode.Encoder; import ghidra.xml.XmlParseException; import ghidra.xml.XmlPullParser; @@ -44,7 +46,7 @@ public interface ParamList { public void assignMap(Program prog, DataType[] proto, ArrayList res, 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; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java index 54ef79d1ee..c04a155600 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.ArrayList; 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.data.*; import ghidra.program.model.listing.*; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.SystemUtilities; import ghidra.util.exception.InvalidInputException; import ghidra.util.xml.SpecXmlUtils; @@ -199,39 +200,37 @@ public class ParamListStandard implements ParamList { } @Override - public void saveXml(StringBuilder buffer, boolean isInput) { - buffer.append(isInput ? "\n"); int curgroup = -1; for (ParamEntry el : entry) { if (curgroup >= 0) { if (!el.isGrouped() || el.getGroup() != curgroup) { - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_GROUP); curgroup = -1; } } if (el.isGrouped()) { if (curgroup < 0) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_GROUP); curgroup = el.getGroup(); } } - el.saveXml(buffer); - buffer.append('\n'); + el.encode(encoder); } if (curgroup >= 0) { - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_GROUP); } - buffer.append(isInput ? "" : ""); + encoder.closeElement(isInput ? ElementId.ELEM_INPUT : ElementId.ELEM_OUTPUT); } private void parsePentry(XmlPullParser parser, CompilerSpec cspec, ArrayList pe, diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeInjectLibrary.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeInjectLibrary.java index 9f667772de..7572ac8d54 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeInjectLibrary.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeInjectLibrary.java @@ -23,6 +23,7 @@ import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; import ghidra.program.model.lang.InjectPayload.InjectParameter; import ghidra.program.model.listing.Program; +import ghidra.program.model.pcode.Encoder; import ghidra.sleigh.grammar.Location; import ghidra.util.Msg; import ghidra.xml.XmlParseException; @@ -375,25 +376,26 @@ public class PcodeInjectLibrary { } /** - * Save the parts of the inject library that come from the compiler spec - * to the output stream as XML tags - * @param buffer is the output stream + * Encode the parts of the inject library that come from the compiler spec + * to 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()) { if (injectPayload instanceof InjectPayloadSleigh) { - ((InjectPayloadSleigh) injectPayload).saveXml(buffer); + ((InjectPayloadSleigh) injectPayload).encode(encoder); } } for (InjectPayload injectPayload : callOtherFixupMap.values()) { if (injectPayload instanceof InjectPayloadSleigh) { - ((InjectPayloadSleigh) injectPayload).saveXml(buffer); + ((InjectPayloadSleigh) injectPayload).encode(encoder); } } for (InjectPayload injectPayload : exePcodeMap.values()) { if (injectPayload instanceof InjectPayloadSegment) { if (injectPayload.getSource().startsWith("cspec")) { - ((InjectPayloadSleigh) injectPayload).saveXml(buffer); + ((InjectPayloadSleigh) injectPayload).encode(encoder); } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java index de07c76f37..5902caa748 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java @@ -15,14 +15,14 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.ArrayList; import ghidra.program.database.SpecExtension; import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.listing.*; -import ghidra.program.model.pcode.AddressXML; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.SystemUtilities; import ghidra.util.exception.InvalidInputException; import ghidra.util.xml.SpecXmlUtils; @@ -417,89 +417,87 @@ public class PrototypeModel { } /** - * Marshal this object as XML to an output buffer - * @param buffer is the output buffer + * Encode this object to an output stream + * @param encoder is the stream encoder * @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) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_MODELALIAS); + encoder.writeString(AttributeId.ATTRIB_NAME, name); + encoder.writeString(AttributeId.ATTRIB_PARENT, compatModel.name); + encoder.closeElement(ElementId.ELEM_MODELALIAS); return; } - buffer.append("\n"); - inputParams.saveXml(buffer, true); - buffer.append('\n'); - outputParams.saveXml(buffer, false); - buffer.append('\n'); + inputParams.encode(encoder, true); + outputParams.encode(encoder, false); if (hasUponEntry || hasUponReturn) { InjectPayload payload = injectLibrary.getPayload(InjectPayload.CALLMECHANISM_TYPE, getInjectName()); - payload.saveXml(buffer); + payload.encode(encoder); } if (unaffected != null) { - buffer.append("\n"); - writeVarnodes(buffer, unaffected); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_UNAFFECTED); + encodeVarnodes(encoder, unaffected); + encoder.closeElement(ElementId.ELEM_UNAFFECTED); } if (killedbycall != null) { - buffer.append("\n"); - writeVarnodes(buffer, killedbycall); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_KILLEDBYCALL); + encodeVarnodes(encoder, killedbycall); + encoder.closeElement(ElementId.ELEM_KILLEDBYCALL); } if (likelytrash != null) { - buffer.append("\n"); - writeVarnodes(buffer, likelytrash); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_LIKELYTRASH); + encodeVarnodes(encoder, likelytrash); + encoder.closeElement(ElementId.ELEM_LIKELYTRASH); } if (returnaddress != null) { - buffer.append("\n"); - writeVarnodes(buffer, returnaddress); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_RETURNADDRESS); + encodeVarnodes(encoder, returnaddress); + encoder.closeElement(ElementId.ELEM_RETURNADDRESS); } if (localRange != null && !localRange.isEmpty()) { - buffer.append("\n"); - writeAddressSet(buffer, localRange); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_LOCALRANGE); + encodeAddressSet(encoder, localRange); + encoder.closeElement(ElementId.ELEM_LOCALRANGE); } if (paramRange != null && !paramRange.isEmpty()) { - buffer.append("\n"); - writeAddressSet(buffer, paramRange); - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PARAMRANGE); + encodeAddressSet(encoder, paramRange); + encoder.closeElement(ElementId.ELEM_PARAMRANGE); } - buffer.append("\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) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_VARNODE); + AddressXML.encodeAttributes(encoder, vn.getAddress(), vn.getSize()); + encoder.closeElement(ElementId.ELEM_VARNODE); } } @@ -523,7 +521,7 @@ public class PrototypeModel { return res; } - private void writeAddressSet(StringBuilder buffer, AddressSet addressSet) { + private void encodeAddressSet(Encoder encoder, AddressSet addressSet) throws IOException { AddressRangeIterator iter = addressSet.getAddressRanges(); while (iter.hasNext()) { AddressRange addrRange = iter.next(); @@ -543,22 +541,22 @@ public class PrototypeModel { if (first < 0 && last >= 0) { // Range crosses 0 first &= mask; // Split out the piece coming before 0 - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_RANGE); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, mask); + encoder.closeElement(ElementId.ELEM_RANGE); // Reset first,last to be the piece coming after 0 first = 0; } first &= mask; last &= mask; } - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_RANGE); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, first); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last); + encoder.closeElement(ElementId.ELEM_RANGE); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModelMerged.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModelMerged.java index 3f94f8d8bb..a23212edf2 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModelMerged.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModelMerged.java @@ -15,12 +15,13 @@ */ package ghidra.program.model.lang; +import java.io.IOException; import java.util.*; import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Parameter; -import ghidra.util.xml.SpecXmlUtils; +import ghidra.program.model.pcode.*; import ghidra.xml.*; /** @@ -54,16 +55,15 @@ public class PrototypeModelMerged extends PrototypeModel { } @Override - public void saveXml(StringBuilder buffer, PcodeInjectLibrary injectLibrary) { - buffer.append("\n"); + public void encode(Encoder encoder, PcodeInjectLibrary injectLibrary) throws IOException { + encoder.openElement(ElementId.ELEM_RESOLVEPROTOTYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, name); for (PrototypeModel model : modellist) { - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_MODEL); + encoder.writeString(AttributeId.ATTRIB_NAME, model.name); + encoder.closeElement(ElementId.ELEM_MODEL); } - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_RESOLVEPROTOTYPE); } public void restoreXml(XmlPullParser parser, List modelList) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AddressXML.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AddressXML.java index bc003626b8..bb3a803ba3 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AddressXML.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AddressXML.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.ArrayList; import ghidra.program.model.address.Address; @@ -127,10 +128,11 @@ public class AddressXML { } /** - * Write this sized address as an \ XML tag. - * @param buffer is the buffer to write to + * Encode this sized address as an \ element to the stream + * @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) { long logicalSize = size; long sizeSum = 0; @@ -140,18 +142,18 @@ public class AddressXML { if (sizeSum == size) { logicalSize = 0; } - buildXML(buffer, joinRecord, logicalSize); + encode(encoder, joinRecord, logicalSize); return; } - 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. - * This assumes the XML tag name has already been emitted. - * @param buf is the XML stream + * Encode "space" and "offset" attributes for the current element, describing the + * given Address to the stream. + * @param encoder is the stream encoder * @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(); if (space.isOverlaySpace()) { if (space.getType() != AddressSpace.TYPE_OTHER) { @@ -445,18 +448,20 @@ public class AddressXML { addr = space.getAddress(addr.getOffset()); } } - SpecXmlUtils.encodeStringAttribute(buf, "space", space.getName()); - SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset()); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_OFFSET, addr.getUnsignedOffset()); } /** - * Append "space" "offset" and "size" attributes describing the given memory range to the XML stream. - * This assumes the XML tag name has already been emitted. - * @param buf is the XML stream + * Encode "space" "offset" and "size" attributes for the current element, describing + * the given memory range to the stream. + * @param encoder is the stream encoder * @param addr is the starting Address 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(); if (space.isOverlaySpace()) { if (space.getType() != AddressSpace.TYPE_OTHER) { @@ -464,19 +469,22 @@ public class AddressXML { addr = space.getAddress(addr.getOffset()); } } - SpecXmlUtils.encodeStringAttribute(buf, "space", space.getName()); - SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset()); - SpecXmlUtils.encodeSignedIntegerAttribute(buf, "size", size); + + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); + 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. - * This assumes the XML tag name has already been emitted. - * @param buffer is the XML stream + * Encode a memory range, as "space", "first", and "last" attributes, for the current element, + * to the stream. + * @param encoder is the stream encoder * @param startAddr is the first 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(); long offset = startAddr.getOffset(); long size = endAddr.getOffset() - offset + 1; @@ -492,91 +500,114 @@ public class AddressXML { long last = offset + size - 1; boolean useFirst = (offset != 0); boolean useLast = (last != -1); - SpecXmlUtils.encodeStringAttribute(buffer, "space", space.getName()); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); if (useFirst) { - SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "first", offset); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, offset); } if (useLast) { - SpecXmlUtils.encodeUnsignedIntegerAttribute(buffer, "last", last); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, last); } } /** - * Write out the given Address as an \ tag to the XML stream + * Encode the given Address as an \ element to the stream * - * @param buf is the XML stream - * @param addr -- Address to convert to XML + * @param encoder is the stream encoder + * @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)) { - buf.append(""); + encoder.closeElement(ElementId.ELEM_ADDR); return; } - buf.append(""); + encodeAttributes(encoder, addr); + encoder.closeElement(ElementId.ELEM_ADDR); } /** - * Write out the given Address and a size as an \ tag to the XML stream + * Encode the given Address and a size as an \ element to the stream * - * @param buf is the XML stream + * @param encoder is the stream encoder * @param addr is the given Address * @param size is the given size + * @throws IOException for errors in the underlying stream */ - public static void buildXML(StringBuilder buf, Address addr, int size) { - buf.append(""); + public static void encode(Encoder encoder, Address addr, int size) throws IOException { + encoder.openElement(ElementId.ELEM_ADDR); + encodeAttributes(encoder, addr, size); + 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(); if (space.isOverlaySpace()) { space = space.getPhysicalSpace(); addr = space.getAddress(addr.getOffset()); } - buf.append(space.getName()); - buf.append(":0x"); + buffer.append(space.getName()); + buffer.append(":0x"); long off = addr.getUnsignedOffset(); - buf.append(Long.toHexString(off)); - buf.append(':'); - buf.append(Integer.toString(size)); + buffer.append(Long.toHexString(off)); + buffer.append(':'); + buffer.append(Integer.toString(vn.getSize())); + return buffer.toString(); } /** - * Write out a sequence of Varnodes as a single \ tag to an XML stream. + * Encode a sequence of Varnodes as a single \ element to the stream. * If there is more than one Varnode, or if the logical size is non-zero, - * the \ tag will specify the address space as "join" and will have + * the \ element will specify the address space as "join" and will have * additional "piece" attributes. * - * @param buf is the XML stream + * @param encoder is the stream encoder * @param varnodes is the sequence of storage varnodes * @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) { - buf.append(""); + encoder.openElement(ElementId.ELEM_ADDR); + encoder.closeElement(ElementId.ELEM_ADDR); return; } 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; } - buf.append(" 2) { + encoder.writeString(AttributeId.ATTRIB_PIECE3, encodeVarnodePiece(varnodes[2])); + } + 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) { - buf.append(" logicalsize=\"").append(logicalsize).append('\"'); + encoder.writeSignedInteger(AttributeId.ATTRIB_LOGICALSIZE, logicalsize); } - buf.append("/>"); + encoder.closeElement(ElementId.ELEM_ADDR); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java index 4098ab5ddf..88217afcc6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java @@ -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. */ public class AttributeId { - private static HashMap lookupAttributeId = new HashMap<>(); + private static HashMap lookupAttributeId = new HashMap<>(); private final String name; // The name of the attribute private final int id; // The (internal) id of the attribute public AttributeId(String nm, int i) { name = nm; id = i; - lookupAttributeId.put(nm, i); + if (null != lookupAttributeId.put(nm, this)) { + throw new RuntimeException("Duplicate AttributeId: " + nm); + } } public final String getName() { @@ -56,11 +58,8 @@ public class AttributeId { * @return the associated id */ public static int find(String nm) { - Integer res = lookupAttributeId.get(nm); - if (res != null) { - return res.intValue(); - } - return ATTRIB_UNKNOWN.id; + AttributeId res = lookupAttributeId.getOrDefault(nm, ATTRIB_UNKNOWN); + return res.id; } // 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_UNIQ = new AttributeId("uniq", 29); - // architecture - public static final AttributeId ATTRIB_ADJUSTVMA = new AttributeId("adjustvma", 30); - public static final AttributeId ATTRIB_ENABLE = new AttributeId("enable", 31); - public static final AttributeId ATTRIB_GROUP = new AttributeId("group", 32); - public static final AttributeId ATTRIB_GROWTH = new AttributeId("growth", 33); - public static final AttributeId ATTRIB_LOADERSYMBOLS = new AttributeId("loadersymbols", 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); + // varnode + public static final AttributeId ATTRIB_ADDRTIED = new AttributeId("addrtied", 30); + public static final AttributeId ATTRIB_GRP = new AttributeId("grp", 31); + public static final AttributeId ATTRIB_INPUT = new AttributeId("input", 32); + public static final AttributeId ATTRIB_PERSISTS = new AttributeId("persists", 33); + public static final AttributeId ATTRIB_UNAFF = new AttributeId("unaff", 34); - // block - public static final AttributeId ATTRIB_ALTINDEX = new AttributeId("altindex", 40); - public static final AttributeId ATTRIB_DEPTH = new AttributeId("depth", 41); - public static final AttributeId ATTRIB_END = new AttributeId("end", 42); - public static final AttributeId ATTRIB_OPCODE = new AttributeId("opcode", 43); - public static final AttributeId ATTRIB_REV = new AttributeId("rev", 44); + // prettyprint + public static final AttributeId ATTRIB_BLOCKREF = new AttributeId("blockref", 35); + public static final AttributeId ATTRIB_CLOSE = new AttributeId("close", 36); + public static final AttributeId ATTRIB_COLOR = new AttributeId("color", 37); + public static final AttributeId ATTRIB_INDENT = new AttributeId("indent", 38); + 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 - public static final AttributeId ATTRIB_A = new AttributeId("a", 45); - public static final AttributeId ATTRIB_B = new AttributeId("b", 46); - public static final AttributeId ATTRIB_LENGTH = new AttributeId("length", 47); - public static final AttributeId ATTRIB_TAG = new AttributeId("tag", 48); + // translate + public static final AttributeId ATTRIB_CODE = new AttributeId("code", 43); + public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 44); + public static final AttributeId ATTRIB_DEFAULTSPACE = new AttributeId("defaultspace", 45); + 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 - public static final AttributeId ATTRIB_CAT = new AttributeId("cat", 49); - public static final AttributeId ATTRIB_FIELD = new AttributeId("field", 50); - public static final AttributeId ATTRIB_MERGE = new AttributeId("merge", 51); - public static final AttributeId ATTRIB_SCOPEIDBYNAME = new AttributeId("scopeidbyname", 52); - public static final AttributeId ATTRIB_VOLATILE = new AttributeId("volatile", 53); + public static final AttributeId ATTRIB_CAT = new AttributeId("cat", 61); + public static final AttributeId ATTRIB_FIELD = new AttributeId("field", 62); + public static final AttributeId ATTRIB_MERGE = new AttributeId("merge", 63); + public static final AttributeId ATTRIB_SCOPEIDBYNAME = new AttributeId("scopeidbyname", 64); + public static final AttributeId ATTRIB_VOLATILE = new AttributeId("volatile", 65); - // fspec - public static final AttributeId ATTRIB_CUSTOM = new AttributeId("custom", 54); - public static final AttributeId ATTRIB_DOTDOTDOT = new AttributeId("dotdotdot", 55); - public static final AttributeId ATTRIB_EXTENSION = new AttributeId("extension", 56); - 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); + // variable + public static final AttributeId ATTRIB_CLASS = new AttributeId("class", 66); + public static final AttributeId ATTRIB_REPREF = new AttributeId("repref", 67); + public static final AttributeId ATTRIB_SYMREF = new AttributeId("symref", 68); // 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 public static final AttributeId ATTRIB_VECTOR_LANE_SIZES = - new AttributeId("vector_lane_sizes", 103); + new AttributeId("vector_lane_sizes", 130); - // translate - public static final AttributeId ATTRIB_CODE = new AttributeId("code", 104); - public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 105); - 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); + // jumptable + public static final AttributeId ATTRIB_LABEL = new AttributeId("label", 131); + public static final AttributeId ATTRIB_NUM = new AttributeId("num", 132); // varmap - public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 129); - public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 130); + public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 133); + public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 134); - // varnode - public static final AttributeId ATTRIB_ADDRTIED = new AttributeId("addrtied", 131); - 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); + // loadimage_xml +// public static final AttributeId ATTRIB_ARCH = new AttributeId("arch", 135); - // prettyprint - public static final AttributeId ATTRIB_BLOCKREF = new AttributeId("blockref", 136); - public static final AttributeId ATTRIB_CLOSE = new AttributeId("close", 137); - public static final AttributeId ATTRIB_COLOR = new AttributeId("color", 138); - public static final AttributeId ATTRIB_INDENT = new AttributeId("indent", 139); - public static final AttributeId ATTRIB_OFF = new AttributeId("off", 140); - public static final AttributeId ATTRIB_OPEN = new AttributeId("open", 141); - public static final AttributeId ATTRIB_OPREF = new AttributeId("opref", 142); - public static final AttributeId ATTRIB_VARREF = new AttributeId("varref", 143); + // sleigh_arch +// public static final AttributeId ATTRIB_DEPRECATED = new AttributeId("deprecated", 136); +// public static final AttributeId ATTRIB_ENDIAN = new AttributeId("endian", 137); +// public static final AttributeId ATTRIB_PROCESSOR = new AttributeId("processor", 138); +// public static final AttributeId ATTRIB_PROCESSORSPEC = new AttributeId("processorspec", 139); +// public static final AttributeId ATTRIB_SLAFILE = new AttributeId("slafile", 140); +// public static final AttributeId ATTRIB_SPEC = new AttributeId("spec", 141); +// public static final AttributeId ATTRIB_TARGET = new AttributeId("target", 142); +// 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); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCondition.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCondition.java index 2cb9679c21..d036288abc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCondition.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCondition.java @@ -15,8 +15,9 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.lang.UnknownInstructionException; -import ghidra.util.xml.SpecXmlUtils; /** * Block representing and '&&' or '||' control flow path within a conditional expression @@ -41,14 +42,14 @@ public class BlockCondition extends BlockGraph { } @Override - public void saveXmlHeader(StringBuilder buffer) { - super.saveXmlHeader(buffer); + protected void encodeHeader(Encoder encoder) throws IOException { + super.encodeHeader(encoder); String opcodename = PcodeOp.getMnemonic(opcode); - SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename); + encoder.writeString(AttributeId.ATTRIB_OPCODE, opcodename); } @Override - public void decodeHeader(Decoder decoder) throws PcodeXMLException { + protected void decodeHeader(Decoder decoder) throws PcodeXMLException { super.decodeHeader(decoder); String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE); try { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCopy.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCopy.java index 2ee6d87c02..da9aa70e38 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCopy.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockCopy.java @@ -15,8 +15,9 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; -import ghidra.util.xml.SpecXmlUtils; /** * Placeholder for a basic block (BlockBasic) within a structured @@ -78,13 +79,13 @@ public class BlockCopy extends PcodeBlock { } @Override - public void saveXmlHeader(StringBuilder buf) { - super.saveXmlHeader(buf); - SpecXmlUtils.encodeSignedIntegerAttribute(buf, "altindex", altindex); + protected void encodeHeader(Encoder encoder) throws IOException { + super.encodeHeader(encoder); + encoder.writeSignedInteger(AttributeId.ATTRIB_ALTINDEX, altindex); } @Override - public void decodeHeader(Decoder decoder) throws PcodeXMLException { + protected void decodeHeader(Decoder decoder) throws PcodeXMLException { super.decodeHeader(decoder); altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGoto.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGoto.java index bc0e86510b..68f5cf1531 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGoto.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGoto.java @@ -16,9 +16,6 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; - -import ghidra.util.xml.SpecXmlUtils; /** * A "plain" goto block @@ -51,21 +48,19 @@ public class BlockGoto extends BlockGraph { } @Override - public void saveXmlBody(Writer writer) throws IOException { - super.saveXmlBody(writer); - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - writer.write(buf.toString()); + encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex()); + encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth); + encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, gototype); + encoder.closeElement(ElementId.ELEM_TARGET); } @Override - public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { + protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { super.decodeBody(decoder, resolver); int el = decoder.openElement(ElementId.ELEM_TARGET); int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGraph.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGraph.java index b1305ddb49..e1e42db012 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGraph.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockGraph.java @@ -16,11 +16,8 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; -import ghidra.util.xml.SpecXmlUtils; - /** * A block (with in edges and out edges) that contains other blocks * @@ -141,24 +138,22 @@ public class BlockGraph extends PcodeBlock { } @Override - public void saveXmlBody(Writer writer) throws IOException { - super.saveXmlBody(writer); + protected void encodeBody(Encoder encoder) throws IOException { + super.encodeBody(encoder); for (PcodeBlock bl : list) { - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - writer.write(buf.toString()); + encoder.writeString(AttributeId.ATTRIB_TYPE, name); + encoder.closeElement(ElementId.ELEM_BHEAD); } for (PcodeBlock bl : list) { - bl.saveXml(writer); + bl.encode(encoder); } } @Override - public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { + protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { BlockMap newresolver = new BlockMap(resolver); super.decodeBody(decoder, newresolver); ArrayList tmplist = new ArrayList<>(); @@ -186,7 +181,7 @@ public class BlockGraph extends PcodeBlock { * @param decoder is the stream decoder * @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()); decode(decoder, resolver); resolver.resolveGotoReferences(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockIfGoto.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockIfGoto.java index 0572ad281a..c3aa8926a5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockIfGoto.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockIfGoto.java @@ -16,9 +16,6 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; - -import ghidra.util.xml.SpecXmlUtils; /** * Block representing an if () goto control flow @@ -54,21 +51,19 @@ public class BlockIfGoto extends BlockGraph { } @Override - public void saveXmlBody(Writer writer) throws IOException { - super.saveXmlBody(writer); + protected void encodeBody(Encoder encoder) throws IOException { + super.encodeBody(encoder); PcodeBlock leaf = gototarget.getFrontLeaf(); int depth = gototarget.calcDepth(leaf); - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - writer.write(buf.toString()); + encoder.openElement(ElementId.ELEM_TARGET); + encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex()); + encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth); + encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, gototype); + encoder.closeElement(ElementId.ELEM_TARGET); } @Override - public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { + protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { super.decodeBody(decoder, resolver); int el = decoder.openElement(ElementId.ELEM_TARGET); int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockMultiGoto.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockMultiGoto.java index 11f35dd042..c5ecc38648 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockMultiGoto.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/BlockMultiGoto.java @@ -16,11 +16,8 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; -import ghidra.util.xml.SpecXmlUtils; - /** * A block representing a 2-or-more control flow branchpoint * @@ -45,24 +42,21 @@ public class BlockMultiGoto extends BlockGraph { } @Override - public void saveXmlBody(Writer writer) throws IOException { - super.saveXmlBody(writer); + protected void encodeBody(Encoder encoder) throws IOException { + super.encodeBody(encoder); for (PcodeBlock gototarget : targets) { - - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - writer.write(buf.toString()); + encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, leaf.getIndex()); + encoder.writeSignedInteger(AttributeId.ATTRIB_DEPTH, depth); +// encoder.writeSignedInteger(AttributeId.ATTRIB_TYPE, 2); // Always a break + encoder.closeElement(ElementId.ELEM_TARGET); } } @Override - public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { + protected void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException { super.decodeBody(decoder, resolver); for (;;) { int el = decoder.peekElement(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Decoder.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Decoder.java index d1013ca9f4..d4df02d70a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Decoder.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Decoder.java @@ -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 * 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. - * This attribute will not be traversed by getNextAttribute(). + * This attribute will not be traversed by getNextAttributeId(). */ public interface Decoder { @@ -67,7 +67,7 @@ public interface Decoder { * Open (traverse into) the next child element of the current parent. * The child becomes the current parent. * 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(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicEntry.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicEntry.java index 82bb688066..8f894de711 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicEntry.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicEntry.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.listing.Program; @@ -68,9 +70,11 @@ public class DynamicEntry extends SymbolEntry { } @Override - public void saveXml(StringBuilder buf) { - buf.append(""); - buildRangelistXML(buf); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_HASH); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_VAL, hash); + encoder.closeElement(ElementId.ELEM_HASH); + encodeRangelist(encoder); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java index d2f51363d2..9a4e040d33 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java @@ -28,21 +28,23 @@ import java.util.HashMap; * as an attribute. */ public class ElementId { - private static HashMap lookupElementId = new HashMap<>(); + private static HashMap lookupElementId = new HashMap<>(); private String name; // The name of the element private int id; // The (internal) id of the element public ElementId(String nm, int i) { name = nm; 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; } - public int getId() { + public final int getId() { return id; } @@ -52,11 +54,8 @@ public class ElementId { * @return the associated id */ public static int find(String nm) { - Integer res = lookupElementId.get(nm); - if (res != null) { - return res.intValue(); - } - return ELEM_UNKNOWN.id; + ElementId res = lookupElementId.getOrDefault(nm, ELEM_UNKNOWN); + return res.id; } 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_VALUE = new ElementId("value", 9); public static final ElementId ELEM_VOID = new ElementId("void", 10); + public static final ElementId ELEM_ADDR = new ElementId("addr", 11); // 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_RANGELIST = new ElementId("rangelist", 13); 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_VARNODE = new ElementId("varnode", 16); - // architecture - public static final ElementId ELEM_ADDRESS_SHIFT_AMOUNT = - new ElementId("address_shift_amount", 17); - public static final ElementId ELEM_AGGRESSIVETRIM = new ElementId("aggressivetrim", 18); - public static final ElementId ELEM_COMPILER_SPEC = new ElementId("compiler_spec", 19); - public static final ElementId ELEM_DATA_SPACE = new ElementId("data_space", 20); - public static final ElementId ELEM_DEFAULT_MEMORY_BLOCKS = - new ElementId("default_memory_blocks", 21); - public static final ElementId ELEM_DEFAULT_PROTO = new ElementId("default_proto", 22); - public static final ElementId ELEM_DEFAULT_SYMBOLS = new ElementId("default_symbols", 23); - public static final ElementId ELEM_EVAL_CALLED_PROTOTYPE = - 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); + // prettyprint + public static final ElementId ELEM_BREAK = new ElementId("break", 17); + public static final ElementId ELEM_CLANG_DOCUMENT = new ElementId("clang_document", 18); + public static final ElementId ELEM_FUNCNAME = new ElementId("funcname", 19); + public static final ElementId ELEM_FUNCPROTO = new ElementId("funcproto", 20); + public static final ElementId ELEM_LABEL = new ElementId("label", 21); + public static final ElementId ELEM_RETURN_TYPE = new ElementId("return_type", 22); + public static final ElementId ELEM_STATEMENT = new ElementId("statement", 23); + public static final ElementId ELEM_SYNTAX = new ElementId("syntax", 24); + public static final ElementId ELEM_VARDECL = new ElementId("vardecl", 25); + public static final ElementId ELEM_VARIABLE = new ElementId("variable", 26); - // block - public static final ElementId ELEM_BHEAD = new ElementId("bhead", 47); - public static final ElementId ELEM_BLOCK = new ElementId("block", 48); - public static final ElementId ELEM_BLOCKEDGE = new ElementId("blockedge", 49); - public static final ElementId ELEM_EDGE = new ElementId("edge", 50); - - // callgraph - public static final ElementId ELEM_CALLGRAPH = new ElementId("callgraph", 51); - public static final ElementId ELEM_NODE = new ElementId("node", 52); - - // comment - 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); + // transform + public static final ElementId ELEM_OP = new ElementId("op", 27); + public static final ElementId ELEM_SLEIGH = new ElementId("sleigh", 28); + public static final ElementId ELEM_SPACE = new ElementId("space", 29); + public static final ElementId ELEM_SPACEID = new ElementId("spaceid", 30); + public static final ElementId ELEM_SPACES = new ElementId("spaces", 31); + public static final ElementId ELEM_SPACE_BASE = new ElementId("space_base", 32); + public static final ElementId ELEM_SPACE_OTHER = new ElementId("space_other", 33); + public static final ElementId ELEM_SPACE_OVERLAY = new ElementId("space_overlay", 34); + public static final ElementId ELEM_SPACE_UNIQUE = new ElementId("space_unique", 35); + public static final ElementId ELEM_TRUNCATE_SPACE = new ElementId("truncate_space", 36); // type - public static final ElementId ELEM_CORETYPES = new ElementId("coretypes", 190); - public static final ElementId ELEM_DATA_ORGANIZATION = new ElementId("data_organization", 191); - public static final ElementId ELEM_DEF = new ElementId("def", 192); - public static final ElementId ELEM_ENTRY = new ElementId("entry", 193); - public static final ElementId ELEM_ENUM = new ElementId("enum", 194); - public static final ElementId ELEM_FIELD = new ElementId("field", 195); - public static final ElementId ELEM_INTEGER_SIZE = new ElementId("integer_size", 196); - public static final ElementId ELEM_LONG_SIZE = new ElementId("long_size", 197); - public static final ElementId ELEM_SIZE_ALIGNMENT_MAP = - new ElementId("size_alignment_map", 198); - public static final ElementId ELEM_TYPE = new ElementId("type", 199); - public static final ElementId ELEM_TYPEGRP = new ElementId("typegrp", 200); - public static final ElementId ELEM_TYPEREF = new ElementId("typeref", 201); + public static final ElementId ELEM_ABSOLUTE_MAX_ALIGNMENT = + new ElementId("absolute_max_alignment", 37); + public static final ElementId ELEM_BITFIELD_PACKING = new ElementId("bitfield_packing", 38); + public static final ElementId ELEM_CHAR_SIZE = new ElementId("char_size", 39); + public static final ElementId ELEM_CHAR_TYPE = new ElementId("char_type", 40); + public static final ElementId ELEM_CORETYPES = new ElementId("coretypes", 41); + public static final ElementId ELEM_DATA_ORGANIZATION = new ElementId("data_organization", 42); + public static final ElementId ELEM_DEF = new ElementId("def", 43); + public static final ElementId ELEM_DEFAULT_ALIGNMENT = new ElementId("default_alignment", 44); + public static final ElementId ELEM_DEFAULT_POINTER_ALIGNMENT = + new ElementId("default_pointer_alignment", 45); + public static final ElementId ELEM_DOUBLE_SIZE = new ElementId("double_size", 46); + 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 - public static final ElementId ELEM_CONSTRESOLVE = new ElementId("constresolve", 202); - public static final ElementId ELEM_JUMPASSIST = new ElementId("jumpassist", 203); - public static final ElementId ELEM_SEGMENTOP = new ElementId("segmentop", 204); + // database + public static final ElementId ELEM_COLLISION = new ElementId("collision", 67); + public static final ElementId ELEM_DB = new ElementId("db", 68); + 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 - 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 - public static final ElementId ELEM_LOCALDB = new ElementId("localdb", 206); - - // 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); + public static final ElementId ELEM_LOCALDB = new ElementId("localdb", 228); // 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); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java index 52ca8615f7..9322043f77 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.AddressSpace; /** @@ -42,53 +44,66 @@ public interface Encoder { * Begin a new element in the encoding * The element will have the given ElementId annotation and becomes the \e current element. * @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 * The current element must match the given annotation or an exception is thrown. * @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 * The boolean data is associated with the given AttributeId annotation and the current open element. * @param attribId is the given AttributeId annotation * @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 * The integer is associated with the given AttributeId annotation and the current open element. * @param attribId is the given AttributeId annotation * @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 * The integer is associated with the given AttributeId annotation and the current open element. * @param attribId is the given AttributeId annotation * @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 * The string is associated with the given AttributeId annotation and the current open element. * @param attribId is the given AttributeId annotation * @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 * The address space is associated with the given AttributeId annotation and the current open element. * @param attribId is the given AttributeId annotation * @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(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java index 55bacd0caf..fa01722245 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/EquateSymbol.java @@ -15,9 +15,10 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; -import ghidra.util.xml.SpecXmlUtils; public class EquateSymbol extends HighSymbol { @@ -104,9 +105,9 @@ public class EquateSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { - buf.append("\n"); - buf.append(" 0x"); - buf.append(Long.toHexString(value)); - buf.append("\n"); - buf.append("\n"); + encoder.openElement(ElementId.ELEM_VALUE); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_CONTENT, value); + encoder.closeElement(ElementId.ELEM_VALUE); + encoder.closeElement(ElementId.ELEM_EQUATESYMBOL); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java index 4f4db0eb40..c5a16daa80 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.data.*; import ghidra.program.model.lang.*; import ghidra.program.model.listing.*; @@ -314,49 +316,48 @@ public class FunctionPrototype { } /** - * append an XML string representing this function prototype - * @param res is where the string should be appended + * Encode this function prototype to a stream. + * @param encoder is the stream encoder * @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) { - res.append("\n"); - res.append(" \n "); int sz = returntype.getLength(); if (sz < 0) { Msg.warn(this, "Bad returntype size"); @@ -368,46 +369,46 @@ public class FunctionPrototype { if (sz != returnstorage.size()) { // If the sizes do no match logicalsize = sz; // force the logical size on the varnode } - AddressXML.buildXML(res, returnstorage.getVarnodes(), logicalsize); - res.append("\n "); + AddressXML.encode(encoder, returnstorage.getVarnodes(), logicalsize); } else { - // Decompiler will use model for storage - res.append("\n "); // Don't specify where return type is stored + // Decompiler will use model for storage. Don't specify where return type is stored + encoder.openElement(ElementId.ELEM_ADDR); + encoder.closeElement(ElementId.ELEM_ADDR); } - dtmanage.buildTypeRef(res, returntype, sz); - res.append(" \n"); + dtmanage.encodeTypeRef(encoder, returntype, sz); + encoder.closeElement(ElementId.ELEM_RETURNSYM); if (injectname != null) { - res.append(""); - res.append(injectname); - res.append("\n"); + encoder.openElement(ElementId.ELEM_INJECT); + encoder.writeString(AttributeId.ATTRIB_CONTENT, injectname); + encoder.closeElement(ElementId.ELEM_INJECT); } if (params != null) { - res.append("\n"); + encoder.openElement(ElementId.ELEM_INTERNALLIST); for (ParameterDefinition param : params) { - res.append(" 0)) { - res.append(" name=\"").append(name).append('\"'); + encoder.writeString(AttributeId.ATTRIB_NAME, name); namelock = true; } - res.append(" typelock=\"true\" namelock=\""); - res.append(namelock ? "true" : "false"); - res.append("\">\n"); - res.append(" \n "); // Blank address + encoder.writeBool(AttributeId.ATTRIB_TYPELOCK, true); + encoder.writeBool(AttributeId.ATTRIB_NAMELOCK, namelock); + encoder.openElement(ElementId.ELEM_ADDR); + encoder.closeElement(ElementId.ELEM_ADDR); // Blank address sz = dt.getLength(); if (sz < 0) { sz = 1; } - dtmanage.buildTypeRef(res, dt, sz); - res.append("\n"); + dtmanage.encodeTypeRef(encoder, dt, sz); + encoder.closeElement(ElementId.ELEM_PARAM); } - res.append("\n"); + encoder.closeElement(ElementId.ELEM_INTERNALLIST); } - res.append("\n"); + encoder.closeElement(ElementId.ELEM_PROTOTYPE); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighExternalSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighExternalSymbol.java index a2c9e1f974..4a6e8b1e25 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighExternalSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighExternalSymbol.java @@ -15,11 +15,12 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.VariableStorage; 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. @@ -55,13 +56,12 @@ public class HighExternalSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { - buf.append(" 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.buildXML(buf, resolveAddress); - buf.append("\n"); + AddressXML.encode(encoder, resolveAddress); + encoder.closeElement(ElementId.ELEM_EXTERNREFSYMBOL); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java index 85a202ec66..bac01e84bc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java @@ -15,19 +15,19 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import ghidra.program.database.function.FunctionDB; import ghidra.program.database.symbol.CodeSymbol; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressOutOfBoundsException; -import ghidra.program.model.lang.*; +import ghidra.program.model.address.*; +import ghidra.program.model.lang.CompilerSpec; +import ghidra.program.model.lang.Language; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.InvalidInputException; -import ghidra.util.xml.SpecXmlUtils; /** * @@ -58,7 +58,8 @@ public class HighFunction extends PcodeSyntaxTree { func = function; this.language = language; 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); proto = new FunctionPrototype(localSymbols, function); jumpTables = null; @@ -423,70 +424,63 @@ public class HighFunction extends PcodeSyntaxTree { } /** - * Build an XML string that represents all the information about this HighFunction. The - * size describes how many bytes starting from the entry point are used by the function, but - * this doesn't need to be strictly accurate as it is only used to associate the function with - * addresses near its entry point. - * + * Encode this HighFunction to a stream. The size describes how many bytes starting from the + * entry point are used by the function, but this doesn't need to be strictly accurate as it + * is only used to associate the function with addresses near its entry point. + * @param encoder is the stream encoder * @param id is the id associated with 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 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 // So size needs to be smaller than size of the contiguous chunk containing the entry point - StringBuilder resBuf = new StringBuilder(); - resBuf.append("\n"); if (entryPoint == null) { - AddressXML.buildXML(resBuf, func.getEntryPoint()); + AddressXML.encode(encoder, func.getEntryPoint()); } else { - AddressXML.buildXML(resBuf, entryPoint); // Address is forced on XML + AddressXML.encode(encoder, entryPoint); // Address is forced on XML } - localSymbols.buildLocalDbXML(resBuf, namespace); - proto.buildPrototypeXML(resBuf, getDataTypeManager()); + localSymbols.encodeLocalDb(encoder, namespace); + proto.encodePrototype(encoder, getDataTypeManager()); if ((jumpTables != null) && (jumpTables.size() > 0)) { - resBuf.append("\n"); + encoder.openElement(ElementId.ELEM_JUMPTABLELIST); for (JumpTable jumpTable : jumpTables) { - jumpTable.buildXml(resBuf); + jumpTable.encode(encoder); } - resBuf.append("\n"); + encoder.closeElement(ElementId.ELEM_JUMPTABLELIST); } boolean hasOverrideTag = ((protoOverrides != null) && (protoOverrides.size() > 0)); if (hasOverrideTag) { - resBuf.append("\n"); - } - if ((protoOverrides != null) && (protoOverrides.size() > 0)) { + encoder.openElement(ElementId.ELEM_OVERRIDE); PcodeDataTypeManager dtmanage = getDataTypeManager(); for (DataTypeSymbol sym : protoOverrides) { Address addr = sym.getAddress(); FunctionPrototype fproto = new FunctionPrototype( (FunctionSignature) sym.getDataType(), compilerSpec, false); - resBuf.append("\n"); - AddressXML.buildXML(resBuf, addr); - fproto.buildPrototypeXML(resBuf, dtmanage); - resBuf.append("\n"); + encoder.openElement(ElementId.ELEM_PROTOOVERRIDE); + AddressXML.encode(encoder, addr); + fproto.encodePrototype(encoder, dtmanage); + encoder.closeElement(ElementId.ELEM_PROTOOVERRIDE); } + encoder.closeElement(ElementId.ELEM_OVERRIDE); } - if (hasOverrideTag) { - resBuf.append("\n"); - } - resBuf.append("\n"); - return resBuf.toString(); + encoder.closeElement(ElementId.ELEM_FUNCTION); } public static Namespace findOverrideSpace(Function func) { @@ -580,13 +574,14 @@ public class HighFunction extends PcodeSyntaxTree { } /** - * Append an XML <parent> tag to the buffer describing the formal path elements + * Encode <parent> element to the stream describing the formal path elements * 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 + * @throws IOException for errors in the underlying stream */ - static public void createNamespaceTag(StringBuilder buf, Namespace namespace) { - buf.append("\n"); + static public void encodeNamespace(Encoder encoder, Namespace namespace) throws IOException { + encoder.openElement(ElementId.ELEM_PARENT); if (namespace != null) { ArrayList arr = new ArrayList<>(); Namespace curspc = namespace; @@ -597,17 +592,17 @@ public class HighFunction extends PcodeSyntaxTree { } curspc = curspc.getParentNamespace(); } - buf.append("\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) { Namespace curScope = arr.get(i); - buf.append("'); - SpecXmlUtils.xmlEscape(buf, curScope.getName()); - buf.append("\n"); + encoder.openElement(ElementId.ELEM_VAL); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, curScope.getID()); + encoder.writeString(AttributeId.ATTRIB_CONTENT, curScope.getName()); + encoder.closeElement(ElementId.ELEM_VAL); } } - buf.append("\n"); + encoder.closeElement(ElementId.ELEM_PARENT); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionShellSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionShellSymbol.java index c8300d1903..51cca02520 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionShellSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionShellSymbol.java @@ -15,11 +15,12 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.VariableStorage; 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, @@ -53,13 +54,12 @@ public class HighFunctionShellSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { - buf.append("\n"); - AddressXML.buildXML(buf, getStorage().getMinAddress()); - buf.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_FUNCTION); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, getId()); + encoder.writeString(AttributeId.ATTRIB_NAME, name); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, 1); + AddressXML.encode(encoder, getStorage().getMinAddress()); + encoder.closeElement(ElementId.ELEM_FUNCTION); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionSymbol.java index fda2c4ccad..b9e8e3bb44 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionSymbol.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.Function; @@ -70,11 +72,9 @@ public class HighFunctionSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { + public void encode(Encoder encoder) throws IOException { MappedEntry entry = (MappedEntry) getFirstWholeMap(); - String funcString = - function.buildFunctionXML(getId(), getNamespace(), entry.getStorage().getMinAddress(), - entry.getSize()); - buf.append(funcString); + function.encode(encoder, getId(), getNamespace(), entry.getStorage().getMinAddress(), + entry.getSize()); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLabelSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLabelSymbol.java index a6f0e9021e..9340e2f656 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLabelSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighLabelSymbol.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.VariableStorage; @@ -46,9 +48,9 @@ public class HighLabelSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { - buf.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_LABELSYM); + encodeHeader(encoder); + encoder.closeElement(ElementId.ELEM_LABELSYM); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java index 4557d6b565..dd5b6ff19e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; 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.Symbol; 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 @@ -361,46 +362,47 @@ public class HighSymbol { } /** - * Write out attributes for the base XML tag - * @param buf is the XML output stream + * Encode attributes for the base symbol element + * @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 - SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "id", id); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id); } - SpecXmlUtils.xmlEscapeAttribute(buf, "name", name); - SpecXmlUtils.encodeBooleanAttribute(buf, "typelock", typelock); - SpecXmlUtils.encodeBooleanAttribute(buf, "namelock", namelock); - SpecXmlUtils.encodeBooleanAttribute(buf, "readonly", isReadOnly()); + encoder.writeString(AttributeId.ATTRIB_NAME, name); + encoder.writeBool(AttributeId.ATTRIB_TYPELOCK, typelock); + encoder.writeBool(AttributeId.ATTRIB_NAMELOCK, namelock); + encoder.writeBool(AttributeId.ATTRIB_READONLY, isReadOnly()); boolean isVolatile = entryList[0].isVolatile(); if (isVolatile) { - SpecXmlUtils.encodeBooleanAttribute(buf, "volatile", true); + encoder.writeBool(AttributeId.ATTRIB_VOLATILE, true); } if (isIsolated()) { - SpecXmlUtils.encodeBooleanAttribute(buf, "merge", false); + encoder.writeBool(AttributeId.ATTRIB_MERGE, false); } if (isThis) { - SpecXmlUtils.encodeBooleanAttribute(buf, "thisptr", true); + encoder.writeBool(AttributeId.ATTRIB_THISPTR, true); } 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) { - 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. - * @param buf is the XML stream + * Encode the symbol description as an element to the stream. This does NOT save the mappings. + * @param encoder is the stream encoder + * @throws IOException for errors in the underlying stream */ - public void saveXML(StringBuilder buf) { - buf.append("\n"); - dtmanage.buildTypeRef(buf, type, getSize()); - buf.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_SYMBOL); + encodeHeader(encoder); + dtmanage.encodeTypeRef(encoder, type, getSize()); + encoder.closeElement(ElementId.ELEM_SYMBOL); } 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 <mapsym> tag to the given XML stream. - * @param res is the given XML stream + * Encode the given symbol with all its mapping as a <mapsym> element to the stream. + * @param encoder is the stream encoder * @param sym is the given symbol + * @throws IOException for errors in the underlying stream */ - public static void buildMapSymXML(StringBuilder res, HighSymbol sym) { - res.append("\n"); - sym.saveXML(res); + public static void encodeMapSym(Encoder encoder, HighSymbol sym) throws IOException { + encoder.openElement(ElementId.ELEM_MAPSYM); + sym.encode(encoder); for (SymbolEntry entry : sym.entryList) { - entry.saveXml(res); + entry.encode(encoder); } - res.append("\n"); + encoder.closeElement(ElementId.ELEM_MAPSYM); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/JumpTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/JumpTable.java index 1d6ce7d18e..9ec9b4ef1b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/JumpTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/JumpTable.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.ArrayList; import ghidra.program.database.symbol.CodeSymbol; @@ -96,16 +97,16 @@ public class JumpTable { return destlist; } - public void buildXml(StringBuilder buf) { - buf.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_BASICOVERRIDE); for (Address element : destlist) { - buf.append("\n"); + encoder.openElement(ElementId.ELEM_DEST); + AddressXML.encodeAttributes(encoder, element); + encoder.closeElement(ElementId.ELEM_DEST); } - // We could add and tags to specify switch variable + // We could add and elements to specify switch variable // We could add a tag to indicate starting value of the switch variable - buf.append("\n"); + encoder.closeElement(ElementId.ELEM_BASICOVERRIDE); } } @@ -177,7 +178,8 @@ public class JumpTable { } if (subel == ElementId.ELEM_DEST.getId()) { decoder.openElement(); - Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder)); + Address caseAddr = + translateOverlayAddress(AddressXML.decodeFromAttributes(decoder)); aTable.add(caseAddr); decoder.rewindAttributes(); for (;;) { @@ -212,21 +214,20 @@ public class JumpTable { decoder.closeElement(el); } - public void buildXml(StringBuilder buf) { - buf.append("\n"); - AddressXML.buildXML(buf, opAddress); - buf.append('\n'); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_JUMPTABLE); + AddressXML.encode(encoder, opAddress); if (addressTable != null) { for (Address element : addressTable) { - buf.append("\n"); + encoder.openElement(ElementId.ELEM_DEST); + AddressXML.encodeAttributes(encoder, element); + encoder.closeElement(ElementId.ELEM_DEST); } } if (override != null) { - override.buildXml(buf); + override.encode(encoder); } - buf.append("\n"); + encoder.closeElement(ElementId.ELEM_JUMPTABLE); } public Address getSwitchAddress() { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java index d0a6b2810a..e685219698 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.*; import ghidra.program.model.address.*; @@ -23,7 +24,6 @@ import ghidra.program.model.data.Undefined; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; 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 @@ -35,7 +35,7 @@ import ghidra.util.xml.SpecXmlUtils; */ public class LocalSymbolMap { 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 addrMappedSymbols; // Hashed by addr and pcaddr private HashMap symbolMap; // Hashed by unique key private HighSymbol[] paramSymbols; @@ -43,11 +43,11 @@ public class LocalSymbolMap { /** * @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; - spacename = spcname; + localSpace = spc; addrMappedSymbols = new HashMap<>(); symbolMap = new HashMap<>(); paramSymbols = new HighSymbol[0]; @@ -278,7 +278,7 @@ public class LocalSymbolMap { */ public void decodeScope(Decoder decoder) throws PcodeXMLException { 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); decoder.skipElement(); // This is the parent scope path @@ -323,35 +323,35 @@ public class LocalSymbolMap { } /** - * Output an XML document representing this local variable map. - * @param resBuf is the buffer to write to + * Encode all the variables in this local variable map to the stream + * @param encoder is the stream encoder * @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 - resBuf.append("\n"); - resBuf.append("\n"); - resBuf.append("\n"); - resBuf.append("\n"); // Empty address range - resBuf.append("\n"); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, parentid); + encoder.closeElement(ElementId.ELEM_PARENT); + encoder.openElement(ElementId.ELEM_RANGELIST); // Emptry address range + encoder.closeElement(ElementId.ELEM_RANGELIST); + encoder.openElement(ElementId.ELEM_SYMBOLLIST); Iterator iter = symbolMap.values().iterator(); while (iter.hasNext()) { HighSymbol sym = iter.next(); - HighSymbol.buildMapSymXML(resBuf, sym); + HighSymbol.encodeMapSym(encoder, sym); } - resBuf.append("\n"); - resBuf.append("\n"); - resBuf.append("\n"); + encoder.closeElement(ElementId.ELEM_SYMBOLLIST); + encoder.closeElement(ElementId.ELEM_SCOPE); + encoder.closeElement(ElementId.ELEM_LOCALDB); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedEntry.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedEntry.java index 0a2b878515..cfa9ead96b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedEntry.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/MappedEntry.java @@ -15,6 +15,8 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.data.AbstractFloatDataType; @@ -82,14 +84,14 @@ public class MappedEntry extends SymbolEntry { } @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 typeLength = symbol.type.getLength(); if (typeLength != storage.size() && symbol.type instanceof AbstractFloatDataType) { logicalsize = typeLength; // Force a logicalsize } - AddressXML.buildXML(buf, storage.getVarnodes(), logicalsize); - buildRangelistXML(buf); + AddressXML.encode(encoder, storage.getVarnodes(), logicalsize); + encodeRangelist(encoder); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlock.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlock.java index 604b382603..cc94556fd4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlock.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlock.java @@ -16,11 +16,9 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; 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 - * @param buffer to write tag to + * Encode edge to stream assuming we already know what block we are in + * @param encoder is the stream encoder + * @throws IOException for errors writing to underlying stream */ - public void saveXml(StringBuilder buffer) { - buffer.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_EDGE); + // We are not encoding label currently + + // Reference to other end of edge + 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; } - 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); } /** - * Serialize information about the block to XML, + * Encode information about the block to stream, * other than header and edge info - * @param writer is where to serialize to - * @throws IOException if there is a problem with the stream + * @param encoder is the stream encoder + * @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 } - 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) { - 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 * @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 } - public void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException { + protected void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException { for (;;) { int el = decoder.peekElement(); if (el != ElementId.ELEM_EDGE.getId()) { @@ -390,17 +400,25 @@ public class PcodeBlock { } } - public void saveXml(Writer writer) throws IOException { - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - writer.write(buf.toString()); - saveXmlBody(writer); - saveXmlEdges(writer); - writer.write("\n"); + /** + * Encode this block to a stream + * @param encoder is the stream encoder + * @throws IOException for errors writing to the underlying stream + */ + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_BLOCK); + encodeHeader(encoder); + 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 { int el = decoder.openElement(ElementId.ELEM_BLOCK); decodeHeader(decoder); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlockBasic.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlockBasic.java index d10abe11ef..9a8898e24d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlockBasic.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeBlockBasic.java @@ -16,11 +16,9 @@ package ghidra.program.model.pcode; import java.io.IOException; -import java.io.Writer; import java.util.Iterator; import ghidra.program.model.address.*; -import ghidra.util.xml.SpecXmlUtils; /** * @@ -110,25 +108,23 @@ public class PcodeBlockBasic extends PcodeBlock { } @Override - public void saveXmlBody(Writer writer) throws IOException { - writer.append("\n"); + protected void encodeBody(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_RANGELIST); AddressRangeIterator iter = cover.getAddressRanges(true); while (iter.hasNext()) { AddressRange range = iter.next(); - StringBuilder buffer = new StringBuilder(); - buffer.append("\n"); + encoder.closeElement(ElementId.ELEM_RANGELIST); } @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); for (;;) { int rangeel = decoder.peekElement(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java index ff8b1f4bd9..ca50a3139a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +28,6 @@ import ghidra.program.model.data.Enum; import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.DecompilerLanguage; import ghidra.program.model.listing.Program; -import ghidra.util.xml.SpecXmlUtils; /** * @@ -43,9 +43,12 @@ public class PcodeDataTypeManager { public DataType dt; // Full datatype object public String name; // Name of the datatype on decompiler side public String metatype; // extra decompiler metatype information for the type + public boolean isChar; // Is this a character data-type + public boolean isUtf; // Is this a UTF encoded character data-type public long id; // Calculated id for type - public TypeMap(DecompilerLanguage lang, DataType d, String meta) { + public TypeMap(DecompilerLanguage lang, DataType d, String meta, boolean isChar, + boolean isUtf) { dt = d; if (d instanceof BuiltIn) { name = ((BuiltIn) d).getDecompilerDisplayName(lang); @@ -54,13 +57,17 @@ public class PcodeDataTypeManager { name = d.getName(); } metatype = meta; + this.isChar = isChar; + this.isUtf = isUtf; id = hashName(name); } - public TypeMap(DataType d, String nm, String meta) { + public TypeMap(DataType d, String nm, String meta, boolean isChar, boolean isUtf) { dt = d; name = nm; metatype = meta; + this.isChar = isChar; + this.isUtf = isUtf; id = hashName(name); } @@ -282,43 +289,45 @@ public class PcodeDataTypeManager { } /** - * Build XML for the void data-type - * @param resBuf is the stream to write to + * Encode the void data-type to the stream + * @param encoder is the stream encoder + * @throws IOException for errors in the underlying stream */ - private void buildVoid(StringBuilder resBuf) { - resBuf.append(""); + private void encodeVoid(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_VOID); + encoder.closeElement(ElementId.ELEM_VOID); } /** - * Build XML for a Pointer data-type - * @param resBuf is the stream to write to + * Encode a Pointer data-type to the stream. + * @param encoder is the stream encoder * @param type is the Pointer data-type * @param spc if non-null, is the specific address space associated with the pointer * @param typeDef if non-null is the base TypeDef for this special form pointer * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildPointer(StringBuilder resBuf, Pointer type, AddressSpace spc, TypeDef typeDef, - int size) { - resBuf.append("'); DataType ptrto = type.getDataType(); if (ptrto != null && ptrto.getDataTypeManager() != progDataTypes) { @@ -326,107 +335,110 @@ public class PcodeDataTypeManager { } if (ptrto == null) { - buildTypeRef(resBuf, DefaultDataType.dataType, 1); + encodeTypeRef(encoder, DefaultDataType.dataType, 1); } else if (ptrto instanceof AbstractStringDataType) { if ((ptrto instanceof StringDataType) || (type instanceof TerminatedStringDataType)) { // Convert pointer to string - appendCharTypeRef(resBuf, dataOrganization.getCharSize()); // to pointer to char + encodeCharTypeRef(encoder, dataOrganization.getCharSize()); // to pointer to char } else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string // TODO: Need to ensure that UTF8 decoding applies - appendCharTypeRef(resBuf, 1); // to pointer to char + encodeCharTypeRef(encoder, 1); // to pointer to char } else if ((ptrto instanceof UnicodeDataType) || (ptrto instanceof TerminatedUnicodeDataType)) { - appendCharTypeRef(resBuf, 2); + encodeCharTypeRef(encoder, 2); } else if ((ptrto instanceof Unicode32DataType) || (ptrto instanceof TerminatedUnicode32DataType)) { - appendCharTypeRef(resBuf, 4); + encodeCharTypeRef(encoder, 4); } else { - buildOpaqueString(resBuf, ptrto, 16384); + encodeOpaqueString(encoder, ptrto, 16384); } } else if (ptrto instanceof FunctionDefinition) { // FunctionDefinition may have size of -1, do not translate to undefined - buildTypeRef(resBuf, ptrto, ptrto.getLength()); + encodeTypeRef(encoder, ptrto, ptrto.getLength()); } else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) { - buildTypeRef(resBuf, Undefined1DataType.dataType, 1); + encodeTypeRef(encoder, Undefined1DataType.dataType, 1); } else { - buildTypeRef(resBuf, ptrto, ptrto.getLength()); + encodeTypeRef(encoder, ptrto, ptrto.getLength()); } - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build an XML representation of a pointer with an associated offset relative to a base data-type. + * Encode a pointer with an associated offset relative to a base data-type to stream. * The pointer is encoded as a TypeDef (of a Pointer). The "pointed to" object is the base data-type, * the relative offset is passed in, and other properties come from the TypeDef. - * @param resBuf is the output buffer accumulating the XML + * @param encoder is the stream encoder * @param type is the TypeDef encoding the relative pointer * @param offset is the relative offset (already extracted from the TypeDef) * @param space if non-null, is a specific address space associated with the pointer + * @throws IOException for errors in the underlying stream */ - private void buildPointerRelative(StringBuilder resBuf, TypeDef type, long offset, - AddressSpace space) { + private void encodePointerRelative(Encoder encoder, TypeDef type, long offset, + AddressSpace space) throws IOException { Pointer pointer = (Pointer) type.getBaseDataType(); - resBuf.append("\n"); DataType parent = pointer.getDataType(); DataType ptrto = findPointerRelativeInner(parent, (int) offset); - buildTypeRef(resBuf, ptrto, 1); - buildTypeRef(resBuf, parent, 1); - resBuf.append("\n").append(offset).append("\n"); - resBuf.append(""); + encodeTypeRef(encoder, ptrto, 1); + encodeTypeRef(encoder, parent, 1); + encoder.openElement(ElementId.ELEM_OFF); + encoder.writeSignedInteger(AttributeId.ATTRIB_CONTENT, offset); + encoder.closeElement(ElementId.ELEM_OFF); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for an Array data-type - * @param resBuf is the stream to write to + * Encode an Array data-type to stream. + * @param encoder is the stream encoder * @param type is the Array data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildArray(StringBuilder resBuf, Array type, int size) { + private void encodeArray(Encoder encoder, Array type, int size) throws IOException { if (type.isZeroLength()) { // TODO: Zero-element arrays not yet supported - buildOpaqueDataType(resBuf, type, size); + encodeOpaqueDataType(encoder, type, size); return; } - resBuf.append("'); - buildTypeRef(resBuf, type.getDataType(), type.getElementLength()); - resBuf.append(""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, type.getNumElements()); + encodeTypeRef(encoder, type.getDataType(), type.getElementLength()); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a Structure data-type - * @param resBuf is the stream to write to + * Encode a Structure data-type to stream + * @param encoder is the stream encoder * @param type is the Structure data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildStructure(StringBuilder resBuf, Structure type, int size) { - resBuf.append("\n"); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "struct"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz); DataTypeComponent[] comps = type.getDefinedComponents(); for (DataTypeComponent comp : comps) { if (comp.isBitFieldComponent() || comp.getLength() == 0) { // TODO: bitfields, zero-length components and zero-element arrays are not yet supported by decompiler continue; } - resBuf.append("'); + encoder.writeString(AttributeId.ATTRIB_NAME, field_name); + encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, comp.getOffset()); DataType fieldtype = comp.getDataType(); - buildTypeRef(resBuf, fieldtype, comp.getLength()); - resBuf.append("\n"); + encodeTypeRef(encoder, fieldtype, comp.getLength()); + encoder.closeElement(ElementId.ELEM_FIELD); } - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a Union data-type - * @param resBuf is the stream to write to + * Encode a Union data-type to the stream + * @param encoder is the stream encoder * @param unionType is the Union data-type + * @throws IOException for errors in the underlying stream */ - public void buildUnion(StringBuilder resBuf, Union unionType) { - resBuf.append("\n"); + public void encodeUnion(Encoder encoder, Union unionType) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, unionType); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "union"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, unionType.getLength()); DataTypeComponent[] comps = unionType.getDefinedComponents(); for (DataTypeComponent comp : comps) { if (comp.getLength() == 0) { continue; } - resBuf.append("'); + encoder.writeString(AttributeId.ATTRIB_NAME, field_name); + encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, comp.getOffset()); + encoder.writeSignedInteger(AttributeId.ATTRIB_ID, comp.getOrdinal()); DataType fieldtype = comp.getDataType(); - buildTypeRef(resBuf, fieldtype, comp.getLength()); - resBuf.append("\n"); + encodeTypeRef(encoder, fieldtype, comp.getLength()); + encoder.closeElement(ElementId.ELEM_FIELD); } - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for an Enum data-type - * @param resBuf is the stream to write to + * Encode an Enum data-type to the stream. + * @param encoder is the stream encoder * @param type is the Enum data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildEnum(StringBuilder resBuf, Enum type, int size) { - resBuf.append("\n"); + encoder.writeString(AttributeId.ATTRIB_METATYPE, metatype); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, type.getLength()); + encoder.writeBool(AttributeId.ATTRIB_ENUM, true); for (long key : keys) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_VAL); + encoder.writeString(AttributeId.ATTRIB_NAME, type.getName(key)); + encoder.writeSignedInteger(AttributeId.ATTRIB_VALUE, key); + encoder.closeElement(ElementId.ELEM_VAL); } - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a character data-type - * @param resBuf is the stream to write to + * Encode a character data-type to the stream + * @param encoder is the stream encoder * @param type is the character data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildCharDataType(StringBuilder resBuf, CharDataType type, int size) { - resBuf.append("'); - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a wide character data-type - * @param resBuf is the stream to write to + * Encode a wide character data-type to the stream + * @param encoder is the stream encoder * @param type is the Pointer data-type + * @throws IOException for errors in the underlying stream */ - private void buildWideCharDataType(StringBuilder resBuf, DataType type) { - resBuf.append("'); - resBuf.append(""); + private void encodeWideCharDataType(Encoder encoder, DataType type) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "int"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, type.getLength()); + encoder.writeBool(AttributeId.ATTRIB_UTF, true); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a string of char data-type - * @param resBuf is the stream to write to + * Encode a string of char data-type to the stream. + * @param encoder is the stream encoder * @param size is the length of the string + * @throws IOException for errors in the underlying stream */ - private void buildStringDataType(StringBuilder resBuf, int size) { - resBuf.append("'); - appendCharTypeRef(resBuf, dataOrganization.getCharSize()); - resBuf.append(""); + private void encodeStringDataType(Encoder encoder, int size) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, ""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, size); + encodeCharTypeRef(encoder, dataOrganization.getCharSize()); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a UTF8 encoded string data-type - * @param resBuf is the stream to write to + * Encode a UTF8 encoded string data-type to the stream + * @param encoder is the stream encoder * @param size is the length of the string (in bytes) + * @throws IOException for errors in the underlying stream */ - private void buildStringUTF8DataType(StringBuilder resBuf, int size) { - resBuf.append("'); - appendCharTypeRef(resBuf, 1); // TODO: Need to ensure that UTF8 decoding applies - resBuf.append(""); + private void encodeStringUTF8DataType(Encoder encoder, int size) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, ""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, size); + encodeCharTypeRef(encoder, 1); // TODO: Need to ensure that UTF8 decoding applies + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a UTF16 encoded string data-type - * @param resBuf is the stream to write to + * Encode a UTF16 encoded string data-type to the stream + * @param encoder is the stream encoder * @param size is the length of the string (in bytes) + * @throws IOException for errors in the underlying stream */ - private void buildUnicodeDataType(StringBuilder resBuf, int size) { - resBuf.append("'); - appendCharTypeRef(resBuf, 2); - resBuf.append(""); + private void encodeUnicodeDataType(Encoder encoder, int size) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, ""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, size / 2); + encodeCharTypeRef(encoder, 2); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a UTF32 encoded string data-type - * @param resBuf is the stream to write to + * Encode a UTF32 encoded string data-type to the stream + * @param encoder is the stream encoder * @param size is the length of the string (in bytes) + * @throws IOException for errors in the underlying stream */ - private void buildUnicode32DataType(StringBuilder resBuf, int size) { - resBuf.append("'); - appendCharTypeRef(resBuf, 4); - resBuf.append(""); + private void encodeUnicode32DataType(Encoder encoder, int size) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, ""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, size / 4); + encodeCharTypeRef(encoder, 4); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a FunctionDefinition data-type - * @param resBuf is the stream to write to + * Encode a FunctionDefinition data-type to the stream. + * @param encoder is the stream encoder * @param type is the FunctionDefinition data-type + * @throws IOException for errors in the underlying stream */ - private void buildFunctionDefinition(StringBuilder resBuf, FunctionDefinition type) { - resBuf.append("'); + private void encodeFunctionDefinition(Encoder encoder, FunctionDefinition type) + throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "code"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, 1); // Force size of 1 CompilerSpec cspec = program.getCompilerSpec(); FunctionPrototype fproto = new FunctionPrototype(type, cspec, voidInputIsVarargs); - fproto.buildPrototypeXML(resBuf, this); - resBuf.append(""); + fproto.encodePrototype(encoder, this); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a boolean data-type - * @param resBuf is the stream to write to + * Encode a boolean data-type to the stream + * @param encoder is the stream encoder * @param type is the boolean data-type + * @throws IOException for errors in the underlying stream */ - private void buildBooleanDataType(StringBuilder resBuf, DataType type) { - resBuf.append("'); - resBuf.append(""); + private void encodeBooleanDataType(Encoder encoder, DataType type) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "bool"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, type.getLength()); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for an integer data-type - * @param resBuf is the stream to write to + * Encode an integer data-type to the stream + * @param encoder is the stream encoder * @param type is the integer data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildAbstractIntegerDataType(StringBuilder resBuf, AbstractIntegerDataType type, - int size) { - resBuf.append("'); - resBuf.append(""); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, signed ? "int" : "uint"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a floating-point data-type - * @param resBuf is the stream to write to + * Encode a floating-point data-type to the stream + * @param encoder is the stream encoder * @param type is the floating-point data-type + * @throws IOException for errors in the underlying stream */ - private void buildAbstractFloatDataType(StringBuilder resBuf, DataType type) { - resBuf.append("'); - resBuf.append(""); + private void encodeAbstractFloatDataType(Encoder encoder, DataType type) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "float"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, type.getLength()); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a data-type whose internals are opaque (to the Decompiler) - * @param resBuf is the stream to write to + * Encode a data-type whose internals are opaque (to the Decompiler) to stream. + * @param encoder is the stream encoder * @param type is the opaque data-type * @param size if non-zero, is the size of the data-type in context + * @throws IOException for errors in the underlying stream */ - private void buildOpaqueDataType(StringBuilder resBuf, DataType type, int size) { - resBuf.append("'); - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build XML for a string data-type whose internals are opaque (to the Decompiler) - * @param resBuf is the stream to write to + * Encode a string data-type whose internals are opaque (to the Decompiler) to stream. + * @param encoder is the stream encoder * @param type is the opaque string * @param size is the length of the string (in bytes) + * @throws IOException for errors in the underlying stream */ - private void buildOpaqueString(StringBuilder resBuf, DataType type, int size) { - resBuf.append("\n"); - resBuf.append(" \n"); + private void encodeOpaqueString(Encoder encoder, DataType type, int size) throws IOException { + encoder.openElement(ElementId.ELEM_TYPE); + encodeNameIdAttributes(encoder, type); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "struct"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeBool(AttributeId.ATTRIB_OPAQUESTRING, true); + encoder.writeBool(AttributeId.ATTRIB_VARLENGTH, true); + encoder.openElement(ElementId.ELEM_FIELD); + encoder.writeString(AttributeId.ATTRIB_NAME, "unknown_data1"); + encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, 0); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "byte"); + encoder.closeElement(ElementId.ELEM_TYPEREF); + encoder.closeElement(ElementId.ELEM_FIELD); size -= 1; - resBuf.append(" "); - resBuf.append("\n"); - resBuf.append(""); + encoder.openElement(ElementId.ELEM_FIELD); + encoder.writeString(AttributeId.ATTRIB_NAME, "opaque_data"); + encoder.writeSignedInteger(AttributeId.ATTRIB_OFFSET, 1); + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, ""); + encoder.writeString(AttributeId.ATTRIB_METATYPE, "array"); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); + encoder.writeSignedInteger(AttributeId.ATTRIB_ARRAYSIZE, size); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "byte"); + encoder.closeElement(ElementId.ELEM_TYPEREF); + encoder.closeElement(ElementId.ELEM_TYPE); + encoder.closeElement(ElementId.ELEM_FIELD); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build an XML document string representing the Structure that has - * its size reported as zero. - * - * @param type data type to build XML for - * - * @return XML string document + * Encode a Structure to the stream that has its size reported as zero. + * @param encoder is the stream encoder + * @param type data type to encode + * @throws IOException for errors in the underlying stream */ - public StringBuilder buildCompositeZeroSizePlaceholder(DataType type) { - StringBuilder resBuf = new StringBuilder(); + public void encodeCompositeZeroSizePlaceholder(Encoder encoder, DataType type) + throws IOException { String metaString; if (type instanceof Structure) { metaString = "struct"; @@ -769,26 +786,27 @@ public class PcodeDataTypeManager { metaString = "union"; } else { - return resBuf; //empty. Could throw AssertException. + return; //empty. Could throw AssertException. } - resBuf.append(""); - return resBuf; + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, type.getDisplayName()); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, progDataTypes.getID(type)); + encoder.writeString(AttributeId.ATTRIB_METATYPE, metaString); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, 0); + encoder.closeElement(ElementId.ELEM_TYPE); } /** - * Build an XML representation of a TypeDef data-type. Generally this sends - * a \ tag with a \ reference to the underlying data-type being typedefed, + * Encode a TypeDef data-type to the stream. Generally this sends + * a \ element with a \ reference to the underlying data-type being typedefed, * but we check for Settings on the TypeDef object that can indicate - * specialty data-types with their own XML format. - * @param resBuf is the output buffer accumulating the XML + * specialty data-types with their own encodings. + * @param encoder is the stream encoder * @param type is the TypeDef to build the XML for * @param size is the size of the data-type for the specific instantiation + * @throws IOException for errors in the underlying stream */ - private void buildTypeDef(StringBuilder resBuf, TypeDef type, int size) { + private void encodeTypeDef(Encoder encoder, TypeDef type, int size) throws IOException { DataType refType = type.getDataType(); String format = null; int sz = refType.getLength(); @@ -805,14 +823,14 @@ public class PcodeDataTypeManager { program.getAddressFactory()); long offset = PointerTypedefInspector.getPointerComponentOffset(type); if (offset != 0) { - buildPointerRelative(resBuf, type, offset, space); + encodePointerRelative(encoder, type, offset, space); return; } if (space != null) { // Cannot use space, unless we are build an actual Pointer // Its possible that refType is still a TypeDef refType = type.getBaseDataType(); - buildPointer(resBuf, (Pointer) refType, space, type, size); + encodePointer(encoder, (Pointer) refType, space, type, size); return; } } @@ -826,45 +844,45 @@ public class PcodeDataTypeManager { } } - resBuf.append("'); - buildTypeRef(resBuf, refType, sz); - resBuf.append(""); - return; + encodeTypeRef(encoder, refType, sz); + encoder.closeElement(ElementId.ELEM_DEF); } /** - * Generate an XML tag describing the given data-type. Most data-types produce a {@code } tag, - * fully describing the data-type. Where possible a {@code } tag is produced, which just gives - * the name of the data-type, deferring a full description of the data-type. For certain simple or - * nameless data-types, a {@code } tag is emitted giving a full description. - * @param resBuf is the stream to append the tag to + * Encode a reference to the given data-type to stream. Most data-types produce a + * {@code } element, fully describing the data-type. Where possible a {@code } + * element is produced, which just encodes the name of the data-type, deferring a full + * description of the data-type. For certain simple or nameless data-types, a {@code } + * element is emitted giving a full description. + * @param encoder is the stream encoder * @param type is the data-type to be converted * @param size is the size in bytes of the specific instance of the data-type + * @throws IOException for errors in the underlying stream */ - public void buildTypeRef(StringBuilder resBuf, DataType type, int size) { + public void encodeTypeRef(Encoder encoder, DataType type, int size) throws IOException { if (type != null && type.getDataTypeManager() != progDataTypes) { type = type.clone(progDataTypes); } if ((type instanceof VoidDataType) || (type == null)) { - buildType(resBuf, type, size); + encodeType(encoder, type, size); return; } if (type instanceof AbstractIntegerDataType) { - buildType(resBuf, type, size); + encodeType(encoder, type, size); return; } if (type instanceof Pointer) { - buildType(resBuf, type, size); + encodeType(encoder, type, size); return; } if (type instanceof Array) { - buildType(resBuf, type, size); + encodeType(encoder, type, size); return; } if (type instanceof FunctionDefinition) { @@ -872,33 +890,33 @@ public class PcodeDataTypeManager { if (id <= 0) { // Its possible the FunctionDefinition was built on the fly and is not // a permanent data-type of the program with an ID. In this case, we can't - // construct a tag but must build a full tag. - buildType(resBuf, type, size); + // construct a element but must build a full element. + encodeType(encoder, type, size); return; } size = 1; } else if (type.getLength() <= 0) { - buildType(resBuf, type, size); + encodeType(encoder, type, size); return; } - resBuf.append(" 0) { - SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id); } if (type.getLength() <= 0 && size > 0) { - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, size); } } - resBuf.append("/>"); + encoder.closeElement(ElementId.ELEM_TYPEREF); } /** @@ -913,125 +931,139 @@ public class PcodeDataTypeManager { } /** - * Append the name and id associated with a given data-type to an XML stream - * @param resBuf is the stream to append to + * Encode the name and id associated with a given data-type to a stream as attributes + * of the current element. + * @param encoder is the stream encoder * @param type is the given data-type + * @throws IOException for errors in the underlying stream */ - private void appendNameIdAttributes(StringBuilder resBuf, DataType type) { + private void encodeNameIdAttributes(Encoder encoder, DataType type) throws IOException { if (type instanceof BuiltIn) { - SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", + encoder.writeString(AttributeId.ATTRIB_NAME, ((BuiltIn) type).getDecompilerDisplayName(displayLanguage)); } else { - SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", type.getName()); + encoder.writeString(AttributeId.ATTRIB_NAME, type.getName()); long id = progDataTypes.getID(type); if (id > 0) { - SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_ID, id); } } } /** - * Append an XML reference for a character data-type, based on the size in bytes - * @param resBuf is the stream to append to + * Encode a reference element for a character data-type, based on the size in bytes to a stream. + * @param encoder is the stream encoder * @param size is the requested size of the character data-type + * @throws IOException for errors in the underlying stream */ - private void appendCharTypeRef(StringBuilder resBuf, int size) { + private void encodeCharTypeRef(Encoder encoder, int size) throws IOException { if (size == dataOrganization.getCharSize()) { - resBuf.append(""); // could have size 1 or 2 + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "char"); // could have size 1 or 2 + encoder.closeElement(ElementId.ELEM_TYPEREF); return; } if (size == dataOrganization.getWideCharSize()) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "wchar_t"); + encoder.closeElement(ElementId.ELEM_TYPEREF); return; } if (size == 2) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "wchar16"); + encoder.closeElement(ElementId.ELEM_TYPEREF); return; } if (size == 4) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "wchar32"); + encoder.closeElement(ElementId.ELEM_TYPEREF); return; } if (size == 1) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_TYPEREF); + encoder.writeString(AttributeId.ATTRIB_NAME, "byte"); + encoder.closeElement(ElementId.ELEM_TYPEREF); return; } throw new IllegalArgumentException("Unsupported character size"); } /** - * Build an XML document string representing the type information for a data type + * Encode information for a data-type to the stream * - * @param resBuf is the stream to append the document to - * @param type data type to build XML for - * @param size size of the data type + * @param encoder is the stream encoder + * @param type is the data-type to encode + * @param size is the size of the data-type + * @throws IOException for errors in the underlying stream */ - public void buildType(StringBuilder resBuf, DataType type, int size) { + public void encodeType(Encoder encoder, DataType type, int size) throws IOException { if (type != null && type.getDataTypeManager() != progDataTypes) { type = type.clone(progDataTypes); } if ((type instanceof VoidDataType) || (type == null)) { - buildVoid(resBuf); + encodeVoid(encoder); } else if (type instanceof TypeDef) { - buildTypeDef(resBuf, (TypeDef) type, size); + encodeTypeDef(encoder, (TypeDef) type, size); } else if (type instanceof Pointer) { - buildPointer(resBuf, (Pointer) type, null, null, size); + encodePointer(encoder, (Pointer) type, null, null, size); } else if (type instanceof Array) { - buildArray(resBuf, (Array) type, size); + encodeArray(encoder, (Array) type, size); } else if (type instanceof Structure) { - buildStructure(resBuf, (Structure) type, size); + encodeStructure(encoder, (Structure) type, size); } else if (type instanceof Union) { - buildUnion(resBuf, (Union) type); + encodeUnion(encoder, (Union) type); } else if (type instanceof Enum) { - buildEnum(resBuf, (Enum) type, size); + encodeEnum(encoder, (Enum) type, size); } else if (type instanceof CharDataType) { - buildCharDataType(resBuf, (CharDataType) type, size); + encodeCharDataType(encoder, (CharDataType) type, size); } else if (type instanceof WideCharDataType || type instanceof WideChar16DataType || type instanceof WideChar32DataType) { - buildWideCharDataType(resBuf, type); + encodeWideCharDataType(encoder, type); } else if (type instanceof AbstractStringDataType) { if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) { - buildStringDataType(resBuf, size); + encodeStringDataType(encoder, size); } else if (type instanceof StringUTF8DataType) { - buildStringUTF8DataType(resBuf, size); + encodeStringUTF8DataType(encoder, size); } else if ((type instanceof UnicodeDataType) || (type instanceof TerminatedUnicodeDataType)) { - buildUnicodeDataType(resBuf, size); + encodeUnicodeDataType(encoder, size); } else if ((type instanceof Unicode32DataType) || (type instanceof TerminatedUnicode32DataType)) { - buildUnicode32DataType(resBuf, size); + encodeUnicode32DataType(encoder, size); } else { - buildOpaqueString(resBuf, type, size); + encodeOpaqueString(encoder, type, size); } } else if (type instanceof FunctionDefinition) { - buildFunctionDefinition(resBuf, (FunctionDefinition) type); + encodeFunctionDefinition(encoder, (FunctionDefinition) type); } else if (type instanceof BooleanDataType) { - buildBooleanDataType(resBuf, type); + encodeBooleanDataType(encoder, type); } else if (type instanceof AbstractIntegerDataType) { // must handle char and bool above - buildAbstractIntegerDataType(resBuf, (AbstractIntegerDataType) type, size); + encodeAbstractIntegerDataType(encoder, (AbstractIntegerDataType) type, size); } else if (type instanceof AbstractFloatDataType) { - buildAbstractFloatDataType(resBuf, type); + encodeAbstractFloatDataType(encoder, type); } else { - buildOpaqueDataType(resBuf, type, size); + encodeOpaqueDataType(encoder, type, size); } } @@ -1043,58 +1075,60 @@ public class PcodeDataTypeManager { private void generateCoreTypes() { voidDt = new VoidDataType(progDataTypes); ArrayList typeList = new ArrayList<>(); - typeList.add(new TypeMap(DataType.DEFAULT, "undefined", " metatype=\"unknown\"")); + typeList.add(new TypeMap(DataType.DEFAULT, "undefined", "unknown", false, false)); for (DataType dt : Undefined.getUndefinedDataTypes()) { - typeList.add(new TypeMap(displayLanguage, dt, " metatype=\"unknown\"")); + typeList.add(new TypeMap(displayLanguage, dt, "unknown", false, false)); } for (DataType dt : AbstractIntegerDataType.getSignedDataTypes(progDataTypes)) { typeList.add( - new TypeMap(displayLanguage, dt.clone(progDataTypes), " metatype=\"int\"")); + new TypeMap(displayLanguage, dt.clone(progDataTypes), "int", false, false)); } for (DataType dt : AbstractIntegerDataType.getUnsignedDataTypes(progDataTypes)) { typeList.add( - new TypeMap(displayLanguage, dt.clone(progDataTypes), " metatype=\"uint\"")); + new TypeMap(displayLanguage, dt.clone(progDataTypes), "uint", false, false)); } for (DataType dt : AbstractFloatDataType.getFloatDataTypes(progDataTypes)) { - typeList.add(new TypeMap(displayLanguage, dt, " metatype=\"float\"")); + typeList.add(new TypeMap(displayLanguage, dt, "float", false, false)); } - typeList.add(new TypeMap(DataType.DEFAULT, "code", " metatype=\"code\"")); + typeList.add(new TypeMap(DataType.DEFAULT, "code", "code", false, false)); // Set "char" datatype DataType charDataType = new CharDataType(progDataTypes); String charMetatype = null; + boolean isChar = false; + boolean isUtf = false; if (charDataType instanceof CharDataType && ((CharDataType) charDataType).isSigned()) { - charMetatype = " metatype=\"int\""; + charMetatype = "int"; } else { - charMetatype = " metatype=\"uint\""; + charMetatype = "uint"; } if (charDataType.getLength() == 1) { - charMetatype = charMetatype + " char=\"true\""; + isChar = true; } else { - charMetatype = charMetatype + " utf=\"true\""; + isUtf = true; } - typeList.add(new TypeMap(displayLanguage, charDataType, charMetatype)); + typeList.add(new TypeMap(displayLanguage, charDataType, charMetatype, isChar, isUtf)); // Set up the "wchar_t" datatype WideCharDataType wideDataType = new WideCharDataType(progDataTypes); - typeList.add(new TypeMap(displayLanguage, wideDataType, " metatype=\"int\" utf=\"true\"")); + typeList.add(new TypeMap(displayLanguage, wideDataType, "int", false, true)); if (wideDataType.getLength() != 2) { - typeList.add(new TypeMap(displayLanguage, new WideChar16DataType(progDataTypes), - " metatype=\"int\" utf=\"true\"")); + typeList.add(new TypeMap(displayLanguage, new WideChar16DataType(progDataTypes), "int", + false, true)); } if (wideDataType.getLength() != 4) { - typeList.add(new TypeMap(displayLanguage, new WideChar32DataType(progDataTypes), - " metatype=\"int\" utf=\"true\"")); + typeList.add(new TypeMap(displayLanguage, new WideChar32DataType(progDataTypes), "int", + false, true)); } DataType boolDataType = new BooleanDataType(progDataTypes); - typeList.add(new TypeMap(displayLanguage, boolDataType, " metatype=\"bool\"")); + typeList.add(new TypeMap(displayLanguage, boolDataType, "bool", false, false)); coreBuiltin = new TypeMap[typeList.size()]; typeList.toArray(coreBuiltin); @@ -1132,30 +1166,30 @@ public class PcodeDataTypeManager { } /** - * Build the coretypes XML element - * @return coretypes XML element + * Encode the coretypes to the stream + * @param encoder is the stream encoder + * @throws IOException for errors in the underlying stream */ - public String buildCoreTypes() { - - StringBuilder buf = new StringBuilder(); - buf.append("\n"); - - buf.append("\n"); + public void encodeCoreTypes(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_CORETYPES); + encoder.openElement(ElementId.ELEM_VOID); + encoder.closeElement(ElementId.ELEM_VOID); for (TypeMap typeMap : coreBuiltin) { - buf.append("\n"); + encoder.openElement(ElementId.ELEM_TYPE); + encoder.writeString(AttributeId.ATTRIB_NAME, typeMap.name); + encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, typeMap.dt.getLength()); + encoder.writeString(AttributeId.ATTRIB_METATYPE, typeMap.metatype); + if (typeMap.isChar) { + encoder.writeBool(AttributeId.ATTRIB_CHAR, true); + } + if (typeMap.isUtf) { + encoder.writeBool(AttributeId.ATTRIB_UTF, true); + } + // Encode special id ( <0 for builtins ) + encoder.writeSignedInteger(AttributeId.ATTRIB_ID, typeMap.id); + encoder.closeElement(ElementId.ELEM_TYPE); } - - buf.append("\n"); - - return buf.toString(); + encoder.closeElement(ElementId.ELEM_CORETYPES); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java index 1b761f04d0..b3b39941e4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java @@ -15,11 +15,11 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.*; import ghidra.program.model.address.*; import ghidra.program.model.lang.UnknownInstructionException; -import ghidra.util.xml.SpecXmlUtils; /** * @@ -416,31 +416,37 @@ public class PcodeOp { output = vn; } - public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) { - resBuf.append("'); - resBuf.append(seqnum.buildXML()); + /** + * Encode this PcodeOp to a stream as an \ element + * @param encoder is the stream encoder + * @param addrFactory is a factory for looking up encoded address spaces + * @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) { - resBuf.append(""); + encoder.openElement(ElementId.ELEM_VOID); + encoder.closeElement(ElementId.ELEM_VOID); } else { - output.buildXML(resBuf); + output.encode(encoder); } if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) { int spaceId = (int) input[0].getOffset(); - resBuf.append(""); + encoder.writeSpace(AttributeId.ATTRIB_NAME, space); + encoder.closeElement(ElementId.ELEM_SPACEID); } else if (input.length > 0) { - input[0].buildXML(resBuf); + input[0].encode(encoder); } for (int i = 1; i < input.length; ++i) { - input[i].buildXML(resBuf); + input[i].encode(encoder); } - resBuf.append(""); + encoder.closeElement(ElementId.ELEM_OP); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SequenceNumber.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SequenceNumber.java index ad46ae5ef4..e3d6724777 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SequenceNumber.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SequenceNumber.java @@ -15,9 +15,10 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; 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 { private Address pc; // Address of assembly language instruction 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 - // 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 @@ -125,19 +126,19 @@ public class SequenceNumber implements Comparable { } /** - * @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() { - StringBuilder resBuf = new StringBuilder(); - resBuf.append(""); - return resBuf; + encoder.closeElement(ElementId.ELEM_SEQNUM); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SymbolEntry.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SymbolEntry.java index 4082e06e55..2b596d7f72 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SymbolEntry.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/SymbolEntry.java @@ -15,10 +15,11 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; 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. @@ -44,10 +45,11 @@ public abstract class SymbolEntry { public abstract void decode(Decoder decoder) throws PcodeXMLException; /** - * Save this entry as (a set of) XML tags to the given stream - * @param buf is the given stream + * Encode this entry as (a set of) elements to 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 @@ -98,12 +100,12 @@ public abstract class SymbolEntry { 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()) { - res.append(""); + encoder.closeElement(ElementId.ELEM_RANGELIST); return; } - res.append(""); AddressSpace space = pcaddr.getAddressSpace(); long off; if (space.isOverlaySpace()) { @@ -113,11 +115,11 @@ public abstract class SymbolEntry { else { off = pcaddr.getUnsignedOffset(); } - res.append(""); - res.append("\n"); + encoder.openElement(ElementId.ELEM_RANGE); + encoder.writeSpace(AttributeId.ATTRIB_SPACE, space); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_FIRST, off); + encoder.writeUnsignedInteger(AttributeId.ATTRIB_LAST, off); + encoder.closeElement(ElementId.ELEM_RANGE); + encoder.closeElement(ElementId.ELEM_RANGELIST); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java index 7ffb9eae3e..d9a0c48751 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java @@ -15,9 +15,10 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; + import ghidra.program.model.address.Address; 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, @@ -39,13 +40,12 @@ public class UnionFacetSymbol extends HighSymbol { } @Override - public void saveXML(StringBuilder buf) { - buf.append("\n"); - dtmanage.buildTypeRef(buf, type, getSize()); - buf.append("\n"); + public void encode(Encoder encoder) throws IOException { + encoder.openElement(ElementId.ELEM_FACETSYMBOL); + encodeHeader(encoder); + encoder.writeSignedInteger(AttributeId.ATTRIB_FIELD, fieldNumber); + dtmanage.encodeTypeRef(encoder, type, getSize()); + encoder.closeElement(ElementId.ELEM_FACETSYMBOL); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java index 78c30b4fce..d9231747ae 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java @@ -15,6 +15,7 @@ */ package ghidra.program.model.pcode; +import java.io.IOException; import java.util.Iterator; 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) { - AddressXML.buildXML(buf, address, size); + public void encode(Encoder encoder) throws IOException { + AddressXML.encode(encoder, address, size); } /** @@ -348,7 +350,7 @@ public class Varnode { } else if (attribId == AttributeId.ATTRIB_REF.getId()) { // If we have a reference 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) { decoder.closeElement(el); return vn; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlDecode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlDecode.java index 70541f715a..0c3b37f357 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlDecode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlDecode.java @@ -119,6 +119,8 @@ public class XmlDecode implements Decoder { throw new PcodeXMLException("Expecting end, but got start <" + el.getName() + '>'); } 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()); // if (elemId != id) { // throw new PcodeXMLException("Unexpected end, <" + el.getName() + '>'); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java new file mode 100644 index 0000000000..5e7e4c0d5a --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java @@ -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("'); + } + } + + @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(); + } +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslatorAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslatorAdapter.java index 223252d285..0fa2f22c38 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslatorAdapter.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslatorAdapter.java @@ -15,6 +15,7 @@ */ package ghidra.program.util; +import java.io.IOException; import java.util.*; 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.lang.*; import ghidra.program.model.listing.*; +import ghidra.program.model.pcode.Encoder; import ghidra.util.Msg; import ghidra.util.datastruct.RangeMap; import ghidra.util.exception.CancelledException; @@ -681,7 +683,7 @@ class TemporaryCompilerSpec implements CompilerSpec { } @Override - public void saveXml(StringBuilder buffer) { + public void encode(Encoder encoder) throws IOException { throw new UnsupportedOperationException(); } diff --git a/Ghidra/Processors/Dalvik/src/main/java/ghidra/dalvik/dex/inject/InjectPayloadDexParameters.java b/Ghidra/Processors/Dalvik/src/main/java/ghidra/dalvik/dex/inject/InjectPayloadDexParameters.java index ab5533718f..66949fdd0d 100644 --- a/Ghidra/Processors/Dalvik/src/main/java/ghidra/dalvik/dex/inject/InjectPayloadDexParameters.java +++ b/Ghidra/Processors/Dalvik/src/main/java/ghidra/dalvik/dex/inject/InjectPayloadDexParameters.java @@ -28,8 +28,7 @@ import ghidra.program.model.lang.InjectContext; import ghidra.program.model.lang.InjectPayload; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; -import ghidra.program.model.pcode.PcodeOp; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.Msg; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -178,12 +177,12 @@ public class InjectPayloadDexParameters implements InjectPayload { } @Override - public void saveXml(StringBuilder buffer) { + public void encode(Encoder encoder) throws IOException { // Provide a minimal tag so decompiler can call-back - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PCODE); + encoder.writeString(AttributeId.ATTRIB_INJECT, "uponentry"); + encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true); + encoder.closeElement(ElementId.ELEM_PCODE); } @Override diff --git a/Ghidra/Processors/JVM/src/main/java/ghidra/app/util/pcodeInject/InjectPayloadJavaParameters.java b/Ghidra/Processors/JVM/src/main/java/ghidra/app/util/pcodeInject/InjectPayloadJavaParameters.java index 7f9c6c7472..b0ca6b18cb 100644 --- a/Ghidra/Processors/JVM/src/main/java/ghidra/app/util/pcodeInject/InjectPayloadJavaParameters.java +++ b/Ghidra/Processors/JVM/src/main/java/ghidra/app/util/pcodeInject/InjectPayloadJavaParameters.java @@ -28,8 +28,7 @@ import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.InjectContext; import ghidra.program.model.lang.InjectPayload; import ghidra.program.model.listing.Program; -import ghidra.program.model.pcode.PcodeOp; -import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.pcode.*; import ghidra.util.Msg; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -111,12 +110,12 @@ public class InjectPayloadJavaParameters implements InjectPayload { } @Override - public void saveXml(StringBuilder buffer) { + public void encode(Encoder encoder) throws IOException { // Provide a minimal tag so decompiler can call-back - buffer.append("\n"); + encoder.openElement(ElementId.ELEM_PCODE); + encoder.writeString(AttributeId.ATTRIB_INJECT, "uponentry"); + encoder.writeBool(AttributeId.ATTRIB_DYNAMIC, true); + encoder.closeElement(ElementId.ELEM_PCODE); } @Override