mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-2262 Marshaling refactor - java-side
This commit is contained in:
parent
0123c85d9f
commit
ae79857b42
68 changed files with 3131 additions and 1597 deletions
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "ifacedecomp.hh"
|
#include "ifacedecomp.hh"
|
||||||
|
|
||||||
|
|
||||||
static IfaceStatus *ghidra_dcp = (IfaceStatus *)0;
|
static IfaceStatus *ghidra_dcp = (IfaceStatus *)0;
|
||||||
static RemoteSocket *remote = (RemoteSocket *)0;
|
static RemoteSocket *remote = (RemoteSocket *)0;
|
||||||
|
|
||||||
|
@ -62,6 +63,8 @@ void connect_to_console(Funcdata *fd)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ElementId ELEM_DOC = ElementId("doc",218);
|
||||||
|
|
||||||
vector<ArchitectureGhidra *> archlist; // List of architectures currently running
|
vector<ArchitectureGhidra *> archlist; // List of architectures currently running
|
||||||
|
|
||||||
map<string,GhidraCommand *> GhidraCapability::commandmap; // List of commands we can receive from Ghidra proper
|
map<string,GhidraCommand *> GhidraCapability::commandmap; // List of commands we can receive from Ghidra proper
|
||||||
|
@ -300,10 +303,10 @@ void DecompileAt::rawAction(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
sout.write("\000\000\001\016",4);
|
sout.write("\000\000\001\016",4);
|
||||||
// Write output XML directly to outstream
|
|
||||||
if (fd->isProcComplete()) {
|
if (fd->isProcComplete()) {
|
||||||
sout << "<doc>\n";
|
|
||||||
XmlEncode encoder(sout);
|
XmlEncode encoder(sout);
|
||||||
|
encoder.openElement(ELEM_DOC);
|
||||||
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
||||||
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
||||||
pidanalysis.encode( encoder, true );
|
pidanalysis.encode( encoder, true );
|
||||||
|
@ -318,7 +321,7 @@ void DecompileAt::rawAction(void)
|
||||||
(ghidra->allacts.getCurrentName() == "decompile"))
|
(ghidra->allacts.getCurrentName() == "decompile"))
|
||||||
ghidra->print->docFunction(fd);
|
ghidra->print->docFunction(fd);
|
||||||
}
|
}
|
||||||
sout << "</doc>\n";
|
encoder.closeElement(ELEM_DOC);
|
||||||
}
|
}
|
||||||
sout.write("\000\000\001\017",4);
|
sout.write("\000\000\001\017",4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
class GhidraCommand;
|
class GhidraCommand;
|
||||||
|
|
||||||
|
extern ElementId ELEM_DOC; ///< Marshaling element \<doc>
|
||||||
|
|
||||||
/// \brief Registration point and dispatcher for commands sent to the decompiler
|
/// \brief Registration point and dispatcher for commands sent to the decompiler
|
||||||
///
|
///
|
||||||
/// This is the base class for \b command \b capabilities (sets of commands).
|
/// This is the base class for \b command \b capabilities (sets of commands).
|
||||||
|
|
|
@ -500,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
|
||||||
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
||||||
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
||||||
|
|
||||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",144); // Number serves as next open index
|
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",147); // Number serves as next open index
|
||||||
|
|
||||||
ElementId ELEM_DATA = ElementId("data",1);
|
ElementId ELEM_DATA = ElementId("data",1);
|
||||||
ElementId ELEM_INPUT = ElementId("input",2);
|
ElementId ELEM_INPUT = ElementId("input",2);
|
||||||
|
@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
|
||||||
ElementId ELEM_VALUE = ElementId("value",9);
|
ElementId ELEM_VALUE = ElementId("value",9);
|
||||||
ElementId ELEM_VOID = ElementId("void",10);
|
ElementId ELEM_VOID = ElementId("void",10);
|
||||||
|
|
||||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",218); // Number serves as next open index
|
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",231); // Number serves as next open index
|
||||||
|
|
|
@ -232,7 +232,7 @@ public:
|
||||||
/// \brief Find the specific attribute in the current element and return it as an address space
|
/// \brief Find the specific attribute in the current element and return it as an address space
|
||||||
///
|
///
|
||||||
/// Search attributes from the current element for a match to the given attribute id.
|
/// Search attributes from the current element for a match to the given attribute id.
|
||||||
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is throw.
|
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is thrown.
|
||||||
/// Parse via getNextAttributeId is reset.
|
/// Parse via getNextAttributeId is reset.
|
||||||
/// \param attribId is the specific attribute id to match
|
/// \param attribId is the specific attribute id to match
|
||||||
/// \return the address space associated with the attribute
|
/// \return the address space associated with the attribute
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,8 +16,6 @@
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
public class ClangBreak extends ClangToken {
|
public class ClangBreak extends ClangToken {
|
||||||
|
|
||||||
|
@ -29,16 +26,18 @@ public class ClangBreak extends ClangToken {
|
||||||
indent = 0;
|
indent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClangBreak(ClangNode par,int indent) {
|
public ClangBreak(ClangNode par, int indent) {
|
||||||
super(par);
|
super(par);
|
||||||
this.indent = indent;
|
this.indent = indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndent() { return indent; }
|
public int getIndent() {
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
indent = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDENT);
|
||||||
indent = SpecXmlUtils.decodeInt(el.getAttribute("indent"));
|
super.decode(decoder, pfactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,7 @@ package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.pcode.PcodeFactory;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
|
|
||||||
public class ClangCommentToken extends ClangToken {
|
public class ClangCommentToken extends ClangToken {
|
||||||
|
|
||||||
|
@ -58,12 +56,11 @@ public class ClangCommentToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el, end, pfactory);
|
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||||
String name = el.getAttribute(ClangXML.SPACE);
|
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
|
||||||
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
|
|
||||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
|
|
||||||
srcaddr = spc.getAddress(offset);
|
srcaddr = spc.getAddress(offset);
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,7 @@
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.pcode.PcodeFactory;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A C code token representing a structure field.
|
* A C code token representing a structure field.
|
||||||
|
@ -55,22 +52,33 @@ public class ClangFieldToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el, end, pfactory);
|
String datatypestring = null;
|
||||||
String datatypestring = el.getAttribute("name"); // Name of the structure
|
long id = 0;
|
||||||
if (datatypestring != null) {
|
for (;;) {
|
||||||
datatype =
|
int attribId = decoder.getNextAttributeId();
|
||||||
pfactory.getDataTypeManager().findBaseType(datatypestring, el.getAttribute("id"));
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
String offsetstring = el.getAttribute(ClangXML.OFFSET);
|
if (attribId == AttributeId.ATTRIB_NAME.getId()) { // Name of the structure
|
||||||
if (offsetstring != null) {
|
datatypestring = decoder.readString();
|
||||||
offset = SpecXmlUtils.decodeInt(offsetstring);
|
|
||||||
}
|
}
|
||||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||||
if (oprefstring != null) {
|
id = decoder.readUnsignedInteger();
|
||||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_OFF.getId()) {
|
||||||
|
offset = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
op = pfactory.getOpRef(refid);
|
op = pfactory.getOpRef(refid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (datatypestring != null) {
|
||||||
|
datatype = pfactory.getDataTypeManager().findBaseType(datatypestring, id);
|
||||||
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,10 +21,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -37,34 +34,51 @@ public class ClangFuncNameToken extends ClangToken {
|
||||||
private HighFunction hfunc; // Overall reference to function
|
private HighFunction hfunc; // Overall reference to function
|
||||||
private PcodeOp op; // Local reference to function op
|
private PcodeOp op; // Local reference to function op
|
||||||
|
|
||||||
public ClangFuncNameToken(ClangNode par,HighFunction hf) {
|
public ClangFuncNameToken(ClangNode par, HighFunction hf) {
|
||||||
super(par);
|
super(par);
|
||||||
hfunc = hf;
|
hfunc = hf;
|
||||||
op = null;
|
op = null;
|
||||||
}
|
}
|
||||||
public HighFunction getHighFunction() { return hfunc; }
|
|
||||||
|
public HighFunction getHighFunction() {
|
||||||
|
return hfunc;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcodeOp getPcodeOp() { return op; }
|
public PcodeOp getPcodeOp() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
if (op==null) return null;
|
if (op == null) {
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public Address getMaxAddress() {
|
|
||||||
if (op==null) return null;
|
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public Address getMaxAddress() {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
if (op == null) {
|
||||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
return null;
|
||||||
if (oprefstring != null) {
|
|
||||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
|
||||||
op = pfactory.getOpRef(refid);
|
|
||||||
}
|
}
|
||||||
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
|
op = pfactory.getOpRef(refid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
public class ClangLabelToken extends ClangToken {
|
public class ClangLabelToken extends ClangToken {
|
||||||
private Address blockaddr; // Address this is labelling
|
private Address blockaddr; // Address this is labelling
|
||||||
|
@ -30,22 +28,26 @@ public class ClangLabelToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVariableRef() { return false; }
|
public boolean isVariableRef() {
|
||||||
|
return false;
|
||||||
@Override
|
|
||||||
public Address getMinAddress() { return blockaddr; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Address getMaxAddress() { return blockaddr; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
|
||||||
super.restoreFromXML(el, end, pfactory);
|
|
||||||
String name = el.getAttribute(ClangXML.SPACE);
|
|
||||||
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
|
|
||||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
|
|
||||||
blockaddr = spc.getAddress(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Address getMinAddress() {
|
||||||
|
return blockaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Address getMaxAddress() {
|
||||||
|
return blockaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
|
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||||
|
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
|
||||||
|
blockaddr = spc.getAddress(offset);
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Created on Jun 18, 2003
|
||||||
|
*
|
||||||
|
* To change the template for this generated file go to
|
||||||
|
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||||
|
*/
|
||||||
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
|
import ghidra.program.model.pcode.*;
|
||||||
|
|
||||||
|
public abstract class ClangMarkup { // Placeholder for CLANG XML identifiers
|
||||||
|
|
||||||
|
// Attribute values
|
||||||
|
public static final String KEYWORD_COLOR = "keyword";
|
||||||
|
public static final String COMMENT_COLOR = "comment";
|
||||||
|
public static final String TYPE_COLOR = "type";
|
||||||
|
public static final String FUNCNAME_COLOR = "funcname";
|
||||||
|
public static final String VARIABLE_COLOR = "var";
|
||||||
|
public static final String CONST_COLOR = "const";
|
||||||
|
public static final String PARAMETER_COLOR = "param";
|
||||||
|
public static final String GLOBAL_COLOR = "global";
|
||||||
|
|
||||||
|
public static ClangTokenGroup buildClangTree(Decoder decoder, HighFunction hfunc)
|
||||||
|
throws PcodeXMLException {
|
||||||
|
ClangTokenGroup docroot;
|
||||||
|
int el = decoder.openElement();
|
||||||
|
if (el == ElementId.ELEM_FUNCTION.getId()) {
|
||||||
|
docroot = new ClangFunction(null, hfunc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
docroot = new ClangTokenGroup(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
docroot.decode(decoder, hfunc);
|
||||||
|
decoder.closeElement(el);
|
||||||
|
return docroot;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,10 +21,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -43,26 +40,39 @@ public class ClangOpToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcodeOp getPcodeOp() { return op; }
|
public PcodeOp getPcodeOp() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
if (op==null) return null;
|
if (op == null) {
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public Address getMaxAddress() {
|
|
||||||
if (op==null) return null;
|
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public Address getMaxAddress() {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
if (op == null) {
|
||||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
return null;
|
||||||
if (oprefstring != null) {
|
}
|
||||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
op = pfactory.getOpRef(refid);
|
op = pfactory.getOpRef(refid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,11 +21,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.*;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -43,16 +41,23 @@ public class ClangReturnType extends ClangTokenGroup {
|
||||||
datatype = null;
|
datatype = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataType getDataType() { return datatype; }
|
public DataType getDataType() {
|
||||||
public Varnode getVarnode() { return varnode; }
|
return datatype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Varnode getVarnode() {
|
||||||
|
return varnode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
XmlElement node = parser.peek();
|
for (;;) {
|
||||||
super.restoreFromXML(parser,pfactory);
|
int attribId = decoder.getNextAttributeId();
|
||||||
String varrefstring = node.getAttribute(ClangXML.VARNODEREF);
|
if (attribId == 0) {
|
||||||
if (varrefstring != null) {
|
break;
|
||||||
int refid = SpecXmlUtils.decodeInt(varrefstring);
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
varnode = pfactory.getRef(refid);
|
varnode = pfactory.getRef(refid);
|
||||||
if (varnode != null) {
|
if (varnode != null) {
|
||||||
if (varnode.getHigh() == null) {
|
if (varnode.getHigh() == null) {
|
||||||
|
@ -61,6 +66,9 @@ public class ClangReturnType extends ClangTokenGroup {
|
||||||
}
|
}
|
||||||
datatype = varnode.getHigh().getDataType();
|
datatype = varnode.getHigh().getDataType();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,8 +22,7 @@
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -40,16 +38,28 @@ import ghidra.xml.*;
|
||||||
public class ClangStatement extends ClangTokenGroup {
|
public class ClangStatement extends ClangTokenGroup {
|
||||||
private PcodeOp op; // Root op of C-statement
|
private PcodeOp op; // Root op of C-statement
|
||||||
|
|
||||||
public ClangStatement(ClangNode par) { super(par); op = null; }
|
public ClangStatement(ClangNode par) {
|
||||||
public PcodeOp getPcodeOp() { return op; }
|
super(par);
|
||||||
@Override
|
op = null;
|
||||||
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
|
|
||||||
XmlElement node = parser.peek();
|
|
||||||
String oprefstring = node.getAttribute(ClangXML.OPREF);
|
|
||||||
if (oprefstring != null) {
|
|
||||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
|
||||||
op = pfactory.getOpRef(refid);
|
|
||||||
}
|
}
|
||||||
super.restoreFromXML(parser,pfactory);
|
|
||||||
|
public PcodeOp getPcodeOp() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
|
op = pfactory.getOpRef(refid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,8 +22,6 @@
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -33,38 +30,54 @@ import ghidra.xml.*;
|
||||||
* A SyntaxToken may be or may include spacing
|
* A SyntaxToken may be or may include spacing
|
||||||
*/
|
*/
|
||||||
public class ClangSyntaxToken extends ClangToken {
|
public class ClangSyntaxToken extends ClangToken {
|
||||||
private int open,close;
|
private int open, close;
|
||||||
|
|
||||||
public ClangSyntaxToken(ClangNode par) {
|
public ClangSyntaxToken(ClangNode par) {
|
||||||
super(par);
|
super(par);
|
||||||
open = close = -1;
|
open = close = -1;
|
||||||
}
|
}
|
||||||
public ClangSyntaxToken(ClangNode par,String txt) {
|
|
||||||
super(par,txt);
|
public ClangSyntaxToken(ClangNode par, String txt) {
|
||||||
|
super(par, txt);
|
||||||
open = close = -1;
|
open = close = -1;
|
||||||
}
|
}
|
||||||
public ClangSyntaxToken(ClangNode par,String txt,String col) {
|
|
||||||
super(par,txt,col);
|
public ClangSyntaxToken(ClangNode par, String txt, String col) {
|
||||||
|
super(par, txt, col);
|
||||||
open = close = -1;
|
open = close = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVariableRef() {
|
public boolean isVariableRef() {
|
||||||
if (Parent() instanceof ClangVariableDecl) return true;
|
if (Parent() instanceof ClangVariableDecl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
for (;;) {
|
||||||
String str = el.getAttribute("open");
|
int attribId = decoder.getNextAttributeId();
|
||||||
if (str != null)
|
if (attribId == 0) {
|
||||||
open = SpecXmlUtils.decodeInt(str);
|
break;
|
||||||
str = el.getAttribute("close");
|
}
|
||||||
if (str != null)
|
if (attribId == AttributeId.ATTRIB_OPEN.getId()) {
|
||||||
close = SpecXmlUtils.decodeInt(str);
|
open = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_CLOSE.getId()) {
|
||||||
|
close = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOpen() { return open; }
|
public int getOpen() {
|
||||||
public int getClose() { return close; }
|
return open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getClose() {
|
||||||
|
return close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,8 +27,6 @@ import java.util.List;
|
||||||
//import ghidra.app.plugin.core.decompile.*;
|
//import ghidra.app.plugin.core.decompile.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -154,9 +152,19 @@ public class ClangToken implements ClangNode {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
text = end.getText();
|
String col = null;
|
||||||
String col = el.getAttribute(ClangXML.COLOR);
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_COLOR.getId()) {
|
||||||
|
col = decoder.readString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = decoder.readString(AttributeId.ATTRIB_CONTENT);
|
||||||
syntax_type = getColor(col);
|
syntax_type = getColor(col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,70 +173,67 @@ public class ClangToken implements ClangNode {
|
||||||
list.add(this);
|
list.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public ClangToken buildToken(ClangNode par, XmlPullParser parser,
|
static public ClangToken buildToken(int node, ClangNode par, Decoder decoder,
|
||||||
PcodeFactory pfactory) {
|
PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
XmlElement node =
|
|
||||||
parser.start(ClangXML.VARIABLE, ClangXML.OP, ClangXML.SYNTAX, ClangXML.BREAK,
|
|
||||||
ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT, ClangXML.LABEL, ClangXML.FIELD);
|
|
||||||
ClangToken token = null;
|
ClangToken token = null;
|
||||||
if (node.getName().equals(ClangXML.VARIABLE)) {
|
if (node == ElementId.ELEM_VARIABLE.getId()) {
|
||||||
token = new ClangVariableToken(par);
|
token = new ClangVariableToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.OP)) {
|
else if (node == ElementId.ELEM_OP.getId()) {
|
||||||
token = new ClangOpToken(par);
|
token = new ClangOpToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.SYNTAX)) {
|
else if (node == ElementId.ELEM_SYNTAX.getId()) {
|
||||||
token = new ClangSyntaxToken(par);
|
token = new ClangSyntaxToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.BREAK)) {
|
else if (node == ElementId.ELEM_BREAK.getId()) {
|
||||||
token = new ClangBreak(par);
|
token = new ClangBreak(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.FUNCNAME)) {
|
else if (node == ElementId.ELEM_FUNCNAME.getId()) {
|
||||||
token = new ClangFuncNameToken(par, null);
|
token = new ClangFuncNameToken(par, null);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.TYPE)) {
|
else if (node == ElementId.ELEM_TYPE.getId()) {
|
||||||
token = new ClangTypeToken(par);
|
token = new ClangTypeToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.COMMENT)) {
|
else if (node == ElementId.ELEM_COMMENT.getId()) {
|
||||||
token = new ClangCommentToken(par);
|
token = new ClangCommentToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.LABEL)) {
|
else if (node == ElementId.ELEM_LABEL.getId()) {
|
||||||
token = new ClangLabelToken(par);
|
token = new ClangLabelToken(par);
|
||||||
}
|
}
|
||||||
else if (node.getName().equals(ClangXML.FIELD)) {
|
else if (node == ElementId.ELEM_FIELD.getId()) {
|
||||||
token = new ClangFieldToken(par);
|
token = new ClangFieldToken(par);
|
||||||
}
|
}
|
||||||
XmlElement end = parser.end(node);
|
else {
|
||||||
if (token != null) {
|
throw new PcodeXMLException("Expecting token element");
|
||||||
token.restoreFromXML(node, end, pfactory);
|
|
||||||
}
|
}
|
||||||
|
token.decode(decoder, pfactory);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getColor(String col) {
|
public static int getColor(String col) {
|
||||||
if (col != null) {
|
if (col != null) {
|
||||||
if (col.equals(ClangXML.KEYWORD_COLOR)) {
|
if (col.equals(ClangMarkup.KEYWORD_COLOR)) {
|
||||||
return KEYWORD_COLOR;
|
return KEYWORD_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.VARIABLE_COLOR)) {
|
else if (col.equals(ClangMarkup.VARIABLE_COLOR)) {
|
||||||
return VARIABLE_COLOR;
|
return VARIABLE_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.CONST_COLOR)) {
|
else if (col.equals(ClangMarkup.CONST_COLOR)) {
|
||||||
return CONST_COLOR;
|
return CONST_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.PARAMETER_COLOR)) {
|
else if (col.equals(ClangMarkup.PARAMETER_COLOR)) {
|
||||||
return PARAMETER_COLOR;
|
return PARAMETER_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.GLOBAL_COLOR)) {
|
else if (col.equals(ClangMarkup.GLOBAL_COLOR)) {
|
||||||
return GLOBAL_COLOR;
|
return GLOBAL_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.TYPE_COLOR)) {
|
else if (col.equals(ClangMarkup.TYPE_COLOR)) {
|
||||||
return TYPE_COLOR;
|
return TYPE_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.COMMENT_COLOR)) {
|
else if (col.equals(ClangMarkup.COMMENT_COLOR)) {
|
||||||
return COMMENT_COLOR;
|
return COMMENT_COLOR;
|
||||||
}
|
}
|
||||||
else if (col.equals(ClangXML.FUNCNAME_COLOR)) {
|
else if (col.equals(ClangMarkup.FUNCNAME_COLOR)) {
|
||||||
return FUNCTION_COLOR;
|
return FUNCTION_COLOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,7 @@ import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.PcodeFactory;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in a tree of C code tokens.
|
* A node in a tree of C code tokens.
|
||||||
|
@ -106,44 +104,43 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
XmlElement node = parser.start(ClangXML.FUNCTION, ClangXML.RETURN_TYPE, ClangXML.VARDECL,
|
for (;;) {
|
||||||
ClangXML.STATEMENT, ClangXML.FUNCPROTO, ClangXML.BLOCK, ClangXML.VARIABLE, ClangXML.OP,
|
int elem = decoder.openElement();
|
||||||
ClangXML.SYNTAX, ClangXML.BREAK, ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT,
|
if (elem == 0) {
|
||||||
ClangXML.LABEL);
|
break;
|
||||||
while (parser.peek().isStart()) {
|
}
|
||||||
XmlElement elem = parser.peek();
|
if (elem == ElementId.ELEM_RETURN_TYPE.getId()) {
|
||||||
if (elem.getName().equals(ClangXML.RETURN_TYPE)) {
|
|
||||||
ClangReturnType child = new ClangReturnType(this);
|
ClangReturnType child = new ClangReturnType(this);
|
||||||
child.restoreFromXML(parser, pfactory);
|
child.decode(decoder, pfactory);
|
||||||
AddTokenGroup(child);
|
AddTokenGroup(child);
|
||||||
}
|
}
|
||||||
else if (elem.getName().equals(ClangXML.VARDECL)) {
|
else if (elem == ElementId.ELEM_VARDECL.getId()) {
|
||||||
ClangVariableDecl child = new ClangVariableDecl(this);
|
ClangVariableDecl child = new ClangVariableDecl(this);
|
||||||
child.restoreFromXML(parser, pfactory);
|
child.decode(decoder, pfactory);
|
||||||
AddTokenGroup(child);
|
AddTokenGroup(child);
|
||||||
}
|
}
|
||||||
else if (elem.getName().equals(ClangXML.STATEMENT)) {
|
else if (elem == ElementId.ELEM_STATEMENT.getId()) {
|
||||||
ClangStatement child = new ClangStatement(this);
|
ClangStatement child = new ClangStatement(this);
|
||||||
child.restoreFromXML(parser, pfactory);
|
child.decode(decoder, pfactory);
|
||||||
AddTokenGroup(child);
|
AddTokenGroup(child);
|
||||||
}
|
}
|
||||||
else if (elem.getName().equals(ClangXML.FUNCPROTO)) {
|
else if (elem == ElementId.ELEM_FUNCPROTO.getId()) {
|
||||||
ClangFuncProto child = new ClangFuncProto(this);
|
ClangFuncProto child = new ClangFuncProto(this);
|
||||||
child.restoreFromXML(parser, pfactory);
|
child.decode(decoder, pfactory);
|
||||||
AddTokenGroup(child);
|
AddTokenGroup(child);
|
||||||
}
|
}
|
||||||
else if (elem.getName().equals(ClangXML.BLOCK)) {
|
else if (elem == ElementId.ELEM_BLOCK.getId()) {
|
||||||
ClangTokenGroup child = new ClangTokenGroup(this);
|
ClangTokenGroup child = new ClangTokenGroup(this);
|
||||||
child.restoreFromXML(parser, pfactory);
|
child.decode(decoder, pfactory);
|
||||||
AddTokenGroup(child);
|
AddTokenGroup(child);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClangToken tok = ClangToken.buildToken(this, parser, pfactory);
|
ClangToken tok = ClangToken.buildToken(elem, this, decoder, pfactory);
|
||||||
AddTokenGroup(tok);
|
AddTokenGroup(tok);
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(elem);
|
||||||
}
|
}
|
||||||
parser.end(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLetterDigitOrUnderscore(char c) {
|
private boolean isLetterDigitOrUnderscore(char c) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,9 +21,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.xml.*;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -41,7 +40,9 @@ public class ClangTypeToken extends ClangToken {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVariableRef() {
|
public boolean isVariableRef() {
|
||||||
if (Parent() instanceof ClangVariableDecl) return true;
|
if (Parent() instanceof ClangVariableDecl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +51,20 @@ public class ClangTypeToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
int id = 0;
|
||||||
datatype = pfactory.getDataTypeManager().findBaseType(getText(),el.getAttribute("id"));
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||||
|
id = (int) decoder.readUnsignedInteger();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
datatype = pfactory.getDataTypeManager().findBaseType(getText(), id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,6 @@ package ghidra.app.decompiler;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -54,10 +51,9 @@ public class ClangVariableDecl extends ClangTokenGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
XmlElement node = parser.peek();
|
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
|
||||||
super.restoreFromXML(parser, pfactory);
|
super.decode(decoder, pfactory);
|
||||||
long symref = SpecXmlUtils.decodeLong(node.getAttribute(ClangXML.SYMREF));
|
|
||||||
HighSymbol sym = pfactory.getSymbol(symref);
|
HighSymbol sym = pfactory.getSymbol(symref);
|
||||||
if (sym == null) {
|
if (sym == null) {
|
||||||
Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent());
|
Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent());
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,10 +21,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler;
|
package ghidra.app.decompiler;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -58,14 +56,20 @@ public class ClangVariableToken extends ClangToken {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
if (op==null) return null;
|
if (op == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMaxAddress() {
|
public Address getMaxAddress() {
|
||||||
if (op==null) return null;
|
if (op == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HighVariable getHighVariable() {
|
public HighVariable getHighVariable() {
|
||||||
Varnode inst = getVarnode();
|
Varnode inst = getVarnode();
|
||||||
|
@ -82,17 +86,22 @@ public class ClangVariableToken extends ClangToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||||
super.restoreFromXML(el,end,pfactory);
|
for (;;) {
|
||||||
String varrefstring = el.getAttribute(ClangXML.VARNODEREF);
|
int attribId = decoder.getNextAttributeId();
|
||||||
if (varrefstring != null) {
|
if (attribId == 0) {
|
||||||
int refid = SpecXmlUtils.decodeInt(varrefstring);
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
|
||||||
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
varnode = pfactory.getRef(refid);
|
varnode = pfactory.getRef(refid);
|
||||||
}
|
}
|
||||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||||
if (oprefstring != null) {
|
int refid = (int) decoder.readUnsignedInteger();
|
||||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
|
||||||
op = pfactory.getOpRef(refid);
|
op = pfactory.getOpRef(refid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
super.decode(decoder, pfactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Created on Jun 18, 2003
|
|
||||||
*
|
|
||||||
* To change the template for this generated file go to
|
|
||||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
|
||||||
*/
|
|
||||||
package ghidra.app.decompiler;
|
|
||||||
|
|
||||||
import ghidra.program.model.pcode.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* To change the template for this generated type comment go to
|
|
||||||
*{@literal Window>Preferences>Java>Code Generation>Code and Comments}
|
|
||||||
*/
|
|
||||||
public abstract class ClangXML { // Placeholder for CLANG XML identifiers
|
|
||||||
|
|
||||||
public static final String DOCUMENT = "clang_document";
|
|
||||||
public static final String FUNCTION = "function";
|
|
||||||
public static final String BLOCK = "block";
|
|
||||||
public static final String RETURN_TYPE = "return_type";
|
|
||||||
public static final String VARDECL = "vardecl";
|
|
||||||
public static final String STATEMENT = "statement";
|
|
||||||
public static final String FUNCPROTO = "funcproto";
|
|
||||||
public static final String SYNTAX = "syntax";
|
|
||||||
public static final String BREAK = "break";
|
|
||||||
public static final String VARIABLE = "variable";
|
|
||||||
public static final String OP = "op";
|
|
||||||
public static final String FUNCNAME="funcname";
|
|
||||||
public static final String TYPE = "type";
|
|
||||||
public static final String FIELD = "field";
|
|
||||||
public static final String COMMENT = "comment";
|
|
||||||
public static final String LABEL = "label";
|
|
||||||
|
|
||||||
// Attributes
|
|
||||||
public static final String INDENT="indent";
|
|
||||||
public static final String COLOR="color";
|
|
||||||
public static final String OPREF = "opref";
|
|
||||||
public static final String BLOCKREF = "blockref";
|
|
||||||
public static final String VARNODEREF="varref";
|
|
||||||
public static final String SPACE="space";
|
|
||||||
public static final String OFFSET="off";
|
|
||||||
public static final String PCSPACE="pcspace";
|
|
||||||
public static final String PCOFFSET="pcoff";
|
|
||||||
public static final String SYMREF="symref";
|
|
||||||
|
|
||||||
// Attribute values
|
|
||||||
public static final String KEYWORD_COLOR = "keyword";
|
|
||||||
public static final String COMMENT_COLOR ="comment";
|
|
||||||
public static final String TYPE_COLOR = "type";
|
|
||||||
public static final String FUNCNAME_COLOR = "funcname";
|
|
||||||
public static final String VARIABLE_COLOR = "var";
|
|
||||||
public static final String CONST_COLOR = "const";
|
|
||||||
public static final String PARAMETER_COLOR = "param";
|
|
||||||
public static final String GLOBAL_COLOR = "global";
|
|
||||||
|
|
||||||
public static ClangTokenGroup buildClangTree(XmlPullParser parser,HighFunction hfunc) {
|
|
||||||
ClangTokenGroup docroot;
|
|
||||||
if (parser.peek().getName().equals("function"))
|
|
||||||
docroot = new ClangFunction(null,hfunc);
|
|
||||||
else
|
|
||||||
docroot = new ClangTokenGroup(null);
|
|
||||||
docroot.restoreFromXML(parser,hfunc);
|
|
||||||
return docroot;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,7 +34,6 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.task.CancelledListener;
|
import ghidra.util.task.CancelledListener;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a self-contained interface to a single decompile
|
* This is a self-contained interface to a single decompile
|
||||||
|
@ -669,10 +668,10 @@ public class DecompInterface {
|
||||||
timeoutSecs);
|
timeoutSecs);
|
||||||
decompileMessage = decompCallback.getNativeMessage();
|
decompileMessage = decompCallback.getNativeMessage();
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(),
|
XmlDecode decoder = new XmlDecode(factory);
|
||||||
HighFunction.getErrorHandler(this, "Results for structureGraph command"));
|
decoder.ingestStream(res.getInputStream(), "structureGraph results");
|
||||||
resgraph = new BlockGraph();
|
resgraph = new BlockGraph();
|
||||||
resgraph.restoreXml(parser, factory);
|
resgraph.restoreXml(decoder);
|
||||||
resgraph.transferObjectRef(ingraph);
|
resgraph.transferObjectRef(ingraph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class DecompileCallback {
|
||||||
private Charset utf8Charset;
|
private Charset utf8Charset;
|
||||||
private String nativeMessage;
|
private String nativeMessage;
|
||||||
|
|
||||||
|
private XmlDecodeLight lightDecoder;
|
||||||
private InstructionBlock lastPseudoInstructionBlock;
|
private InstructionBlock lastPseudoInstructionBlock;
|
||||||
private Disassembler pseudoDisassembler;
|
private Disassembler pseudoDisassembler;
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ public class DecompileCallback {
|
||||||
nativeMessage = null;
|
nativeMessage = null;
|
||||||
debug = null;
|
debug = null;
|
||||||
utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8);
|
utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8);
|
||||||
|
lightDecoder = new XmlDecodeLight(addrfactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SAXParser getSAXParser() throws PcodeXMLException {
|
private static SAXParser getSAXParser() throws PcodeXMLException {
|
||||||
|
@ -170,8 +172,10 @@ public class DecompileCallback {
|
||||||
|
|
||||||
public byte[] getBytes(String addrxml) {
|
public byte[] getBytes(String addrxml) {
|
||||||
try {
|
try {
|
||||||
Address addr = AddressXML.readXML(addrxml, addrfactory);
|
lightDecoder.ingestString(addrxml);
|
||||||
int size = AddressXML.readXMLSize(addrxml);
|
lightDecoder.openElement();
|
||||||
|
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||||
|
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +224,8 @@ public class DecompileCallback {
|
||||||
Address addr;
|
Address addr;
|
||||||
int flags;
|
int flags;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -263,7 +268,8 @@ public class DecompileCallback {
|
||||||
public PackedBytes getPcodePacked(String addrstring) {
|
public PackedBytes getPcodePacked(String addrstring) {
|
||||||
Address addr = null;
|
Address addr = null;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -351,7 +357,8 @@ public class DecompileCallback {
|
||||||
InjectContext con = snippetLibrary.buildInjectContext();
|
InjectContext con = snippetLibrary.buildInjectContext();
|
||||||
PcodeOp[] pcode;
|
PcodeOp[] pcode;
|
||||||
try {
|
try {
|
||||||
con.restoreXml(getSAXParser(), context, addrfactory);
|
lightDecoder.ingestString(context);
|
||||||
|
con.decode(lightDecoder);
|
||||||
}
|
}
|
||||||
catch (PcodeXMLException e) {
|
catch (PcodeXMLException e) {
|
||||||
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
|
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
|
||||||
|
@ -484,7 +491,8 @@ public class DecompileCallback {
|
||||||
public String getSymbol(String addrstring) { // Return first symbol name at this address
|
public String getSymbol(String addrstring) { // Return first symbol name at this address
|
||||||
Address addr;
|
Address addr;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -701,7 +709,8 @@ public class DecompileCallback {
|
||||||
public String getMappedSymbolsXML(String addrstring) { // Return XML describing data or functions at addr
|
public String getMappedSymbolsXML(String addrstring) { // Return XML describing data or functions at addr
|
||||||
Address addr;
|
Address addr;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -746,7 +755,8 @@ public class DecompileCallback {
|
||||||
public String getExternalRefXML(String addrstring) { // Return any external reference at addr
|
public String getExternalRefXML(String addrstring) { // Return any external reference at addr
|
||||||
Address addr;
|
Address addr;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -809,8 +819,8 @@ public class DecompileCallback {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType(String name, String idstr) {
|
public String getType(String name, long id) {
|
||||||
DataType type = dtmanage.findBaseType(name, idstr);
|
DataType type = dtmanage.findBaseType(name, id);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -836,9 +846,10 @@ public class DecompileCallback {
|
||||||
|
|
||||||
public String getRegisterName(String addrstring) {
|
public String getRegisterName(String addrstring) {
|
||||||
try {
|
try {
|
||||||
|
lightDecoder.ingestString(addrstring);
|
||||||
Address addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.openElement();
|
||||||
int size = AddressXML.readXMLSize(addrstring);
|
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||||
|
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
Register reg = pcodelanguage.getRegister(addr, size);
|
Register reg = pcodelanguage.getRegister(addr, size);
|
||||||
if (reg == null) {
|
if (reg == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -855,7 +866,8 @@ public class DecompileCallback {
|
||||||
public String getTrackedRegisters(String addrstring) {
|
public String getTrackedRegisters(String addrstring) {
|
||||||
Address addr;
|
Address addr;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
lightDecoder.ingestString(addrstring);
|
||||||
|
addr = AddressXML.decode(lightDecoder);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
@ -1312,12 +1324,14 @@ public class DecompileCallback {
|
||||||
* @param dtId is the id associated with the character data-type
|
* @param dtId is the id associated with the character data-type
|
||||||
* @return the UTF8 encoded byte array or null
|
* @return the UTF8 encoded byte array or null
|
||||||
*/
|
*/
|
||||||
public StringData getStringData(String addrString, String dtName, String dtId) {
|
public StringData getStringData(String addrString, String dtName, long dtId) {
|
||||||
Address addr;
|
Address addr;
|
||||||
int maxChars;
|
int maxChars;
|
||||||
try {
|
try {
|
||||||
addr = AddressXML.readXML(addrString, addrfactory);
|
lightDecoder.ingestString(addrString);
|
||||||
maxChars = AddressXML.readXMLSize(addrString);
|
lightDecoder.openElement();
|
||||||
|
addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||||
|
maxChars = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
if (overlaySpace != null) {
|
if (overlaySpace != null) {
|
||||||
addr = overlaySpace.getOverlayAddress(addr);
|
addr = overlaySpace.getOverlayAddress(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import ghidra.program.model.lang.PackedBytes;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.timer.GTimer;
|
import ghidra.util.timer.GTimer;
|
||||||
import ghidra.util.timer.GTimerMonitor;
|
import ghidra.util.timer.GTimerMonitor;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -787,7 +788,7 @@ public class DecompileProcess {
|
||||||
|
|
||||||
private void getType() throws IOException {
|
private void getType() throws IOException {
|
||||||
String name = readQueryString();
|
String name = readQueryString();
|
||||||
String id = readQueryString();
|
long id = SpecXmlUtils.decodeLong(readQueryString());
|
||||||
String res = callback.getType(name, id);
|
String res = callback.getType(name, id);
|
||||||
write(query_response_start);
|
write(query_response_start);
|
||||||
if ((res != null) && (res.length() != 0)) {
|
if ((res != null) && (res.length() != 0)) {
|
||||||
|
@ -816,7 +817,7 @@ public class DecompileProcess {
|
||||||
private void getStringData() throws IOException {
|
private void getStringData() throws IOException {
|
||||||
String addr = readQueryString();
|
String addr = readQueryString();
|
||||||
String dtName = readQueryString();
|
String dtName = readQueryString();
|
||||||
String dtId = readQueryString();
|
long dtId = SpecXmlUtils.decodeLong(readQueryString());
|
||||||
DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId);
|
DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId);
|
||||||
write(query_response_start);
|
write(query_response_start);
|
||||||
if (stringData != null) {
|
if (stringData != null) {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import ghidra.program.model.lang.CompilerSpec;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for getting at the various structures returned
|
* Class for getting at the various structures returned
|
||||||
|
@ -75,7 +73,7 @@ public class DecompileResults {
|
||||||
hparamid = null;
|
hparamid = null;
|
||||||
docroot = null;
|
docroot = null;
|
||||||
//dumpResults(raw);
|
//dumpResults(raw);
|
||||||
parseRawString(raw);
|
decodeStream(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void dumpResults(String raw) {
|
// private void dumpResults(String raw) {
|
||||||
|
@ -203,45 +201,45 @@ public class DecompileResults {
|
||||||
return printer.print(true);
|
return printer.print(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseRawString(InputStream rawxml) {
|
private void decodeStream(InputStream rawstream) {
|
||||||
if (rawxml == null) {
|
if (rawstream == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
XmlPullParser parser = null;
|
XmlDecode decoder = new XmlDecode(function.getProgram().getAddressFactory());
|
||||||
try {
|
try {
|
||||||
try {
|
decoder.ingestStream(rawstream,
|
||||||
parser =
|
"Decompiler results for function at " + function.getEntryPoint());
|
||||||
HighFunction.stringTree(
|
|
||||||
rawxml,
|
|
||||||
HighFunction.getErrorHandler(this, "decompiler results for function at " +
|
|
||||||
function.getEntryPoint()));
|
|
||||||
hfunc = null;
|
hfunc = null;
|
||||||
hparamid = null;
|
hparamid = null;
|
||||||
docroot = null;
|
docroot = null;
|
||||||
parser.start("doc");
|
int docel = decoder.openElement(ElementId.ELEM_DOC);
|
||||||
while(parser.peek().isStart()) {
|
for (;;) {
|
||||||
XmlElement el = parser.peek();
|
int el = decoder.peekElement();
|
||||||
if (el.getName().equals("function")) {
|
if (el == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (el == ElementId.ELEM_FUNCTION.getId()) {
|
||||||
if (hfunc == null) {
|
if (hfunc == null) {
|
||||||
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
|
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
|
||||||
hfunc.readXML(parser);
|
hfunc.decode(decoder);
|
||||||
}
|
}
|
||||||
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
|
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
|
||||||
docroot = ClangXML.buildClangTree(parser, hfunc);
|
docroot = ClangMarkup.buildClangTree(decoder, hfunc);
|
||||||
if (docroot == null) {
|
if (docroot == null) {
|
||||||
errMsg = "Unable to parse C (xml)";
|
errMsg = "Unable to decode C markup";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (el.getName().equals("parammeasures")) {
|
else if (el == ElementId.ELEM_PARAMMEASURES.getId()) {
|
||||||
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
|
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
|
||||||
hparamid.readXML(parser);
|
hparamid.decode(decoder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errMsg = "Unknown decompiler tag: "+el.getName();
|
errMsg = "Unknown decompiler tag";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
decoder.closeElement(docel);
|
||||||
}
|
}
|
||||||
catch (PcodeXMLException e) { // Error while walking the DOM
|
catch (PcodeXMLException e) { // Error while walking the DOM
|
||||||
errMsg = e.getMessage();
|
errMsg = e.getMessage();
|
||||||
|
@ -256,10 +254,4 @@ public class DecompileResults {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
if (parser != null) {
|
|
||||||
parser.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,7 +340,7 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
|
||||||
ClangTokenGroup line = new ClangTokenGroup(docroot);
|
ClangTokenGroup line = new ClangTokenGroup(docroot);
|
||||||
ClangBreak lineBreak = new ClangBreak(line, 1);
|
ClangBreak lineBreak = new ClangBreak(line, 1);
|
||||||
ClangSyntaxToken message =
|
ClangSyntaxToken message =
|
||||||
new ClangSyntaxToken(line, errline, ClangXML.COMMENT_COLOR);
|
new ClangSyntaxToken(line, errline, ClangMarkup.COMMENT_COLOR);
|
||||||
line.AddTokenGroup(lineBreak);
|
line.AddTokenGroup(lineBreak);
|
||||||
line.AddTokenGroup(message);
|
line.AddTokenGroup(message);
|
||||||
docroot.AddTokenGroup(line);
|
docroot.AddTokenGroup(line);
|
||||||
|
|
|
@ -15,73 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.xml.parsers.SAXParser;
|
|
||||||
|
|
||||||
import org.xml.sax.*;
|
|
||||||
import org.xml.sax.helpers.DefaultHandler;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
|
|
||||||
public class InjectContext {
|
public class InjectContext {
|
||||||
private class Handler extends DefaultHandler {
|
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private Address curaddr;
|
|
||||||
private int state;
|
|
||||||
|
|
||||||
Handler(AddressFactory adFact) {
|
|
||||||
super();
|
|
||||||
state = 0;
|
|
||||||
addrFactory = adFact;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startElement(String uri, String localName, String rawName, Attributes attr)
|
|
||||||
throws SAXException {
|
|
||||||
if (rawName.equals("context")) {
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else if (rawName.equals("input")) {
|
|
||||||
inputlist = new ArrayList<>();
|
|
||||||
state = 3;
|
|
||||||
}
|
|
||||||
else if (rawName.equals("output")) {
|
|
||||||
output = new ArrayList<>();
|
|
||||||
state = 4;
|
|
||||||
}
|
|
||||||
else if (rawName.equals("addr")) {
|
|
||||||
curaddr = AddressXML.readXML(rawName, attr, addrFactory);
|
|
||||||
if (state == 1) {
|
|
||||||
baseAddr = curaddr;
|
|
||||||
state = 2;
|
|
||||||
}
|
|
||||||
else if (state == 2) {
|
|
||||||
callAddr = curaddr;
|
|
||||||
}
|
|
||||||
else if (state == 3) {
|
|
||||||
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
|
|
||||||
Varnode vn = new Varnode(curaddr, size);
|
|
||||||
inputlist.add(vn);
|
|
||||||
}
|
|
||||||
else if (state == 4) {
|
|
||||||
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
|
|
||||||
Varnode vn = new Varnode(curaddr, size);
|
|
||||||
output.add(vn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new SAXException("Unrecognized inject tag: " + rawName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SleighLanguage language;
|
public SleighLanguage language;
|
||||||
public Address baseAddr; // Base address of op (call,userop) causing the inject
|
public Address baseAddr; // Base address of op (call,userop) causing the inject
|
||||||
|
@ -94,18 +34,44 @@ public class InjectContext {
|
||||||
public InjectContext() {
|
public InjectContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXml(SAXParser parser, String xml, AddressFactory addrFactory)
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int el = decoder.openElement(ElementId.ELEM_CONTEXT);
|
||||||
Handler handler = new Handler(addrFactory);
|
baseAddr = AddressXML.decode(decoder);
|
||||||
try {
|
callAddr = AddressXML.decode(decoder);
|
||||||
parser.parse(new InputSource(new StringReader(xml)), handler);
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == ElementId.ELEM_INPUT.getId()) {
|
||||||
|
decoder.openElement();
|
||||||
|
inputlist = new ArrayList<>();
|
||||||
|
for (;;) {
|
||||||
|
int addrel = decoder.peekElement();
|
||||||
|
if (addrel == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
catch (SAXException e) {
|
decoder.openElement();
|
||||||
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
|
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||||
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(addrel);
|
||||||
|
inputlist.add(new Varnode(addr, size));
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
decoder.closeElement(subel);
|
||||||
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
|
subel = decoder.peekElement();
|
||||||
}
|
}
|
||||||
|
if (subel == ElementId.ELEM_OUTPUT.getId()) {
|
||||||
|
decoder.openElement();
|
||||||
|
output = new ArrayList<>();
|
||||||
|
for (;;) {
|
||||||
|
int addrel = decoder.peekElement();
|
||||||
|
if (addrel == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
decoder.openElement();
|
||||||
|
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||||
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(addrel);
|
||||||
|
output.add(new Varnode(addr, size));
|
||||||
|
}
|
||||||
|
decoder.closeElement(subel);
|
||||||
|
}
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,8 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.xml.sax.Attributes;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.address.*;
|
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
import ghidra.xml.XmlElement;
|
||||||
|
@ -358,155 +357,74 @@ public class AddressXML {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse String containing an XML tag representing an Address.
|
* Create an address from "space" and "offset" attributes of the current element
|
||||||
* The format options are simple enough that we don't try to invoke
|
* @param decoder is the stream decoder
|
||||||
* an actual XML parser but just walk the string. This recognizes
|
* @return the decoded Address
|
||||||
* - \<addr>
|
* @throws PcodeXMLException for any problems decoding the stream
|
||||||
* - \<spaceid> or
|
|
||||||
* - any tag with a "space" and "offset" attribute
|
|
||||||
*
|
|
||||||
* @param addrstring is the string containing the XML tag
|
|
||||||
* @param addrfactory is the factory that can produce addresses
|
|
||||||
* @return the created Address or Address.NO_ADDRESS in some special cases
|
|
||||||
* @throws PcodeXMLException for a badly formed Address
|
|
||||||
*/
|
*/
|
||||||
public static Address readXML(String addrstring, AddressFactory addrfactory)
|
public static Address decodeFromAttributes(Decoder decoder) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
AddressSpace spc = null;
|
||||||
|
long offset = -1;
|
||||||
int tagstart = addrstring.indexOf('<');
|
for (;;) {
|
||||||
if (tagstart >= 0) {
|
int attribId = decoder.getNextAttributeId();
|
||||||
tagstart += 1;
|
if (attribId == 0) {
|
||||||
if (addrstring.startsWith("spaceid", tagstart)) {
|
break;
|
||||||
tagstart += 8;
|
}
|
||||||
int attrstart = addrstring.indexOf("name=\"", tagstart);
|
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
|
||||||
if (attrstart >= 0) {
|
spc = decoder.readSpace();
|
||||||
attrstart += 6;
|
}
|
||||||
int nameend = addrstring.indexOf('\"', attrstart);
|
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||||
if (nameend >= 0) {
|
offset = decoder.readUnsignedInteger();
|
||||||
AddressSpace spc =
|
|
||||||
addrfactory.getAddressSpace(addrstring.substring(attrstart, nameend));
|
|
||||||
int spaceid = spc.getSpaceID();
|
|
||||||
spc = addrfactory.getConstantSpace();
|
|
||||||
return spc.getAddress(spaceid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
// There are several tag forms where we essentially want to just look for 'space' and 'offset' attributes
|
|
||||||
// don't explicitly check the tag name
|
|
||||||
int spacestart = addrstring.indexOf("space=\"");
|
|
||||||
if (spacestart >= 4) {
|
|
||||||
spacestart += 7;
|
|
||||||
int spaceend = addrstring.indexOf('"', spacestart);
|
|
||||||
if (spaceend >= spacestart) {
|
|
||||||
String spcname = addrstring.substring(spacestart, spaceend);
|
|
||||||
int offstart = addrstring.indexOf("offset=\"");
|
|
||||||
if (offstart >= 4) {
|
|
||||||
offstart += 8;
|
|
||||||
int offend = addrstring.indexOf('"', offstart);
|
|
||||||
if (offend >= offstart) {
|
|
||||||
String offstr = addrstring.substring(offstart, offend);
|
|
||||||
AddressSpace spc = addrfactory.getAddressSpace(spcname);
|
|
||||||
// Unknown spaces may result from "spacebase" registers defined in cspec
|
|
||||||
if (spc == null) {
|
if (spc == null) {
|
||||||
return Address.NO_ADDRESS;
|
return Address.NO_ADDRESS;
|
||||||
}
|
}
|
||||||
long offset = SpecXmlUtils.decodeLong(offstr);
|
|
||||||
return spc.getAddress(offset);
|
return spc.getAddress(offset);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new PcodeXMLException("Badly formed address: " + addrstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the (first) size attribute from an XML tag string as an integer
|
* Create an address from a stream encoding. This recognizes elements
|
||||||
* @param addrxml is the XML string
|
|
||||||
* @return the decoded integer or zero if the attribute doesn't exist
|
|
||||||
*/
|
|
||||||
public static int readXMLSize(String addrxml) {
|
|
||||||
int attrstart = addrxml.indexOf("size=\"");
|
|
||||||
if (attrstart >= 4) {
|
|
||||||
attrstart += 6;
|
|
||||||
int attrend = addrxml.indexOf('\"', attrstart);
|
|
||||||
if (attrend > attrstart) {
|
|
||||||
int size = SpecXmlUtils.decodeInt(addrxml.substring(attrstart, attrend));
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an address from an XML parse tree node. This recognizes XML tags
|
|
||||||
* - \<addr>
|
* - \<addr>
|
||||||
* - \<spaceid>
|
* - \<spaceid>
|
||||||
* - \<iop> or
|
* - \<iop> or
|
||||||
* - any tag with "space" and "offset" attributes
|
* - any element with "space" and "offset" attributes
|
||||||
*
|
*
|
||||||
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
|
* An empty \<addr> element, with no attributes, results in Address.NO_ADDRESS being returned.
|
||||||
* @param el is the parse tree element
|
* @param decoder is the stream decoder
|
||||||
* @param addrFactory address factory used to create valid addresses
|
|
||||||
* @return Address created from XML info
|
* @return Address created from XML info
|
||||||
|
* @throws PcodeXMLException for any problems decoding the stream
|
||||||
*/
|
*/
|
||||||
public static Address readXML(XmlElement el, AddressFactory addrFactory) {
|
public static Address decode(Decoder decoder) throws PcodeXMLException {
|
||||||
String localName = el.getName();
|
int el = decoder.openElement();
|
||||||
if (localName.equals("spaceid")) {
|
if (el == ElementId.ELEM_SPACEID.getId()) {
|
||||||
AddressSpace spc = addrFactory.getAddressSpace(el.getAttribute("name"));
|
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_NAME);
|
||||||
|
decoder.closeElement(el);
|
||||||
int spaceid = spc.getSpaceID();
|
int spaceid = spc.getSpaceID();
|
||||||
spc = addrFactory.getConstantSpace();
|
spc = decoder.getAddressFactory().getConstantSpace();
|
||||||
return spc.getAddress(spaceid);
|
return spc.getAddress(spaceid);
|
||||||
}
|
}
|
||||||
else if (localName.equals("iop")) {
|
else if (el == ElementId.ELEM_IOP.getId()) {
|
||||||
int ref = SpecXmlUtils.decodeInt(el.getAttribute("value"));
|
int ref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_VALUE);
|
||||||
AddressSpace spc = addrFactory.getConstantSpace();
|
decoder.closeElement(el);
|
||||||
|
AddressSpace spc = decoder.getAddressFactory().getConstantSpace();
|
||||||
return spc.getAddress(ref);
|
return spc.getAddress(ref);
|
||||||
}
|
}
|
||||||
String space = el.getAttribute("space");
|
AddressSpace spc = null;
|
||||||
if (space == null) {
|
long offset = -1;
|
||||||
return Address.NO_ADDRESS;
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
|
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
|
||||||
AddressSpace spc = addrFactory.getAddressSpace(space);
|
spc = decoder.readSpace();
|
||||||
if (spc == null) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return spc.getAddress(offset);
|
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||||
|
offset = decoder.readUnsignedInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an Address given an XML tag name and its attributes. This recognizes XML tags
|
|
||||||
* - \<addr>
|
|
||||||
* - \<spaceid>
|
|
||||||
* - \<iop>
|
|
||||||
* - any tag with "space" or "offset" attributes
|
|
||||||
*
|
|
||||||
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
|
|
||||||
* @param localName is the name of the tag
|
|
||||||
* @param attr is the collection of attributes for the tag
|
|
||||||
* @param addrFactory is an Address factory
|
|
||||||
* @return the scanned address
|
|
||||||
*/
|
|
||||||
public static Address readXML(String localName, Attributes attr, AddressFactory addrFactory) {
|
|
||||||
if (localName.equals("spaceid")) {
|
|
||||||
AddressSpace spc = addrFactory.getAddressSpace(attr.getValue("name"));
|
|
||||||
int spaceid = spc.getSpaceID();
|
|
||||||
spc = addrFactory.getConstantSpace();
|
|
||||||
return spc.getAddress(spaceid);
|
|
||||||
}
|
}
|
||||||
else if (localName.equals("iop")) {
|
decoder.closeElement(el);
|
||||||
int ref = SpecXmlUtils.decodeInt(attr.getValue("value"));
|
|
||||||
AddressSpace spc = addrFactory.getConstantSpace();
|
|
||||||
return spc.getAddress(ref);
|
|
||||||
}
|
|
||||||
String space = attr.getValue("space");
|
|
||||||
if (space == null) {
|
|
||||||
return Address.NO_ADDRESS;
|
|
||||||
}
|
|
||||||
long offset = SpecXmlUtils.decodeLong(attr.getValue("offset"));
|
|
||||||
AddressSpace spc = addrFactory.getAddressSpace(space);
|
|
||||||
if (spc == null) {
|
if (spc == null) {
|
||||||
return Address.NO_ADDRESS;
|
return Address.NO_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
/* ###
|
||||||
|
* 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.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An annotation for a data element being transferred to/from a stream
|
||||||
|
*
|
||||||
|
* This class parallels the XML concept of an attribute on an element. An AttributeId describes
|
||||||
|
* a particular piece of data associated with an ElementId. The defining characteristic of the AttributeId is
|
||||||
|
* its name. Internally this name is associated with an integer id. The name (and id) uniquely determine
|
||||||
|
* the data being labeled, within the context of a specific ElementId. Within this context, an AttributeId labels either
|
||||||
|
* - An unsigned integer
|
||||||
|
* - A signed integer
|
||||||
|
* - A boolean value
|
||||||
|
* - A string
|
||||||
|
*
|
||||||
|
* 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<String, Integer> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the id associated with a specific attribute name
|
||||||
|
* @param nm the attribute name
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common attributes. Attributes with multiple uses
|
||||||
|
public static final AttributeId ATTRIB_CONTENT = new AttributeId("XMLcontent", 1);
|
||||||
|
public static final AttributeId ATTRIB_ALIGN = new AttributeId("align", 2);
|
||||||
|
public static final AttributeId ATTRIB_BIGENDIAN = new AttributeId("bigendian", 3);
|
||||||
|
public static final AttributeId ATTRIB_CONSTRUCTOR = new AttributeId("constructor", 4);
|
||||||
|
public static final AttributeId ATTRIB_DESTRUCTOR = new AttributeId("destructor", 5);
|
||||||
|
public static final AttributeId ATTRIB_EXTRAPOP = new AttributeId("extrapop", 6);
|
||||||
|
public static final AttributeId ATTRIB_FORMAT = new AttributeId("format", 7);
|
||||||
|
public static final AttributeId ATTRIB_HIDDENRETPARM = new AttributeId("hiddenretparm", 8);
|
||||||
|
public static final AttributeId ATTRIB_ID = new AttributeId("id", 9);
|
||||||
|
public static final AttributeId ATTRIB_INDEX = new AttributeId("index", 10);
|
||||||
|
public static final AttributeId ATTRIB_INDIRECTSTORAGE = new AttributeId("indirectstorage", 11);
|
||||||
|
public static final AttributeId ATTRIB_METATYPE = new AttributeId("metatype", 12);
|
||||||
|
public static final AttributeId ATTRIB_MODEL = new AttributeId("model", 13);
|
||||||
|
public static final AttributeId ATTRIB_NAME = new AttributeId("name", 14);
|
||||||
|
public static final AttributeId ATTRIB_NAMELOCK = new AttributeId("namelock", 15);
|
||||||
|
public static final AttributeId ATTRIB_OFFSET = new AttributeId("offset", 16);
|
||||||
|
public static final AttributeId ATTRIB_READONLY = new AttributeId("readonly", 17);
|
||||||
|
public static final AttributeId ATTRIB_REF = new AttributeId("ref", 18);
|
||||||
|
public static final AttributeId ATTRIB_SIZE = new AttributeId("size", 19);
|
||||||
|
public static final AttributeId ATTRIB_SPACE = new AttributeId("space", 20);
|
||||||
|
public static final AttributeId ATTRIB_THISPTR = new AttributeId("thisptr", 21);
|
||||||
|
public static final AttributeId ATTRIB_TYPE = new AttributeId("type", 22);
|
||||||
|
public static final AttributeId ATTRIB_TYPELOCK = new AttributeId("typelock", 23);
|
||||||
|
public static final AttributeId ATTRIB_VAL = new AttributeId("val", 24);
|
||||||
|
public static final AttributeId ATTRIB_VALUE = new AttributeId("value", 25);
|
||||||
|
public static final AttributeId ATTRIB_WORDSIZE = new AttributeId("wordsize", 26);
|
||||||
|
|
||||||
|
// address
|
||||||
|
public static final AttributeId ATTRIB_FIRST = new AttributeId("first", 27);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// stringmanage
|
||||||
|
public static final AttributeId ATTRIB_TRUNC = new AttributeId("trunc", 102);
|
||||||
|
|
||||||
|
// transform
|
||||||
|
public static final AttributeId ATTRIB_VECTOR_LANE_SIZES =
|
||||||
|
new AttributeId("vector_lane_sizes", 103);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// varmap
|
||||||
|
public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 129);
|
||||||
|
public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 130);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 147);
|
||||||
|
}
|
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
import ghidra.program.model.lang.UnknownInstructionException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block representing and '&&' or '||' control flow path within a conditional expression
|
* Block representing and '&&' or '||' control flow path within a conditional expression
|
||||||
|
@ -49,12 +48,13 @@ public class BlockCondition extends BlockGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||||
super.restoreXmlHeader(el);
|
super.decodeHeader(decoder);
|
||||||
String opcodename = el.getAttribute("opcode");
|
String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE);
|
||||||
try {
|
try {
|
||||||
opcode = PcodeOp.getOpcode(opcodename);
|
opcode = PcodeOp.getOpcode(opcodename);
|
||||||
} catch (UnknownInstructionException e) {
|
}
|
||||||
|
catch (UnknownInstructionException e) {
|
||||||
opcode = PcodeOp.BOOL_AND;
|
opcode = PcodeOp.BOOL_AND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Placeholder for a basic block (BlockBasic) within a structured
|
* Placeholder for a basic block (BlockBasic) within a structured
|
||||||
|
@ -37,7 +36,7 @@ public class BlockCopy extends PcodeBlock {
|
||||||
ref = null;
|
ref = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockCopy(Object r,Address addr) {
|
public BlockCopy(Object r, Address addr) {
|
||||||
super();
|
super();
|
||||||
ref = r;
|
ref = r;
|
||||||
blocktype = PcodeBlock.COPY;
|
blocktype = PcodeBlock.COPY;
|
||||||
|
@ -85,8 +84,8 @@ public class BlockCopy extends PcodeBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||||
super.restoreXmlHeader(el);
|
super.decodeHeader(decoder);
|
||||||
altindex = SpecXmlUtils.decodeInt(el.getAttribute("altindex"));
|
altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A "plain" goto block
|
* A "plain" goto block
|
||||||
|
@ -67,13 +65,13 @@ public class BlockGoto extends BlockGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
super.restoreXmlBody(parser, resolver);
|
super.decodeBody(decoder, resolver);
|
||||||
XmlElement el = parser.start("target");
|
int el = decoder.openElement(ElementId.ELEM_TARGET);
|
||||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||||
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
resolver.addGotoRef(this, target, depth);
|
resolver.addGotoRef(this, target, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A block (with in edges and out edges) that contains other blocks
|
* A block (with in edges and out edges) that contains other blocks
|
||||||
|
@ -35,7 +32,7 @@ public class BlockGraph extends PcodeBlock {
|
||||||
public BlockGraph() {
|
public BlockGraph() {
|
||||||
super();
|
super();
|
||||||
blocktype = PcodeBlock.GRAPH;
|
blocktype = PcodeBlock.GRAPH;
|
||||||
list = new ArrayList<PcodeBlock>();
|
list = new ArrayList<>();
|
||||||
maxindex = -1;
|
maxindex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,9 +42,9 @@ public class BlockGraph extends PcodeBlock {
|
||||||
* @param bl is the new block to add
|
* @param bl is the new block to add
|
||||||
*/
|
*/
|
||||||
public void addBlock(PcodeBlock bl) {
|
public void addBlock(PcodeBlock bl) {
|
||||||
int min,max;
|
int min, max;
|
||||||
if (bl instanceof BlockGraph) {
|
if (bl instanceof BlockGraph) {
|
||||||
BlockGraph gbl = (BlockGraph)bl;
|
BlockGraph gbl = (BlockGraph) bl;
|
||||||
min = gbl.index;
|
min = gbl.index;
|
||||||
max = gbl.maxindex;
|
max = gbl.maxindex;
|
||||||
}
|
}
|
||||||
|
@ -61,11 +58,13 @@ public class BlockGraph extends PcodeBlock {
|
||||||
maxindex = max;
|
maxindex = max;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (min < index)
|
if (min < index) {
|
||||||
index = min;
|
index = min;
|
||||||
if (max > maxindex)
|
}
|
||||||
|
if (max > maxindex) {
|
||||||
maxindex = max;
|
maxindex = max;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bl.parent = this;
|
bl.parent = this;
|
||||||
list.add(bl);
|
list.add(bl);
|
||||||
}
|
}
|
||||||
|
@ -75,11 +74,11 @@ public class BlockGraph extends PcodeBlock {
|
||||||
* getBlock(i) will return the block that satisfies block.getIndex() == i
|
* getBlock(i) will return the block that satisfies block.getIndex() == i
|
||||||
*/
|
*/
|
||||||
public void setIndices() {
|
public void setIndices() {
|
||||||
for(int i=0;i<list.size();++i) {
|
for (int i = 0; i < list.size(); ++i) {
|
||||||
list.get(i).index = i;
|
list.get(i).index = i;
|
||||||
}
|
}
|
||||||
index = 0;
|
index = 0;
|
||||||
maxindex = list.size()-1;
|
maxindex = list.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +91,7 @@ public class BlockGraph extends PcodeBlock {
|
||||||
/**
|
/**
|
||||||
* Retrieve the i-th block from this container
|
* Retrieve the i-th block from this container
|
||||||
* @param i is the index of the block to fetch
|
* @param i is the index of the block to fetch
|
||||||
* @return
|
* @return the block
|
||||||
*/
|
*/
|
||||||
public PcodeBlock getBlock(int i) {
|
public PcodeBlock getBlock(int i) {
|
||||||
return list.get(i);
|
return list.get(i);
|
||||||
|
@ -103,7 +102,7 @@ public class BlockGraph extends PcodeBlock {
|
||||||
* @param begin is the "from" block of the edge
|
* @param begin is the "from" block of the edge
|
||||||
* @param end is the "to" block of the edge
|
* @param end is the "to" block of the edge
|
||||||
*/
|
*/
|
||||||
public void addEdge(PcodeBlock begin,PcodeBlock end) {
|
public void addEdge(PcodeBlock begin, PcodeBlock end) {
|
||||||
end.addInEdge(begin, 0);
|
end.addInEdge(begin, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ public class BlockGraph extends PcodeBlock {
|
||||||
* @param ingraph is the original flow graph
|
* @param ingraph is the original flow graph
|
||||||
*/
|
*/
|
||||||
public void transferObjectRef(BlockGraph ingraph) {
|
public void transferObjectRef(BlockGraph ingraph) {
|
||||||
ArrayList<BlockGraph> queue = new ArrayList<BlockGraph>();
|
ArrayList<BlockGraph> queue = new ArrayList<>();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
queue.add(this);
|
queue.add(this);
|
||||||
while (pos < queue.size()) {
|
while (pos < queue.size()) {
|
||||||
|
@ -134,17 +133,17 @@ public class BlockGraph extends PcodeBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (block instanceof BlockGraph)
|
else if (block instanceof BlockGraph) {
|
||||||
queue.add((BlockGraph) block);
|
queue.add((BlockGraph) block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXmlBody(Writer writer) throws IOException {
|
public void saveXmlBody(Writer writer) throws IOException {
|
||||||
super.saveXmlBody(writer);
|
super.saveXmlBody(writer);
|
||||||
for(int i=0;i<list.size();++i) {
|
for (PcodeBlock bl : list) {
|
||||||
PcodeBlock bl = list.get(i);
|
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("<bhead");
|
buf.append("<bhead");
|
||||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", bl.getIndex());
|
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", bl.getIndex());
|
||||||
|
@ -153,44 +152,43 @@ public class BlockGraph extends PcodeBlock {
|
||||||
buf.append("/>\n");
|
buf.append("/>\n");
|
||||||
writer.write(buf.toString());
|
writer.write(buf.toString());
|
||||||
}
|
}
|
||||||
for(int i=0;i<list.size();++i) {
|
for (PcodeBlock bl : list) {
|
||||||
PcodeBlock bl = list.get(i);
|
|
||||||
bl.saveXml(writer);
|
bl.saveXml(writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
BlockMap newresolver = new BlockMap(resolver);
|
BlockMap newresolver = new BlockMap(resolver);
|
||||||
super.restoreXmlBody(parser, newresolver);
|
super.decodeBody(decoder, newresolver);
|
||||||
ArrayList<PcodeBlock> tmplist = new ArrayList<PcodeBlock>();
|
ArrayList<PcodeBlock> tmplist = new ArrayList<>();
|
||||||
while(parser.peek().isStart()) {
|
for (;;) {
|
||||||
if (!parser.peek().getName().equals("bhead"))
|
int el = decoder.peekElement();
|
||||||
|
if (el != ElementId.ELEM_BHEAD.getId()) {
|
||||||
break;
|
break;
|
||||||
XmlElement el = parser.start();
|
}
|
||||||
int ind = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
decoder.openElement();
|
||||||
String name = el.getAttribute("type");
|
int ind = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
|
String name = decoder.readString(AttributeId.ATTRIB_TYPE);
|
||||||
PcodeBlock newbl = newresolver.createBlock(name, ind);
|
PcodeBlock newbl = newresolver.createBlock(name, ind);
|
||||||
tmplist.add(newbl);
|
tmplist.add(newbl);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
newresolver.sortLevelList();
|
newresolver.sortLevelList();
|
||||||
for(int i=0;i<tmplist.size();++i) {
|
for (PcodeBlock bl : tmplist) {
|
||||||
PcodeBlock bl = tmplist.get(i);
|
bl.decode(decoder, newresolver);
|
||||||
bl.restoreXml(parser, newresolver);
|
|
||||||
addBlock(bl);
|
addBlock(bl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore all blocks and edges in this container from an XML stream.
|
* Decode all blocks and edges in this container from a stream.
|
||||||
* @param parser is the XML stream parser
|
* @param decoder is the stream decoder
|
||||||
* @param factory is the AddressFactory used to construct any Address
|
* @throws PcodeXMLException if there are invalid encodings
|
||||||
* @throws PcodeXMLException if part of the XML description is invalid
|
|
||||||
*/
|
*/
|
||||||
public void restoreXml(XmlPullParser parser, AddressFactory factory) throws PcodeXMLException {
|
public void restoreXml(Decoder decoder) throws PcodeXMLException {
|
||||||
BlockMap resolver = new BlockMap(factory);
|
BlockMap resolver = new BlockMap(decoder.getAddressFactory());
|
||||||
restoreXml(parser,resolver);
|
decode(decoder, resolver);
|
||||||
resolver.resolveGotoReferences();
|
resolver.resolveGotoReferences();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block representing an if () goto control flow
|
* Block representing an if () goto control flow
|
||||||
|
@ -70,13 +68,13 @@ public class BlockIfGoto extends BlockGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
super.restoreXmlBody(parser,resolver);
|
super.decodeBody(decoder, resolver);
|
||||||
XmlElement el = parser.start("target");
|
int el = decoder.openElement(ElementId.ELEM_TARGET);
|
||||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||||
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
gototarget = null;
|
gototarget = null;
|
||||||
resolver.addGotoRef(this, target, depth);
|
resolver.addGotoRef(this, target, depth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A block representing a 2-or-more control flow branchpoint
|
* A block representing a 2-or-more control flow branchpoint
|
||||||
|
@ -38,7 +36,7 @@ public class BlockMultiGoto extends BlockGraph {
|
||||||
|
|
||||||
public BlockMultiGoto() {
|
public BlockMultiGoto() {
|
||||||
super();
|
super();
|
||||||
targets = new ArrayList<PcodeBlock>();
|
targets = new ArrayList<>();
|
||||||
blocktype = PcodeBlock.MULTIGOTO;
|
blocktype = PcodeBlock.MULTIGOTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +47,8 @@ public class BlockMultiGoto extends BlockGraph {
|
||||||
@Override
|
@Override
|
||||||
public void saveXmlBody(Writer writer) throws IOException {
|
public void saveXmlBody(Writer writer) throws IOException {
|
||||||
super.saveXmlBody(writer);
|
super.saveXmlBody(writer);
|
||||||
for(int i=0;i<targets.size();++i) {
|
for (PcodeBlock gototarget : targets) {
|
||||||
|
|
||||||
PcodeBlock gototarget = targets.get(i);
|
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("<target");
|
buf.append("<target");
|
||||||
PcodeBlock leaf = gototarget.getFrontLeaf();
|
PcodeBlock leaf = gototarget.getFrontLeaf();
|
||||||
|
@ -65,14 +62,17 @@ public class BlockMultiGoto extends BlockGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
super.restoreXmlBody(parser, resolver);
|
super.decodeBody(decoder, resolver);
|
||||||
while(parser.peek().isStart()) {
|
for (;;) {
|
||||||
XmlElement el = parser.start("target");
|
int el = decoder.peekElement();
|
||||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
if (el != ElementId.ELEM_TARGET.getId()) {
|
||||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
break;
|
||||||
// int gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
}
|
||||||
parser.end(el);
|
decoder.openElement();
|
||||||
|
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
|
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||||
|
decoder.closeElement(el);
|
||||||
resolver.addGotoRef(this, target, depth);
|
resolver.addGotoRef(this, target, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* ###
|
||||||
|
* 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.InputStream;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.AddressFactory;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for reading structured data from a stream
|
||||||
|
*
|
||||||
|
* All data is loosely structured as with an XML document. A document contains a nested set
|
||||||
|
* of elements, with labels corresponding to the ElementId class. A single element can hold
|
||||||
|
* zero or more attributes and zero or more child elements. An attribute holds a primitive
|
||||||
|
* data element (boolean, long, String) and is labeled by an AttributeId. The document is traversed
|
||||||
|
* using a sequence of openElement() and closeElement() calls, intermixed with read*() calls to extract
|
||||||
|
* the data. The elements are traversed in a depth first order. Attributes within an element can
|
||||||
|
* be traversed in order using repeated calls to the getNextAttributeId() method, followed by a calls to
|
||||||
|
* 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().
|
||||||
|
*/
|
||||||
|
public interface Decoder {
|
||||||
|
|
||||||
|
public AddressFactory getAddressFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear any current decoding state.
|
||||||
|
* Allows the same decoder to be reused. Object is ready for new call to ingestStream.
|
||||||
|
*/
|
||||||
|
public void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare to decode a given stream.
|
||||||
|
* Called once before any decoding. Currently this is assumed to make an internal copy of
|
||||||
|
* the stream data, i.e. the input stream is cleared before any decoding takes place.
|
||||||
|
* @param stream is the given input stream to be decode
|
||||||
|
* @param source is a label describing the source of the input stream
|
||||||
|
* @throws PcodeXMLException for errors reading the stream
|
||||||
|
*/
|
||||||
|
public void ingestStream(InputStream stream, String source) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek at the next child element of the current parent, without traversing in (opening) it.
|
||||||
|
* The element id is returned, which can be compared to ElementId labels.
|
||||||
|
* If there are no remaining child elements to traverse, 0 is returned.
|
||||||
|
* @return the element id or 0
|
||||||
|
*/
|
||||||
|
public int peekElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public int openElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open (traverse into) the next child element, which must be of a specific type
|
||||||
|
* The child becomes the current parent, and its attributes are initialized for use with
|
||||||
|
* getNextAttributeId. The child must match the given element id or an exception is thrown.
|
||||||
|
* @param elemId is the given element id to match
|
||||||
|
* @return the id of the child element
|
||||||
|
* @throws PcodeXMLException if the expected element is not the next element
|
||||||
|
*/
|
||||||
|
public int openElement(ElementId elemId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the current element
|
||||||
|
* The data for the current element is considered fully processed. If the element has additional
|
||||||
|
* children, an exception is thrown. The stream must indicate the end of the element in some way.
|
||||||
|
* @param id is the id of the element to close (which must be the current element)
|
||||||
|
* @throws PcodeXMLException if not at end of expected element
|
||||||
|
*/
|
||||||
|
public void closeElement(int id) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the current element, skipping any child elements that have not yet been parsed.
|
||||||
|
* This closes the given element, which must be current. If there are child elements that have
|
||||||
|
* not been parsed, this is not considered an error, and they are skipped over in the parse.
|
||||||
|
* @param id is the id of the element to close (which must be the current element)
|
||||||
|
* @throws PcodeXMLException if the indicated element is not the current element
|
||||||
|
*/
|
||||||
|
public void closeElementSkipping(int id) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next attribute id for the current element
|
||||||
|
* Attributes are automatically set up for traversal using this method, when the element is
|
||||||
|
* opened. If all attributes have been traversed (or there are no attributes), 0 is returned.
|
||||||
|
* @return the id of the next attribute or 0
|
||||||
|
*/
|
||||||
|
public int getNextAttributeId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset attribute traversal for the current element
|
||||||
|
* Attributes for a single element can be traversed more than once using the getNextAttributeId
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
public void rewindAttributes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current attribute as a boolean value
|
||||||
|
* The last attribute, as returned by getNextAttributeId, is treated as a boolean, and its
|
||||||
|
* value is returned.
|
||||||
|
* @return the boolean value associated with the current attribute.
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public boolean readBool() throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and parse a specific attribute in the current element as a boolean value
|
||||||
|
* The set of attributes for the current element is searched for a match to the given attribute
|
||||||
|
* id. This attribute is then parsed as a boolean and its value returned.
|
||||||
|
* If there is no attribute matching the id, an exception is thrown.
|
||||||
|
* Parsing via getNextAttributeId is reset.
|
||||||
|
* @param attribId is the specific attribute id to match
|
||||||
|
* @return the boolean value
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public boolean readBool(AttributeId attribId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current attribute as a signed integer value
|
||||||
|
* The last attribute, as returned by getNextAttributeId, is treated as a signed integer,
|
||||||
|
* and its value is returned.
|
||||||
|
* @return the signed integer value associated with the current attribute.
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public long readSignedInteger() throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and parse a specific attribute in the current element as a signed integer
|
||||||
|
* The set of attributes for the current element is searched for a match to the given attribute
|
||||||
|
* id. This attribute is then parsed as a signed integer and its value returned.
|
||||||
|
* If there is no attribute matching the id, an exception is thrown.
|
||||||
|
* Parsing via getNextAttributeId is reset.
|
||||||
|
* @param attribId is the specific attribute id to match
|
||||||
|
* @return the signed integer value
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current attribute as an unsigned integer value
|
||||||
|
* The last attribute, as returned by getNextAttributeId, is treated as an unsigned integer,
|
||||||
|
* and its value is returned.
|
||||||
|
* @return the unsigned integer value associated with the current attribute.
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public long readUnsignedInteger() throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and parse a specific attribute in the current element as an unsigned integer
|
||||||
|
* The set of attributes for the current element is searched for a match to the given attribute
|
||||||
|
* id. This attribute is then parsed as an unsigned integer and its value returned.
|
||||||
|
* If there is no attribute matching the id, an exception is thrown.
|
||||||
|
* Parsing via getNextAttributeId is reset.
|
||||||
|
* @param attribId is the specific attribute id to match
|
||||||
|
* @return the unsigned integer value
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current attribute as a string
|
||||||
|
* The last attribute, as returned by getNextAttributeId, is returned as a string.
|
||||||
|
* @return the string associated with the current attribute.
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public String readString() throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the specific attribute in the current element and return it as a string
|
||||||
|
* The set of attributes for the current element is searched for a match to the given attribute
|
||||||
|
* id. This attribute is then returned as a string. If there is no attribute matching the id,
|
||||||
|
* and exception is thrown. Parse via getNextAttributeId is reset.
|
||||||
|
* @param attribId is the specific attribute id to match
|
||||||
|
* @return the string associated with the attribute
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public String readString(AttributeId attribId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the current attribute as an address space
|
||||||
|
* The last attribute, as returned by getNextAttributeId, is returned as an address space.
|
||||||
|
* @return the address space associated with the current attribute.
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public AddressSpace readSpace() throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the specific attribute in the current element and return it as an address space
|
||||||
|
* Search attributes from the current element for a match to the given attribute id.
|
||||||
|
* Return this attribute as an address space. If there is no attribute matching the id, an
|
||||||
|
* exception is thrown. Parse via getNextAttributeId is reset.
|
||||||
|
* @param attribId is the specific attribute id to match
|
||||||
|
* @return the address space associated with the attribute
|
||||||
|
* @throws PcodeXMLException if the expected value is not present
|
||||||
|
*/
|
||||||
|
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip parsing of the next element
|
||||||
|
* The element skipped is the one that would be opened by the next call to openElement.
|
||||||
|
* @throws PcodeXMLException if there is no new element
|
||||||
|
*/
|
||||||
|
public default void skipElement() throws PcodeXMLException {
|
||||||
|
int elemId = openElement();
|
||||||
|
closeElementSkipping(elemId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,9 +21,6 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HighSymbol mapping based on local hashing of the symbol's Varnode within a
|
* A HighSymbol mapping based on local hashing of the symbol's Varnode within a
|
||||||
|
@ -63,11 +60,11 @@ public class DynamicEntry extends SymbolEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement addrel = parser.start("hash");
|
int addrel = decoder.openElement(ElementId.ELEM_HASH);
|
||||||
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
|
hash = decoder.readUnsignedInteger(AttributeId.ATTRIB_VAL);
|
||||||
parser.end(addrel);
|
decoder.closeElement(addrel);
|
||||||
parseRangeList(parser);
|
decodeRangeList(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
/* ###
|
||||||
|
* 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.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An annotation for a specific collection of hierarchical data
|
||||||
|
*
|
||||||
|
* This class parallels the XML concept of an element. An ElementId describes a collection of data, where each
|
||||||
|
* piece is annotated by a specific AttributeId. In addition, each ElementId can contain zero or more child
|
||||||
|
* ElementId objects, forming a hierarchy of annotated data. Each ElementId has a name, which is unique at least
|
||||||
|
* within the context of its parent ElementId. Internally this name is associated with an integer id. A special
|
||||||
|
* AttributeId ATTRIB_CONTENT is used to label the XML element's text content, which is traditionally not labeled
|
||||||
|
* as an attribute.
|
||||||
|
*/
|
||||||
|
public class ElementId {
|
||||||
|
private static HashMap<String, Integer> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the id associated with a specific element name
|
||||||
|
* @param nm the element name
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final ElementId ELEM_DATA = new ElementId("data", 1);
|
||||||
|
public static final ElementId ELEM_INPUT = new ElementId("input", 2);
|
||||||
|
public static final ElementId ELEM_OFF = new ElementId("off", 3);
|
||||||
|
public static final ElementId ELEM_OUTPUT = new ElementId("output", 4);
|
||||||
|
public static final ElementId ELEM_RETURNADDRESS = new ElementId("returnaddress", 5);
|
||||||
|
public static final ElementId ELEM_SYMBOL = new ElementId("symbol", 6);
|
||||||
|
public static final ElementId ELEM_TARGET = new ElementId("target", 7);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// variable
|
||||||
|
public static final ElementId ELEM_HIGH = new ElementId("high", 205);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// ghidra_process
|
||||||
|
public static final ElementId ELEM_DOC = new ElementId("doc", 218);
|
||||||
|
|
||||||
|
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 231);
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* ###
|
||||||
|
* 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 ghidra.program.model.address.AddressSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for writing structured data to a stream
|
||||||
|
*
|
||||||
|
* The resulting encoded data is structured similarly to an XML document. The document contains a nested set
|
||||||
|
* of \elements, with labels corresponding to the ElementId class. A single element can hold
|
||||||
|
* zero or more attributes and zero or more child elements. An attribute holds a primitive
|
||||||
|
* data element (boolean, long, String) and is labeled by an AttributeId. The document is written
|
||||||
|
* using a sequence of openElement() and closeElement() calls, intermixed with write*() calls to encode
|
||||||
|
* the data primitives. All primitives written using a write*() call are associated with current open element,
|
||||||
|
* and all write*() calls for one element must come before opening any child element.
|
||||||
|
* The traditional XML element text content can be written using the special ATTRIB_CONTENT AttributeId, which
|
||||||
|
* must be the last write*() call associated with the specific element.
|
||||||
|
*/
|
||||||
|
public interface Encoder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear any state associated with the encoder
|
||||||
|
* The encoder should be ready to write a new document after this call.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void openElement(ElementId elemId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void closeElement(ElementId elemId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void writeBool(AttributeId attribId, boolean val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void writeSignedInteger(AttributeId attribId, long val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void writeUnsignedInteger(AttributeId attribId, long val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void writeString(AttributeId attribId, String val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void writeSpace(AttributeId attribId, AddressSpace spc);
|
||||||
|
}
|
|
@ -18,8 +18,6 @@ package ghidra.program.model.pcode;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
public class EquateSymbol extends HighSymbol {
|
public class EquateSymbol extends HighSymbol {
|
||||||
|
|
||||||
|
@ -66,12 +64,22 @@ public class EquateSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement symel = parser.start("equatesymbol");
|
int symel = decoder.openElement(ElementId.ELEM_EQUATESYMBOL);
|
||||||
restoreXMLHeader(symel);
|
decodeHeader(decoder);
|
||||||
type = DataType.DEFAULT;
|
type = DataType.DEFAULT;
|
||||||
convert = FORMAT_DEFAULT;
|
convert = FORMAT_DEFAULT;
|
||||||
String formString = symel.getAttribute("format");
|
decoder.rewindAttributes();
|
||||||
|
String formString = null;
|
||||||
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_FORMAT.getId()) {
|
||||||
|
formString = decoder.readString();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (formString != null) {
|
if (formString != null) {
|
||||||
if (formString.equals("hex")) {
|
if (formString.equals("hex")) {
|
||||||
convert = FORMAT_HEX;
|
convert = FORMAT_HEX;
|
||||||
|
@ -89,9 +97,10 @@ public class EquateSymbol extends HighSymbol {
|
||||||
convert = FORMAT_BIN;
|
convert = FORMAT_BIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.start("value");
|
int valel = decoder.openElement(ElementId.ELEM_VALUE);
|
||||||
value = SpecXmlUtils.decodeLong(parser.end().getText()); // End <value> tag
|
value = decoder.readUnsignedInteger(AttributeId.ATTRIB_CONTENT);
|
||||||
parser.end(symel);
|
decoder.closeElement(valel);
|
||||||
|
decoder.closeElement(symel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,8 +21,6 @@ import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -152,7 +150,7 @@ public class FunctionPrototype {
|
||||||
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
|
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
|
||||||
outputlock = false;
|
outputlock = false;
|
||||||
returnstorage = VariableStorage.VOID_STORAGE; // Treat as unlocked void
|
returnstorage = VariableStorage.VOID_STORAGE; // Treat as unlocked void
|
||||||
returntype = DataType.VOID;
|
returntype = VoidDataType.dataType;
|
||||||
}
|
}
|
||||||
voidinputlock =
|
voidinputlock =
|
||||||
(f.getSignatureSource() != SourceType.DEFAULT) && f.getParameterCount() == 0;
|
(f.getSignatureSource() != SourceType.DEFAULT) && f.getParameterCount() == 0;
|
||||||
|
@ -413,22 +411,22 @@ public class FunctionPrototype {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the function prototype from {@code <prototype>} tag.
|
* Decode the function prototype from a {@code <prototype>} element in the stream.
|
||||||
* @param parser is the XML document to parse
|
* @param decoder is the stream decoder
|
||||||
* @param dtmanage is the DataTypeManager used to parse data-type tags
|
* @param dtmanage is the DataTypeManager used to parse data-type tags
|
||||||
* @throws PcodeXMLException for any problems parsing
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage)
|
public void decodePrototype(Decoder decoder, PcodeDataTypeManager dtmanage)
|
||||||
throws PcodeXMLException {
|
throws PcodeXMLException {
|
||||||
XmlElement node = parser.start("prototype");
|
int node = decoder.openElement(ElementId.ELEM_PROTOTYPE);
|
||||||
modelname = node.getAttribute("model");
|
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
|
||||||
PrototypeModel protoModel =
|
PrototypeModel protoModel =
|
||||||
dtmanage.getProgram().getCompilerSpec().getCallingConvention(modelname);
|
dtmanage.getProgram().getCompilerSpec().getCallingConvention(modelname);
|
||||||
if (protoModel == null) {
|
if (protoModel == null) {
|
||||||
throw new PcodeXMLException("Bad prototype model name: " + modelname);
|
throw new PcodeXMLException("Bad prototype model name: " + modelname);
|
||||||
}
|
}
|
||||||
hasThis = protoModel.hasThisPointer();
|
hasThis = protoModel.hasThisPointer();
|
||||||
String val = node.getAttribute("extrapop");
|
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
|
||||||
if (val.equals("unknown")) {
|
if (val.equals("unknown")) {
|
||||||
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||||
}
|
}
|
||||||
|
@ -436,52 +434,61 @@ public class FunctionPrototype {
|
||||||
extrapop = SpecXmlUtils.decodeInt(val);
|
extrapop = SpecXmlUtils.decodeInt(val);
|
||||||
}
|
}
|
||||||
modellock = false;
|
modellock = false;
|
||||||
if (node.hasAttribute("modellock")) {
|
|
||||||
modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock"));
|
|
||||||
}
|
|
||||||
dotdotdot = false;
|
dotdotdot = false;
|
||||||
if (node.hasAttribute("dotdotdot")) {
|
|
||||||
dotdotdot = SpecXmlUtils.decodeBoolean(node.getAttribute("dotdotdot"));
|
|
||||||
}
|
|
||||||
voidinputlock = false;
|
voidinputlock = false;
|
||||||
if (node.hasAttribute("voidlock")) {
|
|
||||||
voidinputlock = SpecXmlUtils.decodeBoolean(node.getAttribute("voidlock"));
|
|
||||||
}
|
|
||||||
isinline = false;
|
isinline = false;
|
||||||
if (node.hasAttribute("inline")) {
|
|
||||||
isinline = SpecXmlUtils.decodeBoolean(node.getAttribute("inline"));
|
|
||||||
}
|
|
||||||
noreturn = false;
|
noreturn = false;
|
||||||
if (node.hasAttribute("noreturn")) {
|
|
||||||
noreturn = SpecXmlUtils.decodeBoolean(node.getAttribute("noreturn"));
|
|
||||||
}
|
|
||||||
custom = false;
|
custom = false;
|
||||||
if (node.hasAttribute("custom")) {
|
|
||||||
custom = SpecXmlUtils.decodeBoolean(node.getAttribute("custom"));
|
|
||||||
}
|
|
||||||
isConstruct = false;
|
isConstruct = false;
|
||||||
if (node.hasAttribute("constructor")) {
|
|
||||||
isConstruct = SpecXmlUtils.decodeBoolean(node.getAttribute("constructor"));
|
|
||||||
}
|
|
||||||
isDestruct = false;
|
isDestruct = false;
|
||||||
if (node.hasAttribute("destructor")) {
|
for (;;) {
|
||||||
isDestruct = SpecXmlUtils.decodeBoolean(node.getAttribute("destructor"));
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
XmlElement retel = parser.start("returnsym");
|
if (attribId == AttributeId.ATTRIB_MODELLOCK.getId()) {
|
||||||
|
modellock = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_DOTDOTDOT.getId()) {
|
||||||
|
dotdotdot = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_VOIDLOCK.getId()) {
|
||||||
|
voidinputlock = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_INLINE.getId()) {
|
||||||
|
isinline = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_NORETURN.getId()) {
|
||||||
|
noreturn = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_CUSTOM.getId()) {
|
||||||
|
custom = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_CONSTRUCTOR.getId()) {
|
||||||
|
isConstruct = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_DESTRUCTOR.getId()) {
|
||||||
|
isDestruct = decoder.readBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int retel = decoder.openElement(ElementId.ELEM_RETURNSYM);
|
||||||
outputlock = false;
|
outputlock = false;
|
||||||
if (retel.hasAttribute("typelock")) {
|
for (;;) {
|
||||||
outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock"));
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
|
||||||
|
outputlock = decoder.readBool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parser.discardSubTree();
|
|
||||||
returnstorage = null; // For now don't use decompiler's return storage
|
|
||||||
returntype = dtmanage.readXMLDataType(parser);
|
|
||||||
parser.end(retel);
|
|
||||||
|
|
||||||
XmlElement peeknode = parser.peek();
|
decoder.skipElement();
|
||||||
if ((peeknode != null) && peeknode.isStart()) {
|
returnstorage = null; // For now don't use decompiler's return storage
|
||||||
parser.discardSubTree(); // The decompiler may return an <inject> tag
|
returntype = dtmanage.decodeDataType(decoder);
|
||||||
}
|
decoder.closeElement(retel);
|
||||||
parser.end(node);
|
|
||||||
|
decoder.closeElementSkipping(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SymbolUtilities;
|
import ghidra.program.model.symbol.SymbolUtilities;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A global symbol as part of the decompiler's model of a function. This symbol can
|
* A global symbol as part of the decompiler's model of a function. This symbol can
|
||||||
|
@ -149,8 +148,8 @@ public class HighCodeSymbol extends HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
super.restoreXML(parser);
|
super.decode(decoder);
|
||||||
symbol = null;
|
symbol = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,6 @@ import ghidra.program.model.data.AbstractIntegerDataType;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -88,10 +85,19 @@ public class HighConstant extends HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("high");
|
//int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
long symref = 0;
|
||||||
restoreInstances(parser, el);
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||||
|
symref = decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodeInstances(decoder);
|
||||||
pcaddr = function.getPCAddress(represent);
|
pcaddr = function.getPCAddress(represent);
|
||||||
if (symref != 0) {
|
if (symref != 0) {
|
||||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||||
|
@ -115,7 +121,7 @@ public class HighConstant extends HighVariable {
|
||||||
symbol.setHighVariable(this);
|
symbol.setHighVariable(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(el);
|
//decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.xml.sax.*;
|
|
||||||
|
|
||||||
import ghidra.program.database.function.FunctionDB;
|
import ghidra.program.database.function.FunctionDB;
|
||||||
import ghidra.program.database.symbol.CodeSymbol;
|
import ghidra.program.database.symbol.CodeSymbol;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
@ -28,11 +25,9 @@ import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -219,9 +214,9 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
return super.newVarnode(sz, addr, id);
|
return super.newVarnode(sz, addr, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
|
private void decodeHigh(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.peek();
|
int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||||
String classstring = el.getAttribute("class");
|
String classstring = decoder.readString(AttributeId.ATTRIB_CLASS);
|
||||||
HighVariable var;
|
HighVariable var;
|
||||||
switch (classstring.charAt(0)) {
|
switch (classstring.charAt(0)) {
|
||||||
case 'o':
|
case 'o':
|
||||||
|
@ -242,81 +237,80 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
default:
|
default:
|
||||||
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
|
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
|
||||||
}
|
}
|
||||||
var.restoreXml(parser);
|
var.decode(decoder);
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
|
private void decodeHighlist(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("highlist");
|
int el = decoder.openElement(ElementId.ELEM_HIGHLIST);
|
||||||
while (parser.peek().isStart()) {
|
while (decoder.peekElement() != 0) {
|
||||||
readHighXML(parser);
|
decodeHigh(decoder);
|
||||||
}
|
}
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement start = parser.start("function");
|
int start = decoder.openElement(ElementId.ELEM_FUNCTION);
|
||||||
String name = start.getAttribute("name");
|
String name = decoder.readString(AttributeId.ATTRIB_NAME);
|
||||||
if (!func.getName().equals(name)) {
|
if (!func.getName().equals(name)) {
|
||||||
throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name);
|
throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name);
|
||||||
}
|
}
|
||||||
while (!parser.peek().isEnd()) {
|
for (;;) {
|
||||||
XmlElement subel = parser.peek();
|
int subel = decoder.peekElement();
|
||||||
if (subel.getName().equals("addr")) {
|
if (subel == 0) {
|
||||||
subel = parser.start("addr");
|
break;
|
||||||
Address addr = AddressXML.readXML(subel, getAddressFactory());
|
}
|
||||||
parser.end(subel);
|
if (subel == ElementId.ELEM_ADDR.getId()) {
|
||||||
|
Address addr = AddressXML.decode(decoder);
|
||||||
addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr);
|
addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr);
|
||||||
if (!func.getEntryPoint().equals(addr)) {
|
if (!func.getEntryPoint().equals(addr)) {
|
||||||
throw new PcodeXMLException("Mismatched address in function tag");
|
throw new PcodeXMLException("Mismatched address in function tag");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("prototype")) {
|
else if (subel == ElementId.ELEM_PROTOTYPE.getId()) {
|
||||||
proto.readPrototypeXML(parser, getDataTypeManager());
|
proto.decodePrototype(decoder, getDataTypeManager());
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("localdb")) {
|
else if (subel == ElementId.ELEM_LOCALDB.getId()) {
|
||||||
localSymbols.parseScopeXML(parser);
|
localSymbols.decodeScope(decoder);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("ast")) {
|
else if (subel == ElementId.ELEM_AST.getId()) {
|
||||||
super.readXML(parser);
|
super.decode(decoder);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("highlist")) {
|
else if (subel == ElementId.ELEM_HIGHLIST.getId()) {
|
||||||
readHighlistXML(parser);
|
decodeHighlist(decoder);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("jumptablelist")) {
|
else if (subel == ElementId.ELEM_JUMPTABLELIST.getId()) {
|
||||||
readJumpTableListXML(parser);
|
decodeJumpTableList(decoder);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("override")) {
|
else if (subel == ElementId.ELEM_OVERRIDE.getId()) {
|
||||||
// Do nothing with override at the moment
|
// Do nothing with override at the moment
|
||||||
parser.discardSubTree();
|
decoder.skipElement();
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("scope")) {
|
else if (subel == ElementId.ELEM_SCOPE.getId()) {
|
||||||
// This must be a subscope of the local scope
|
// This must be a subscope of the local scope
|
||||||
// Currently this can only hold static variables of the function
|
// Currently this can only hold static variables of the function
|
||||||
// which ghidra already knows about
|
// which ghidra already knows about
|
||||||
parser.discardSubTree();
|
decoder.skipElement();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new PcodeXMLException("Unknown tag in function: " + subel.getName());
|
throw new PcodeXMLException("Unknown element in function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(start);
|
decoder.closeElement(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read in the Jump Table list for this function from XML
|
* Decode the Jump Table list for this function from the stream
|
||||||
*
|
*
|
||||||
* @param parser is the XML stream
|
* @param decoder is the stream decoder
|
||||||
* @throws PcodeXMLException for any format errors
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
private void readJumpTableListXML(XmlPullParser parser) throws PcodeXMLException {
|
private void decodeJumpTableList(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("jumptablelist");
|
int el = decoder.openElement(ElementId.ELEM_JUMPTABLELIST);
|
||||||
while (parser.peek().isStart()) {
|
while (decoder.peekElement() != 0) {
|
||||||
JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace());
|
JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace());
|
||||||
table.restoreXml(parser, getAddressFactory());
|
table.decode(decoder);
|
||||||
if (!table.isEmpty()) {
|
if (!table.isEmpty()) {
|
||||||
if (jumpTables == null) {
|
if (jumpTables == null) {
|
||||||
jumpTables = new ArrayList<>();
|
jumpTables = new ArrayList<>();
|
||||||
|
@ -324,7 +318,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
jumpTables.add(table);
|
jumpTables.add(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Address getPCAddress(Varnode rep) {
|
protected Address getPCAddress(Varnode rep) {
|
||||||
|
@ -495,26 +489,6 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
return resBuf.toString();
|
return resBuf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
|
||||||
final String targetName) {
|
|
||||||
return new ErrorHandler() {
|
|
||||||
@Override
|
|
||||||
public void error(SAXParseException exception) throws SAXException {
|
|
||||||
Msg.error(errOriginator, "Error parsing " + targetName, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fatalError(SAXParseException exception) throws SAXException {
|
|
||||||
Msg.error(errOriginator, "Fatal error parsing " + targetName, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void warning(SAXParseException exception) throws SAXException {
|
|
||||||
Msg.warn(errOriginator, "Warning parsing " + targetName, exception);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Namespace findOverrideSpace(Function func) {
|
public static Namespace findOverrideSpace(Function func) {
|
||||||
SymbolTable symtab = func.getProgram().getSymbolTable();
|
SymbolTable symtab = func.getProgram().getSymbolTable();
|
||||||
return findNamespace(symtab, func, "override");
|
return findNamespace(symtab, func, "override");
|
||||||
|
@ -592,29 +566,6 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create XML parse tree from an input XML string
|
|
||||||
*
|
|
||||||
* TODO: this probably doesn't belong here.
|
|
||||||
*
|
|
||||||
* @param xml is the XML string to parse
|
|
||||||
* @param handler is the handler to use for parsing errors
|
|
||||||
* @return the XML tree
|
|
||||||
*
|
|
||||||
* @throws PcodeXMLException for format errors in the XML
|
|
||||||
*/
|
|
||||||
static public XmlPullParser stringTree(InputStream xml, ErrorHandler handler)
|
|
||||||
throws PcodeXMLException {
|
|
||||||
try {
|
|
||||||
XmlPullParser parser =
|
|
||||||
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The decompiler treats some namespaces as equivalent to the "global" namespace.
|
* The decompiler treats some namespaces as equivalent to the "global" namespace.
|
||||||
* Return true if the given namespace is treated as equivalent.
|
* Return true if the given namespace is treated as equivalent.
|
||||||
|
|
|
@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -50,15 +47,23 @@ public class HighGlobal extends HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("high");
|
// int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
long symref = 0;
|
||||||
String attrString = el.getAttribute("offset");
|
|
||||||
offset = -1;
|
offset = -1;
|
||||||
if (attrString != null) {
|
for (;;) {
|
||||||
offset = SpecXmlUtils.decodeInt(attrString);
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
restoreInstances(parser, el);
|
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||||
|
offset = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||||
|
symref = decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodeInstances(decoder);
|
||||||
if (symref != 0) {
|
if (symref != 0) {
|
||||||
symbol = function.getGlobalSymbolMap().getSymbol(symref);
|
symbol = function.getGlobalSymbolMap().getSymbol(symref);
|
||||||
}
|
}
|
||||||
|
@ -94,6 +99,6 @@ public class HighGlobal extends HighVariable {
|
||||||
}
|
}
|
||||||
symbol.setHighVariable(this);
|
symbol.setHighVariable(this);
|
||||||
|
|
||||||
parser.end(el);
|
// decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
public class HighLocal extends HighVariable {
|
public class HighLocal extends HighVariable {
|
||||||
|
|
||||||
|
@ -53,15 +50,21 @@ public class HighLocal extends HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("high");
|
//int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
|
||||||
offset = -1;
|
offset = -1;
|
||||||
String attrString = el.getAttribute("offset");
|
for (;;) {
|
||||||
if (attrString != null) {
|
int attribId = decoder.getNextAttributeId();
|
||||||
offset = SpecXmlUtils.decodeInt(attrString);
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
restoreInstances(parser, el);
|
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||||
|
offset = (int) decoder.readUnsignedInteger();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodeInstances(decoder);
|
||||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||||
if (symbol == null) {
|
if (symbol == null) {
|
||||||
throw new PcodeXMLException("HighLocal is missing symbol");
|
throw new PcodeXMLException("HighLocal is missing symbol");
|
||||||
|
@ -75,7 +78,7 @@ public class HighLocal extends HighVariable {
|
||||||
pcaddr = symbol.getPCAddress();
|
pcaddr = symbol.getPCAddress();
|
||||||
symbol.setHighVariable(this);
|
symbol.setHighVariable(this);
|
||||||
|
|
||||||
parser.end(el);
|
//decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -66,25 +63,32 @@ public class HighOther extends HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("high");
|
// int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
long symref = 0;
|
||||||
offset = -1;
|
offset = -1;
|
||||||
String attrString = el.getAttribute("offset");
|
for (;;) {
|
||||||
restoreInstances(parser, el);
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||||
|
offset = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||||
|
symref = decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodeInstances(decoder);
|
||||||
name = "UNNAMED";
|
name = "UNNAMED";
|
||||||
pcaddr = function.getPCAddress(represent);
|
pcaddr = function.getPCAddress(represent);
|
||||||
if (symref != 0) {
|
if (symref != 0) {
|
||||||
offset = -1;
|
|
||||||
if (attrString != null) {
|
|
||||||
offset = SpecXmlUtils.decodeInt(attrString);
|
|
||||||
}
|
|
||||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||||
if (symbol != null && offset < 0) {
|
if (symbol != null && offset < 0) {
|
||||||
name = symbol.getName();
|
name = symbol.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.end(el);
|
// decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -55,8 +54,8 @@ public class HighParam extends HighLocal {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
super.restoreXml(parser);
|
super.decode(decoder);
|
||||||
HighSymbol sym = getSymbol();
|
HighSymbol sym = getSymbol();
|
||||||
slot = sym.getCategoryIndex();
|
slot = sym.getCategoryIndex();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -132,66 +131,66 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||||
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
|
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement start = parser.start("parammeasures");
|
int start = decoder.openElement(ElementId.ELEM_PARAMMEASURES);
|
||||||
functionname = start.getAttribute("name");
|
functionname = decoder.readString(AttributeId.ATTRIB_NAME);
|
||||||
if (!func.getName().equals(functionname)) {
|
if (!func.getName().equals(functionname)) {
|
||||||
throw new PcodeXMLException(
|
throw new PcodeXMLException(
|
||||||
"Function name mismatch: " + func.getName() + " + " + functionname);
|
"Function name mismatch: " + func.getName() + " + " + functionname);
|
||||||
}
|
}
|
||||||
while (!parser.peek().isEnd()) {
|
for (;;) {
|
||||||
XmlElement subel = parser.peek();
|
int subel = decoder.peekElement();
|
||||||
if (subel.getName().equals("addr")) {
|
if (subel == 0) {
|
||||||
subel = parser.start("addr");
|
break;
|
||||||
functionaddress = AddressXML.readXML(subel, getAddressFactory());
|
}
|
||||||
parser.end(subel);
|
if (subel == ElementId.ELEM_ADDR.getId()) {
|
||||||
|
functionaddress = AddressXML.decode(decoder);
|
||||||
functionaddress =
|
functionaddress =
|
||||||
func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress);
|
func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress);
|
||||||
if (!func.getEntryPoint().equals(functionaddress)) {
|
if (!func.getEntryPoint().equals(functionaddress)) {
|
||||||
throw new PcodeXMLException("Mismatched address in function tag");
|
throw new PcodeXMLException("Mismatched address in function tag");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("proto")) {
|
else if (subel == ElementId.ELEM_PROTO.getId()) {
|
||||||
subel = parser.start("proto");
|
decoder.openElement();
|
||||||
modelname = subel.getAttribute("model");
|
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
|
||||||
String val = subel.getAttribute("extrapop");
|
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
|
||||||
if (val.equals("unknown")) {
|
if (val.equals("unknown")) {
|
||||||
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
protoextrapop = SpecXmlUtils.decodeInt(val);
|
protoextrapop = SpecXmlUtils.decodeInt(val);
|
||||||
}
|
}
|
||||||
parser.end(subel);
|
decoder.closeElement(subel);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("input")) {
|
else if (subel == ElementId.ELEM_INPUT.getId()) {
|
||||||
parseParamMeasureXML(parser, inputlist, "input");
|
decodeParamMeasure(decoder, inputlist);
|
||||||
}
|
}
|
||||||
else if (subel.getName().equals("output")) {
|
else if (subel == ElementId.ELEM_OUTPUT.getId()) {
|
||||||
parseParamMeasureXML(parser, outputlist, "output");
|
decodeParamMeasure(decoder, outputlist);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new PcodeXMLException("Unknown tag in parammeasures: " + subel.getName());
|
throw new PcodeXMLException("Unknown tag in parammeasures");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(start);
|
decoder.closeElement(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read in the inputs or outputs list for this function from an XML rep
|
* Decode the inputs or outputs list for this function from a stream.
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @param pmlist is populated with the resulting list
|
* @param pmlist is populated with the resulting list
|
||||||
* @param tag is the name of the tag
|
* @throws PcodeXMLException for invalid encodings
|
||||||
* @throws PcodeXMLException for improperly formed XML
|
|
||||||
*/
|
*/
|
||||||
private void parseParamMeasureXML(XmlPullParser parser, List<ParamMeasure> pmlist, String tag)
|
private void decodeParamMeasure(Decoder decoder, List<ParamMeasure> pmlist)
|
||||||
throws PcodeXMLException {
|
throws PcodeXMLException {
|
||||||
XmlElement el = parser.start(tag);
|
int el = decoder.openElement();
|
||||||
ParamMeasure pm = new ParamMeasure();
|
ParamMeasure pm = new ParamMeasure();
|
||||||
pm.readXml(parser, this);
|
pm.decode(decoder, this);
|
||||||
if (!pm.isEmpty()) {
|
if (!pm.isEmpty()) {
|
||||||
pmlist.add(pm);
|
pmlist.add(pm);
|
||||||
}
|
}
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
||||||
|
@ -214,29 +213,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and XML SAX parse tree from an input XML string
|
|
||||||
*
|
|
||||||
* TODO: this probably doesn't belong here.
|
|
||||||
*
|
|
||||||
* @param xml string to parse
|
|
||||||
* @param handler is the error handler
|
|
||||||
* @return an XML tree element
|
|
||||||
*
|
|
||||||
* @throws PcodeXMLException for improper XML
|
|
||||||
*/
|
|
||||||
static public XmlPullParser stringTree(String xml, ErrorHandler handler)
|
|
||||||
throws PcodeXMLException {
|
|
||||||
try {
|
|
||||||
XmlPullParser parser =
|
|
||||||
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update any parameters for this Function from parameters defined in this map.
|
* Update any parameters for this Function from parameters defined in this map.
|
||||||
*
|
*
|
||||||
|
@ -244,7 +220,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||||
* @param srctype function signature source
|
* @param srctype function signature source
|
||||||
*/
|
*/
|
||||||
public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) {
|
public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) {
|
||||||
PcodeDataTypeManager dtManage = getDataTypeManager();
|
|
||||||
try {
|
try {
|
||||||
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
|
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
|
||||||
int best_index = 0;
|
int best_index = 0;
|
||||||
|
@ -285,7 +260,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||||
* @param srctype function signature source
|
* @param srctype function signature source
|
||||||
*/
|
*/
|
||||||
public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) {
|
public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) {
|
||||||
PcodeDataTypeManager dtManage = getDataTypeManager();
|
|
||||||
try {
|
try {
|
||||||
List<Variable> params = new ArrayList<>();
|
List<Variable> params = new ArrayList<>();
|
||||||
for (ParamMeasure pm : inputlist) {
|
for (ParamMeasure pm : inputlist) {
|
||||||
|
|
|
@ -23,8 +23,6 @@ import ghidra.program.model.symbol.Namespace;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type
|
* A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type
|
||||||
|
@ -405,69 +403,74 @@ public class HighSymbol {
|
||||||
buf.append("</symbol>\n");
|
buf.append("</symbol>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void restoreXMLHeader(XmlElement symel) throws PcodeXMLException {
|
protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||||
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
|
name = null;
|
||||||
if (id == 0) {
|
id = 0;
|
||||||
throw new PcodeXMLException("missing unique symbol id");
|
|
||||||
}
|
|
||||||
typelock = false;
|
typelock = false;
|
||||||
String typelockstr = symel.getAttribute("typelock");
|
|
||||||
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) {
|
|
||||||
typelock = true;
|
|
||||||
}
|
|
||||||
namelock = false;
|
namelock = false;
|
||||||
String namelockstr = symel.getAttribute("namelock");
|
|
||||||
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
|
|
||||||
namelock = true;
|
|
||||||
}
|
|
||||||
isThis = false;
|
isThis = false;
|
||||||
String thisstring = symel.getAttribute("thisptr");
|
|
||||||
if ((thisstring != null) && (SpecXmlUtils.decodeBoolean(thisstring))) {
|
|
||||||
isThis = true;
|
|
||||||
}
|
|
||||||
isHidden = false;
|
isHidden = false;
|
||||||
String hiddenstring = symel.getAttribute("hiddenretparm");
|
|
||||||
if ((hiddenstring != null) && (SpecXmlUtils.decodeBoolean(hiddenstring))) {
|
|
||||||
isHidden = true;
|
|
||||||
}
|
|
||||||
// isolate = false;
|
|
||||||
// String isolatestr = symel.getAttribute("merge");
|
|
||||||
// if ((isolatestr != null) && !SpecXmlUtils.decodeBoolean(isolatestr)) {
|
|
||||||
// isolate = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
name = symel.getAttribute("name");
|
|
||||||
categoryIndex = -1;
|
categoryIndex = -1;
|
||||||
category = -1;
|
category = -1;
|
||||||
if (symel.hasAttribute("cat")) {
|
|
||||||
category = SpecXmlUtils.decodeInt(symel.getAttribute("cat"));
|
for (;;) {
|
||||||
if (category == 0) {
|
int attribId = decoder.getNextAttributeId();
|
||||||
categoryIndex = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||||
|
id = decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
|
||||||
|
typelock = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_NAMELOCK.getId()) {
|
||||||
|
namelock = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_THISPTR.getId()) {
|
||||||
|
isThis = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_HIDDENRETPARM.getId()) {
|
||||||
|
isHidden = decoder.readBool();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_NAME.getId()) {
|
||||||
|
name = decoder.readString();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_CAT.getId()) {
|
||||||
|
category = (int) decoder.readSignedInteger();
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_INDEX.getId()) {
|
||||||
|
categoryIndex = (int) decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (id == 0) {
|
||||||
|
throw new PcodeXMLException("missing unique symbol id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore this symbol object and its associated mappings from an XML description
|
* Decode this symbol object and its associated mappings from the stream.
|
||||||
* in the given stream.
|
* @param decoder is the stream decoder
|
||||||
* @param parser is the given XML stream
|
* @throws PcodeXMLException for invalid encodings
|
||||||
* @throws PcodeXMLException if the XML description is invalid
|
|
||||||
*/
|
*/
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement symel = parser.start("symbol");
|
int symel = decoder.openElement(ElementId.ELEM_SYMBOL);
|
||||||
restoreXMLHeader(symel);
|
decodeHeader(decoder);
|
||||||
type = dtmanage.readXMLDataType(parser);
|
type = dtmanage.decodeDataType(decoder);
|
||||||
parser.end(symel);
|
decoder.closeElement(symel);
|
||||||
|
|
||||||
if (categoryIndex >= 0 && name.startsWith("$$undef")) {
|
if (categoryIndex >= 0 && name.startsWith("$$undef")) {
|
||||||
// use default parameter name
|
// use default parameter name
|
||||||
name = "param_" + Integer.toString(categoryIndex + 1);
|
name = "param_" + Integer.toString(categoryIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
XmlElement el = parser.peek();
|
int el = decoder.peekElement();
|
||||||
|
if (el == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
SymbolEntry entry;
|
SymbolEntry entry;
|
||||||
if (el.getName().equals("hash")) {
|
if (el == ElementId.ELEM_HASH.getId()) {
|
||||||
entry = new DynamicEntry(this);
|
entry = new DynamicEntry(this);
|
||||||
}
|
}
|
||||||
else if (this instanceof HighCodeSymbol) {
|
else if (this instanceof HighCodeSymbol) {
|
||||||
|
@ -476,7 +479,7 @@ public class HighSymbol {
|
||||||
else {
|
else {
|
||||||
entry = new MappedEntry(this);
|
entry = new MappedEntry(this);
|
||||||
}
|
}
|
||||||
entry.restoreXML(parser);
|
entry.decode(decoder);
|
||||||
addMapEntry(entry);
|
addMapEntry(entry);
|
||||||
}
|
}
|
||||||
if ((isThis || isHidden) && entryList != null) {
|
if ((isThis || isHidden) && entryList != null) {
|
||||||
|
@ -496,21 +499,21 @@ public class HighSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a full HighSymbol from the next <mapsym> tag in the given XML stream.
|
* Restore a full HighSymbol from the next <mapsym> element in the stream.
|
||||||
* This method acts as an XML based HighSymbol factory, instantiating the correct class
|
* This method acts as a HighSymbol factory, instantiating the correct class
|
||||||
* based on the particular tags.
|
* based on the particular elements.
|
||||||
* @param parser is the given XML stream
|
* @param decoder is the stream decoder
|
||||||
* @param isGlobal is true if this symbol is being read into a global scope
|
* @param isGlobal is true if this symbol is being read into a global scope
|
||||||
* @param high is the function model that will own the new symbol
|
* @param high is the function model that will own the new symbol
|
||||||
* @return the new symbol
|
* @return the new symbol
|
||||||
* @throws PcodeXMLException if the XML description is invalid
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public static HighSymbol restoreMapSymXML(XmlPullParser parser, boolean isGlobal,
|
public static HighSymbol decodeMapSym(Decoder decoder, boolean isGlobal, HighFunction high)
|
||||||
HighFunction high) throws PcodeXMLException {
|
throws PcodeXMLException {
|
||||||
HighSymbol res = null;
|
HighSymbol res = null;
|
||||||
parser.start("mapsym");
|
int mapel = decoder.openElement(ElementId.ELEM_MAPSYM);
|
||||||
XmlElement symel = parser.peek();
|
int symel = decoder.peekElement();
|
||||||
if (symel.getName().equals("equatesymbol")) {
|
if (symel == ElementId.ELEM_EQUATESYMBOL.getId()) {
|
||||||
res = new EquateSymbol(high);
|
res = new EquateSymbol(high);
|
||||||
}
|
}
|
||||||
else if (isGlobal) {
|
else if (isGlobal) {
|
||||||
|
@ -520,19 +523,23 @@ public class HighSymbol {
|
||||||
else {
|
else {
|
||||||
res = new HighSymbol(high);
|
res = new HighSymbol(high);
|
||||||
}
|
}
|
||||||
res.restoreXML(parser);
|
res.decode(decoder);
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
SymbolEntry entry;
|
SymbolEntry entry;
|
||||||
if (parser.peek().getName().equals("hash")) {
|
int subid = decoder.peekElement();
|
||||||
|
if (subid == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (subid == ElementId.ELEM_HASH.getId()) {
|
||||||
entry = new DynamicEntry(res);
|
entry = new DynamicEntry(res);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entry = new MappedEntry(res);
|
entry = new MappedEntry(res);
|
||||||
}
|
}
|
||||||
entry.restoreXML(parser);
|
entry.decode(decoder);
|
||||||
res.addMapEntry(entry);
|
res.addMapEntry(entry);
|
||||||
}
|
}
|
||||||
parser.end();
|
decoder.closeElement(mapel);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -58,7 +55,7 @@ public abstract class HighVariable {
|
||||||
protected void setHighOnInstances() {
|
protected void setHighOnInstances() {
|
||||||
for (Varnode instance : instances) {
|
for (Varnode instance : instances) {
|
||||||
if (instance instanceof VarnodeAST) {
|
if (instance instanceof VarnodeAST) {
|
||||||
((VarnodeAST)instance).setHigh(this);
|
((VarnodeAST) instance).setHigh(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,15 +138,13 @@ public abstract class HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the data-type and the Varnode instances of this HighVariable.
|
* Decode the data-type and the Varnode instances of this HighVariable.
|
||||||
* The "representative" Varnode is also populated.
|
* The "representative" Varnode is also populated.
|
||||||
* @param parser is the XML stream
|
* @param decoder is the stream decoder
|
||||||
* @param el is the root {@code <high>} tag
|
* @throws PcodeXMLException for invalid encodings
|
||||||
* @throws PcodeXMLException if the XML is not valid
|
|
||||||
*/
|
*/
|
||||||
protected void restoreInstances(XmlPullParser parser, XmlElement el)
|
protected void decodeInstances(Decoder decoder) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int repref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_REPREF);
|
||||||
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
|
|
||||||
Varnode rep = function.getRef(repref);
|
Varnode rep = function.getRef(repref);
|
||||||
if (rep == null) {
|
if (rep == null) {
|
||||||
throw new PcodeXMLException("Undefined varnode reference");
|
throw new PcodeXMLException("Undefined varnode reference");
|
||||||
|
@ -157,17 +152,15 @@ public abstract class HighVariable {
|
||||||
|
|
||||||
type = null;
|
type = null;
|
||||||
|
|
||||||
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
|
ArrayList<Varnode> vnlist = new ArrayList<>();
|
||||||
if (parser.peek().isStart()) {
|
type = function.getDataTypeManager().decodeDataType(decoder);
|
||||||
type = function.getDataTypeManager().readXMLDataType(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null) {
|
for (;;) {
|
||||||
throw new PcodeXMLException("Missing <type> for HighVariable");
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
Varnode vn = Varnode.decode(decoder, function);
|
||||||
while (parser.peek().isStart()) {
|
|
||||||
Varnode vn = Varnode.readXML(parser, function);
|
|
||||||
vnlist.add(vn);
|
vnlist.add(vn);
|
||||||
}
|
}
|
||||||
Varnode[] vnarray = new Varnode[vnlist.size()];
|
Varnode[] vnarray = new Varnode[vnlist.size()];
|
||||||
|
@ -193,9 +186,9 @@ public abstract class HighVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore this HighVariable from a {@code <high>} XML tag
|
* Decode this HighVariable from a {@code <high>} element in the stream
|
||||||
* @param parser is the XML stream
|
* @param decoder is the stream decoder
|
||||||
* @throws PcodeXMLException if the XML is not valid
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public abstract void restoreXml(XmlPullParser parser) throws PcodeXMLException;
|
public abstract void decode(Decoder decoder) throws PcodeXMLException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,6 @@ import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JumpTable found as part of the decompilation of a function
|
* JumpTable found as part of the decompilation of a function
|
||||||
|
@ -78,14 +75,12 @@ public class JumpTable {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory) {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("loadtable");
|
int el = decoder.openElement(ElementId.ELEM_LOADTABLE);
|
||||||
size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
num = SpecXmlUtils.decodeInt(el.getAttribute("num"));
|
num = (int) decoder.readSignedInteger(AttributeId.ATTRIB_NUM);
|
||||||
XmlElement subel = parser.start("addr");
|
addr = translateOverlayAddress(AddressXML.decode(decoder));
|
||||||
addr = translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
|
decoder.closeElement(el);
|
||||||
parser.end(subel);
|
|
||||||
parser.end(el);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,47 +154,51 @@ public class JumpTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a JumpTable object by parsing the XML elements
|
* Decode a JumpTable object from the stream.
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @param addrFactory is used to look-up address spaces
|
* @throws PcodeXMLException for invalid encodings
|
||||||
* @throws PcodeXMLException for improperly formed XML
|
|
||||||
*/
|
*/
|
||||||
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory)
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int el = decoder.openElement(ElementId.ELEM_JUMPTABLE);
|
||||||
XmlElement el = parser.start("jumptable");
|
if (decoder.peekElement() == 0) { // Empty jumptable
|
||||||
try {
|
decoder.closeElement(el);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ArrayList<Address> aTable = new ArrayList<>();
|
ArrayList<Address> aTable = new ArrayList<>();
|
||||||
ArrayList<Integer> lTable = new ArrayList<>();
|
ArrayList<Integer> lTable = new ArrayList<>();
|
||||||
ArrayList<LoadTable> ldTable = new ArrayList<>();
|
ArrayList<LoadTable> ldTable = new ArrayList<>();
|
||||||
|
|
||||||
if (!parser.peek().isStart()) { // Empty jumptable
|
Address switchAddr = translateOverlayAddress(AddressXML.decode(decoder));
|
||||||
return;
|
|
||||||
|
for (;;) {
|
||||||
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (subel == ElementId.ELEM_DEST.getId()) {
|
||||||
XmlElement addrel = parser.start("addr");
|
decoder.openElement();
|
||||||
Address switchAddr = translateOverlayAddress(AddressXML.readXML(addrel, addrFactory));
|
Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder));
|
||||||
parser.end(addrel);
|
|
||||||
|
|
||||||
while (parser.peek().isStart()) {
|
|
||||||
if (parser.peek().getName().equals("dest")) {
|
|
||||||
XmlElement subel = parser.start("dest");
|
|
||||||
Address caseAddr =
|
|
||||||
translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
|
|
||||||
aTable.add(caseAddr);
|
aTable.add(caseAddr);
|
||||||
String slabel = subel.getAttribute("label");
|
decoder.rewindAttributes();
|
||||||
if (slabel != null) {
|
for (;;) {
|
||||||
int label = SpecXmlUtils.decodeInt(slabel);
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attribId == AttributeId.ATTRIB_LABEL.getId()) {
|
||||||
|
int label = (int) decoder.readUnsignedInteger();
|
||||||
lTable.add(label);
|
lTable.add(label);
|
||||||
}
|
}
|
||||||
parser.end(subel);
|
|
||||||
}
|
}
|
||||||
else if (parser.peek().getName().equals("loadtable")) {
|
decoder.closeElement(subel);
|
||||||
|
}
|
||||||
|
else if (subel == ElementId.ELEM_LOADTABLE.getId()) {
|
||||||
LoadTable loadtable = new LoadTable();
|
LoadTable loadtable = new LoadTable();
|
||||||
loadtable.restoreXml(parser, addrFactory);
|
loadtable.decode(decoder);
|
||||||
ldTable.add(loadtable);
|
ldTable.add(loadtable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parser.discardSubTree();
|
decoder.skipElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,10 +209,7 @@ public class JumpTable {
|
||||||
lTable.toArray(labelTable);
|
lTable.toArray(labelTable);
|
||||||
loadTable = new LoadTable[ldTable.size()];
|
loadTable = new LoadTable[ldTable.size()];
|
||||||
ldTable.toArray(loadTable);
|
ldTable.toArray(loadTable);
|
||||||
}
|
decoder.closeElement(el);
|
||||||
finally {
|
|
||||||
parser.end(el);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildXml(StringBuilder buf) {
|
public void buildXml(StringBuilder buf) {
|
||||||
|
|
|
@ -24,8 +24,6 @@ import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container for local symbols within the decompiler's model of a function. It contains HighSymbol
|
* A container for local symbols within the decompiler's model of a function. It contains HighSymbol
|
||||||
|
@ -261,40 +259,40 @@ public class LocalSymbolMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a <mapsym> tag in XML
|
* Decode a <mapsym> element from the stream.
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @return the reconstructed HighSymbol
|
* @return the reconstructed HighSymbol
|
||||||
* @throws PcodeXMLException for problems sub tags
|
* @throws PcodeXMLException for problems sub tags
|
||||||
*/
|
*/
|
||||||
private HighSymbol parseSymbolXML(XmlPullParser parser) throws PcodeXMLException {
|
private HighSymbol decodeSymbol(Decoder decoder) throws PcodeXMLException {
|
||||||
HighSymbol res = HighSymbol.restoreMapSymXML(parser, false, func);
|
HighSymbol res = HighSymbol.decodeMapSym(decoder, false, func);
|
||||||
insertSymbol(res);
|
insertSymbol(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a local symbol scope in XML from the <localdb> tag.
|
* Decode a local symbol scope from the stream
|
||||||
*
|
*
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @throws PcodeXMLException for problems parsing individual tags
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public void parseScopeXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decodeScope(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("localdb");
|
int el = decoder.openElement(ElementId.ELEM_LOCALDB);
|
||||||
spacename = el.getAttribute("main");
|
spacename = decoder.readString(AttributeId.ATTRIB_MAIN);
|
||||||
XmlElement scopeel = parser.start("scope");
|
int scopeel = decoder.openElement(ElementId.ELEM_SCOPE);
|
||||||
|
|
||||||
parser.discardSubTree(); // This is the parent scope path
|
decoder.skipElement(); // This is the parent scope path
|
||||||
parser.discardSubTree(); // This is the address range
|
decoder.skipElement(); // This is the address range
|
||||||
|
|
||||||
addrMappedSymbols.clear(); // Clear out any old map
|
addrMappedSymbols.clear(); // Clear out any old map
|
||||||
symbolMap.clear(); // Clear out any old map
|
symbolMap.clear(); // Clear out any old map
|
||||||
|
|
||||||
XmlElement nextEl = parser.peek();
|
int nextEl = decoder.peekElement();
|
||||||
if (nextEl != null && nextEl.isStart() && "symbollist".equals(nextEl.getName())) {
|
if (nextEl == ElementId.ELEM_SYMBOLLIST.getId()) {
|
||||||
parseSymbolList(parser);
|
decodeSymbolList(decoder);
|
||||||
}
|
}
|
||||||
parser.end(scopeel);
|
decoder.closeElement(scopeel);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() {
|
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() {
|
||||||
|
@ -305,15 +303,15 @@ public class LocalSymbolMap {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add mapped symbols to this LocalVariableMap, by parsing the <symbollist> and <mapsym> tags.
|
* Add mapped symbols to this LocalVariableMap, by decoding the <symbollist> and <mapsym> elements
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @throws PcodeXMLException for problems parsing a tag
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public void parseSymbolList(XmlPullParser parser) throws PcodeXMLException {
|
public void decodeSymbolList(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("symbollist");
|
int el = decoder.openElement(ElementId.ELEM_SYMBOLLIST);
|
||||||
ArrayList<HighSymbol> parms = new ArrayList<>();
|
ArrayList<HighSymbol> parms = new ArrayList<>();
|
||||||
while (parser.peek().isStart()) {
|
while (decoder.peekElement() != 0) {
|
||||||
HighSymbol sym = parseSymbolXML(parser);
|
HighSymbol sym = decodeSymbol(decoder);
|
||||||
if (sym.isParameter()) {
|
if (sym.isParameter()) {
|
||||||
parms.add(sym);
|
parms.add(sym);
|
||||||
}
|
}
|
||||||
|
@ -321,7 +319,7 @@ public class LocalSymbolMap {
|
||||||
paramSymbols = new HighSymbol[parms.size()];
|
paramSymbols = new HighSymbol[parms.size()];
|
||||||
parms.toArray(paramSymbols);
|
parms.toArray(paramSymbols);
|
||||||
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
|
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A normal address based HighSymbol mapping with an associated Data object
|
* A normal address based HighSymbol mapping with an associated Data object
|
||||||
|
@ -52,8 +51,8 @@ public class MappedDataEntry extends MappedEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
super.restoreXML(parser);
|
super.decode(decoder);
|
||||||
data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress());
|
data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.data.AbstractFloatDataType;
|
import ghidra.program.model.data.AbstractFloatDataType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
|
@ -23,8 +24,6 @@ import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.model.symbol.Reference;
|
import ghidra.program.model.symbol.Reference;
|
||||||
import ghidra.program.model.symbol.ReferenceIterator;
|
import ghidra.program.model.symbol.ReferenceIterator;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A normal mapping of a HighSymbol to a particular Address, consuming a set number of bytes
|
* A normal mapping of a HighSymbol to a particular Address, consuming a set number of bytes
|
||||||
|
@ -53,33 +52,33 @@ public class MappedEntry extends SymbolEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
HighFunction function = symbol.function;
|
HighFunction function = symbol.function;
|
||||||
Program program = function.getFunction().getProgram();
|
Program program = function.getFunction().getProgram();
|
||||||
AddressFactory addrFactory = function.getAddressFactory();
|
|
||||||
|
|
||||||
XmlElement addrel = parser.start("addr");
|
int addrel = decoder.openElement(ElementId.ELEM_ADDR);
|
||||||
int sz = symbol.type.getLength();
|
int sz = symbol.type.getLength();
|
||||||
if (sz == 0) {
|
if (sz == 0) {
|
||||||
throw new PcodeXMLException(
|
throw new PcodeXMLException(
|
||||||
"Invalid symbol 0-sized data-type: " + symbol.type.getName());
|
"Invalid symbol 0-sized data-type: " + symbol.type.getName());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Address varAddr = AddressXML.readXML(addrel, addrFactory);
|
Address varAddr = AddressXML.decodeFromAttributes(decoder);
|
||||||
AddressSpace spc = varAddr.getAddressSpace();
|
AddressSpace spc = varAddr.getAddressSpace();
|
||||||
if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) {
|
if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) {
|
||||||
storage = new VariableStorage(program, varAddr, sz);
|
storage = new VariableStorage(program, varAddr, sz);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
storage = function.readXMLVarnodePieces(addrel, varAddr);
|
decoder.rewindAttributes();
|
||||||
|
storage = function.decodeVarnodePieces(decoder, varAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
throw new PcodeXMLException("Invalid storage: " + e.getMessage());
|
throw new PcodeXMLException("Invalid storage: " + e.getMessage());
|
||||||
}
|
}
|
||||||
parser.end(addrel);
|
decoder.closeElement(addrel);
|
||||||
|
|
||||||
parseRangeList(parser);
|
decodeRangeList(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ParamMeasure
|
* ParamMeasure
|
||||||
|
@ -43,24 +40,24 @@ public class ParamMeasure {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
if (vn == null)
|
if (vn == null) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a ParamMeasure object by parsing the XML elements
|
* Decode a ParamMeasure object from the stream.
|
||||||
* @param parser xml parser
|
* @param decoder is the stream decoder
|
||||||
* @param factory pcode factory
|
* @param factory pcode factory
|
||||||
* @throws PcodeXMLException if an error occurs when reading the xml.
|
* @throws PcodeXMLException for an invalid encoding
|
||||||
*/
|
*/
|
||||||
public void readXml(XmlPullParser parser, PcodeFactory factory) throws PcodeXMLException {
|
public void decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
|
||||||
vn = Varnode.readXML(parser, factory);
|
vn = Varnode.decode(decoder, factory);
|
||||||
dt = factory.getDataTypeManager().readXMLDataType(parser);
|
dt = factory.getDataTypeManager().decodeDataType(decoder);
|
||||||
XmlElement rankel = parser.start("rank");
|
int rankel = decoder.openElement(ElementId.ELEM_RANK);
|
||||||
String strVal = rankel.getAttribute("val");
|
rank = (int) decoder.readSignedInteger(AttributeId.ATTRIB_VAL);
|
||||||
rank = SpecXmlUtils.decodeInt(strVal);
|
decoder.closeElement(rankel);
|
||||||
parser.end(rankel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varnode getVarnode() {
|
public Varnode getVarnode() {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -160,32 +158,34 @@ public class PcodeBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore meta-data for a single edge
|
* Decode a single edge
|
||||||
* @param parser
|
* @param decoder is the stream decoder
|
||||||
* @param resolver used to recover PcodeBlock reference
|
* @param resolver used to recover PcodeBlock reference
|
||||||
* @throws PcodeXMLException
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("edge");
|
int el = decoder.openElement(ElementId.ELEM_EDGE);
|
||||||
label = 0; // Tag does not currently contain info about label
|
label = 0; // Tag does not currently contain info about label
|
||||||
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
|
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
|
||||||
point = resolver.findLevelBlock(endIndex);
|
point = resolver.findLevelBlock(endIndex);
|
||||||
if (point == null)
|
if (point == null) {
|
||||||
throw new PcodeXMLException("Bad serialized edge in block graph");
|
throw new PcodeXMLException("Bad serialized edge in block graph");
|
||||||
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
|
}
|
||||||
parser.end(el);
|
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXml(XmlPullParser parser, ArrayList<? extends PcodeBlock> blockList)
|
public void decode(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
|
||||||
throws PcodeXMLException {
|
throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("edge");
|
int el = decoder.openElement(ElementId.ELEM_EDGE);
|
||||||
label = 0; // Tag does not currently contain info about label
|
label = 0; // Tag does not currently contain info about label
|
||||||
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
|
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
|
||||||
point = blockList.get(endIndex);
|
point = blockList.get(endIndex);
|
||||||
if (point == null)
|
if (point == null) {
|
||||||
throw new PcodeXMLException("Bad serialized edge in block list");
|
throw new PcodeXMLException("Bad serialized edge in block list");
|
||||||
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
|
}
|
||||||
parser.end(el);
|
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,8 +198,8 @@ public class PcodeBlock {
|
||||||
index = -1;
|
index = -1;
|
||||||
blocktype = PLAIN;
|
blocktype = PLAIN;
|
||||||
parent = null;
|
parent = null;
|
||||||
intothis = new ArrayList<BlockEdge>();
|
intothis = new ArrayList<>();
|
||||||
outofthis = new ArrayList<BlockEdge>();
|
outofthis = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getType() {
|
public int getType() {
|
||||||
|
@ -240,38 +240,37 @@ public class PcodeBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the next input edge via XML
|
* Decode the next input edge from the stream
|
||||||
* @param parser
|
* @param decoder is the stream decoder
|
||||||
* @param resolver
|
* @param resolver is used to find PcodeBlocks
|
||||||
* @throws PcodeXMLException
|
* @throws PcodeXMLException for any invalid encoding
|
||||||
*/
|
*/
|
||||||
protected void restoreNextInEdge(XmlPullParser parser, BlockMap resolver)
|
protected void decodeNextInEdge(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
|
||||||
BlockEdge inEdge = new BlockEdge();
|
BlockEdge inEdge = new BlockEdge();
|
||||||
intothis.add(inEdge);
|
intothis.add(inEdge);
|
||||||
inEdge.restoreXml(parser, resolver);
|
inEdge.decode(decoder, resolver);
|
||||||
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||||
inEdge.point.outofthis.add(null);
|
inEdge.point.outofthis.add(null);
|
||||||
}
|
}
|
||||||
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
|
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
|
||||||
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the next input edge via XML. Resolve block indices via a blockList
|
* Decode the next input edge from the stream. Resolve block indices via a blockList
|
||||||
* @param parser
|
* @param decoder is the stream decoder
|
||||||
* @param blockList allows lookup of PcodeBlock via index
|
* @param blockList allows lookup of PcodeBlock via index
|
||||||
* @throws PcodeXMLException
|
* @throws PcodeXMLException for any invalid encoding
|
||||||
*/
|
*/
|
||||||
protected void restoreNextInEdge(XmlPullParser parser,
|
protected void decodeNextInEdge(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
|
||||||
ArrayList<? extends PcodeBlock> blockList) throws PcodeXMLException {
|
throws PcodeXMLException {
|
||||||
BlockEdge inEdge = new BlockEdge();
|
BlockEdge inEdge = new BlockEdge();
|
||||||
intothis.add(inEdge);
|
intothis.add(inEdge);
|
||||||
inEdge.restoreXml(parser, blockList);
|
inEdge.decode(decoder, blockList);
|
||||||
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||||
inEdge.point.outofthis.add(null);
|
inEdge.point.outofthis.add(null);
|
||||||
}
|
}
|
||||||
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
|
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
|
||||||
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,8 +348,8 @@ public class PcodeBlock {
|
||||||
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "index", index);
|
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "index", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||||
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -365,28 +364,29 @@ public class PcodeBlock {
|
||||||
|
|
||||||
public void saveXmlEdges(Writer writer) throws IOException {
|
public void saveXmlEdges(Writer writer) throws IOException {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
for (int i = 0; i < intothis.size(); ++i) {
|
for (BlockEdge element : intothis) {
|
||||||
intothis.get(i).saveXml(buf);
|
element.saveXml(buf);
|
||||||
}
|
}
|
||||||
writer.write(buf.toString());
|
writer.write(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the any additional information beyond header and edges from XML
|
* Restore the any additional information beyond header and edges from stream
|
||||||
* @param parser is the XML parser
|
* @param decoder is the stream decoder
|
||||||
* @param resolver is for looking up edge references
|
* @param resolver is for looking up edge references
|
||||||
* @throws PcodeXMLException for invalid XML descriptions
|
* @throws PcodeXMLException for invalid encoding
|
||||||
*/
|
*/
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
// No body to restore by default
|
// No body to restore by default
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXmlEdges(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
if (!parser.peek().getName().equals("edge")) {
|
int el = decoder.peekElement();
|
||||||
return;
|
if (el != ElementId.ELEM_EDGE.getId()) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
restoreNextInEdge(parser, resolver);
|
decodeNextInEdge(decoder, resolver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,11 +401,11 @@ public class PcodeBlock {
|
||||||
writer.write("</block>\n");
|
writer.write("</block>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("block");
|
int el = decoder.openElement(ElementId.ELEM_BLOCK);
|
||||||
restoreXmlHeader(el);
|
decodeHeader(decoder);
|
||||||
restoreXmlBody(parser, resolver);
|
decodeBody(decoder, resolver);
|
||||||
restoreXmlEdges(parser, resolver);
|
decodeEdges(decoder, resolver);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ import java.util.Iterator;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -35,7 +34,7 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
PcodeBlockBasic() {
|
PcodeBlockBasic() {
|
||||||
super();
|
super();
|
||||||
blocktype = PcodeBlock.BASIC;
|
blocktype = PcodeBlock.BASIC;
|
||||||
oplist = new ListLinked<PcodeOp>();
|
oplist = new ListLinked<>();
|
||||||
cover = new AddressSet();
|
cover = new AddressSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +63,9 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
* @param op is the new PcodeOp to insert
|
* @param op is the new PcodeOp to insert
|
||||||
*/
|
*/
|
||||||
protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) {
|
protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) {
|
||||||
PcodeOpAST opast = (PcodeOpAST)op;
|
PcodeOpAST opast = (PcodeOpAST) op;
|
||||||
opast.setParent(this);
|
opast.setParent(this);
|
||||||
Iterator<PcodeOp> newiter = oplist.insertBefore(iter,op);
|
Iterator<PcodeOp> newiter = oplist.insertBefore(iter, op);
|
||||||
opast.setBasicIter(newiter);
|
opast.setBasicIter(newiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +75,9 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
* @param op is the new PcodeOp to insert
|
* @param op is the new PcodeOp to insert
|
||||||
*/
|
*/
|
||||||
protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) {
|
protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) {
|
||||||
PcodeOpAST opast = (PcodeOpAST)op;
|
PcodeOpAST opast = (PcodeOpAST) op;
|
||||||
opast.setParent(this);
|
opast.setParent(this);
|
||||||
Iterator<PcodeOp> newiter = oplist.insertAfter(iter,opast);
|
Iterator<PcodeOp> newiter = oplist.insertAfter(iter, opast);
|
||||||
opast.setBasicIter(newiter);
|
opast.setBasicIter(newiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +86,7 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
* @param op is the PcodeOp to insert
|
* @param op is the PcodeOp to insert
|
||||||
*/
|
*/
|
||||||
protected void insertEnd(PcodeOp op) {
|
protected void insertEnd(PcodeOp op) {
|
||||||
PcodeOpAST opast = (PcodeOpAST)op;
|
PcodeOpAST opast = (PcodeOpAST) op;
|
||||||
opast.setParent(this);
|
opast.setParent(this);
|
||||||
Iterator<PcodeOp> newiter = oplist.add(opast);
|
Iterator<PcodeOp> newiter = oplist.add(opast);
|
||||||
opast.setBasicIter(newiter);
|
opast.setBasicIter(newiter);
|
||||||
|
@ -98,7 +97,7 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
* @param op is the PcodeOp to remove
|
* @param op is the PcodeOp to remove
|
||||||
*/
|
*/
|
||||||
protected void remove(PcodeOp op) {
|
protected void remove(PcodeOp op) {
|
||||||
PcodeOpAST opast = (PcodeOpAST)op;
|
PcodeOpAST opast = (PcodeOpAST) op;
|
||||||
opast.setParent(null);
|
opast.setParent(null);
|
||||||
oplist.remove(op.getBasicIter());
|
oplist.remove(op.getBasicIter());
|
||||||
}
|
}
|
||||||
|
@ -129,21 +128,23 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
AddressFactory addressFactory = resolver.getAddressFactory();
|
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
|
||||||
XmlElement rangelistel = parser.start("rangelist");
|
for (;;) {
|
||||||
while (parser.peek().isStart()) {
|
int rangeel = decoder.peekElement();
|
||||||
XmlElement rangeel = parser.start("range");
|
if (rangeel != ElementId.ELEM_RANGE.getId()) {
|
||||||
String spc = rangeel.getAttribute("space");
|
break;
|
||||||
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
|
}
|
||||||
AddressSpace addressSpace = addressFactory.getAddressSpace(spc);
|
decoder.openElement();
|
||||||
|
AddressSpace addressSpace = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||||
|
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
|
||||||
Address start = addressSpace.getAddress(offset);
|
Address start = addressSpace.getAddress(offset);
|
||||||
offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("last"));
|
offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_LAST);
|
||||||
Address stop = addressSpace.getAddress(offset);
|
Address stop = addressSpace.getAddress(offset);
|
||||||
cover.addRange(start, stop);
|
cover.addRange(start, stop);
|
||||||
parser.end(rangeel);
|
decoder.closeElement(rangeel);
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.end(rangelistel);
|
decoder.closeElement(rangelistel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ import ghidra.program.model.lang.CompilerSpec;
|
||||||
import ghidra.program.model.lang.DecompilerLanguage;
|
import ghidra.program.model.lang.DecompilerLanguage;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -123,13 +121,11 @@ public class PcodeDataTypeManager {
|
||||||
* a corresponding data-type exists, this data-type is returned. Otherwise the first
|
* a corresponding data-type exists, this data-type is returned. Otherwise the first
|
||||||
* built-in data-type with a matching name is returned
|
* built-in data-type with a matching name is returned
|
||||||
* @param nm name of data-type
|
* @param nm name of data-type
|
||||||
* @param idstr is an optional string containing a data-type id number
|
* @param id is an optional data-type id number
|
||||||
* @return the data-type object or null if no matching data-type exists
|
* @return the data-type object or null if no matching data-type exists
|
||||||
*/
|
*/
|
||||||
public DataType findBaseType(String nm, String idstr) {
|
public DataType findBaseType(String nm, long id) {
|
||||||
long id = 0;
|
if (id != 0) {
|
||||||
if (idstr != null) {
|
|
||||||
id = SpecXmlUtils.decodeLong(idstr);
|
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
DataType dt = progDataTypes.getDataType(id);
|
DataType dt = progDataTypes.getDataType(id);
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
|
@ -156,50 +152,62 @@ public class PcodeDataTypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the data type that corresponds to the given XML element.
|
* Decode a data-type from the stream
|
||||||
* @param parser the xml parser
|
* @param decoder is the stream decoder
|
||||||
* @return the read data type
|
* @return the decoded data-type object
|
||||||
* @throws PcodeXMLException if the data type could be resolved from the
|
* @throws PcodeXMLException for invalid encodings
|
||||||
* element
|
|
||||||
*/
|
*/
|
||||||
public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException {
|
public DataType decodeDataType(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("type", "void", "typeref", "def");
|
int el = decoder.openElement();
|
||||||
try {
|
if (el == ElementId.ELEM_VOID.getId()) {
|
||||||
if (el == null) {
|
decoder.closeElement(el);
|
||||||
throw new PcodeXMLException("Bad <type> tag");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (el.getName().equals("void")) {
|
|
||||||
return voidDt;
|
return voidDt;
|
||||||
}
|
}
|
||||||
if (el.getName().equals("typeref")) {
|
String name = "";
|
||||||
return findBaseType(el.getAttribute("name"), el.getAttribute("id"));
|
long id = 0;
|
||||||
|
for (;;) {
|
||||||
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (el.getName().equals("def")) {
|
if (attribId == AttributeId.ATTRIB_NAME.getId()) {
|
||||||
String nameStr = el.getAttribute("name");
|
name = decoder.readString();
|
||||||
String idStr = el.getAttribute("id");
|
|
||||||
parser.discardSubTree(); // Get rid of unused <typeref>
|
|
||||||
return findBaseType(nameStr, idStr);
|
|
||||||
}
|
}
|
||||||
String name = el.getAttribute("name");
|
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||||
|
id = decoder.readUnsignedInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (el == ElementId.ELEM_TYPEREF.getId()) {
|
||||||
|
decoder.closeElement(el);
|
||||||
|
return findBaseType(name, id);
|
||||||
|
}
|
||||||
|
if (el == ElementId.ELEM_DEF.getId()) {
|
||||||
|
decoder.closeElementSkipping(el);
|
||||||
|
return findBaseType(name, id);
|
||||||
|
}
|
||||||
|
if (el != ElementId.ELEM_TYPE.getId()) {
|
||||||
|
throw new PcodeXMLException("Expecting <type> element");
|
||||||
|
}
|
||||||
|
|
||||||
if (name.length() != 0) {
|
if (name.length() != 0) {
|
||||||
return findBaseType(name, el.getAttribute("id"));
|
decoder.closeElementSkipping(el);
|
||||||
|
return findBaseType(name, id);
|
||||||
}
|
}
|
||||||
String meta = el.getAttribute("metatype");
|
String meta = decoder.readString(AttributeId.ATTRIB_METATYPE);
|
||||||
DataType restype = null;
|
DataType restype = null;
|
||||||
if (meta.equals("ptr")) {
|
if (meta.equals("ptr")) {
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
if (parser.peek().isStart()) {
|
if (decoder.peekElement() != 0) {
|
||||||
DataType dt = readXMLDataType(parser);
|
DataType dt = decodeDataType(decoder);
|
||||||
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
|
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
|
||||||
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
|
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
|
||||||
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
|
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (meta.equals("array")) {
|
else if (meta.equals("array")) {
|
||||||
int arrsize = SpecXmlUtils.decodeInt(el.getAttribute("arraysize"));
|
int arrsize = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ARRAYSIZE);
|
||||||
if (parser.peek().isStart()) {
|
if (decoder.peekElement() != 0) {
|
||||||
DataType dt = readXMLDataType(parser);
|
DataType dt = decodeDataType(decoder);
|
||||||
if (dt == null || dt.getLength() == 0) {
|
if (dt == null || dt.getLength() == 0) {
|
||||||
dt = DataType.DEFAULT;
|
dt = DataType.DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -207,47 +215,44 @@ public class PcodeDataTypeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
|
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
|
||||||
parser.discardSubTree(); // get rid of unused "addr" element
|
decoder.closeElementSkipping(el); // get rid of unused "addr" element
|
||||||
return voidDt;
|
return voidDt;
|
||||||
}
|
}
|
||||||
else if (meta.equals("struct")) {
|
else if (meta.equals("struct")) {
|
||||||
// we now can reach here with the decompiler inventing structures, apparently
|
// We reach here if the decompiler invents a structure, apparently
|
||||||
// this is a band-aid so that we don't blow up
|
// this is a band-aid so that we don't blow up
|
||||||
// just make an undefined data type of the appropriate size
|
// just make an undefined data type of the appropriate size
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElementSkipping(el);
|
||||||
return Undefined.getUndefinedDataType(size);
|
return Undefined.getUndefinedDataType(size);
|
||||||
// OLD COMMENT:
|
|
||||||
// Structures should always be named so we should never reach here
|
|
||||||
// if all the structures are contained in ghidra. I should probably add the
|
|
||||||
// parsing here so the decompiler can pass new structures into ghidra
|
|
||||||
}
|
}
|
||||||
else if (meta.equals("int")) {
|
else if (meta.equals("int")) {
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(el);
|
||||||
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
|
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
|
||||||
}
|
}
|
||||||
else if (meta.equals("uint")) {
|
else if (meta.equals("uint")) {
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(el);
|
||||||
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
|
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
|
||||||
}
|
}
|
||||||
else if (meta.equals("float")) {
|
else if (meta.equals("float")) {
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(el);
|
||||||
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
|
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
|
||||||
}
|
}
|
||||||
else { // We typically reach here if the decompiler invents a new type
|
else { // We typically reach here if the decompiler invents a new type
|
||||||
// probably an unknown with a non-standard size
|
// probably an unknown with a non-standard size
|
||||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||||
|
decoder.closeElement(el);
|
||||||
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
|
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
|
||||||
}
|
}
|
||||||
if (restype == null) {
|
if (restype == null) {
|
||||||
throw new PcodeXMLException("Unable to resolve DataType");
|
throw new PcodeXMLException("Unable to resolve DataType");
|
||||||
}
|
}
|
||||||
|
decoder.closeElementSkipping(el);
|
||||||
return restype;
|
return restype;
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
parser.discardSubTree(el);
|
|
||||||
// parser.end(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the inner data-type being referred to by an offset from a relative/shifted pointer.
|
* Get the inner data-type being referred to by an offset from a relative/shifted pointer.
|
||||||
|
|
|
@ -23,7 +23,7 @@ import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
import ghidra.program.model.lang.UnknownInstructionException;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -49,24 +49,46 @@ public interface PcodeFactory {
|
||||||
*
|
*
|
||||||
* @return a new varnode
|
* @return a new varnode
|
||||||
*/
|
*/
|
||||||
public Varnode newVarnode(int sz,Address addr);
|
public Varnode newVarnode(int sz, Address addr);
|
||||||
|
|
||||||
|
public Varnode newVarnode(int sz, Address addr, int refId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a join address from "piece" attributes
|
||||||
|
*
|
||||||
|
* @param decoder is the stream decoder
|
||||||
|
* @param addr join address associated with pieces
|
||||||
|
*
|
||||||
|
* @return the decoded VariableStorage
|
||||||
|
* @throws PcodeXMLException for an improperly encoded stream
|
||||||
|
* @throws InvalidInputException if the pieces are not valid storage locations
|
||||||
|
*/
|
||||||
|
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
|
||||||
|
throws PcodeXMLException, InvalidInputException;
|
||||||
|
|
||||||
|
public Varnode createFromStorage(Address addr, VariableStorage storage, int logicalSize);
|
||||||
|
|
||||||
public Varnode newVarnode(int sz,Address addr,int refId);
|
|
||||||
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr) throws PcodeXMLException, InvalidInputException;
|
|
||||||
public Varnode createFromStorage(Address addr,VariableStorage storage, int logicalSize);
|
|
||||||
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
|
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
|
||||||
|
|
||||||
public Varnode getRef(int refid);
|
public Varnode getRef(int refid);
|
||||||
|
|
||||||
public PcodeOp getOpRef(int refid);
|
public PcodeOp getOpRef(int refid);
|
||||||
|
|
||||||
public HighSymbol getSymbol(long symbolId);
|
public HighSymbol getSymbol(long symbolId);
|
||||||
public Varnode setInput(Varnode vn,boolean val);
|
|
||||||
public void setAddrTied(Varnode vn,boolean val);
|
|
||||||
public void setPersistent(Varnode vn, boolean val);
|
|
||||||
public void setUnaffected(Varnode vn,boolean val);
|
|
||||||
public void setMergeGroup(Varnode vn,short val);
|
|
||||||
public void setDataType(Varnode vn,DataType type);
|
|
||||||
|
|
||||||
public PcodeOp newOp(SequenceNumber sq,int opc,ArrayList<Varnode> inputs,Varnode output)
|
public Varnode setInput(Varnode vn, boolean val);
|
||||||
|
|
||||||
|
public void setAddrTied(Varnode vn, boolean val);
|
||||||
|
|
||||||
|
public void setPersistent(Varnode vn, boolean val);
|
||||||
|
|
||||||
|
public void setUnaffected(Varnode vn, boolean val);
|
||||||
|
|
||||||
|
public void setMergeGroup(Varnode vn, short val);
|
||||||
|
|
||||||
|
public void setDataType(Varnode vn, DataType type);
|
||||||
|
|
||||||
|
public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output)
|
||||||
throws UnknownInstructionException;
|
throws UnknownInstructionException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ import java.util.*;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
import ghidra.program.model.lang.UnknownInstructionException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -418,7 +416,7 @@ public class PcodeOp {
|
||||||
output = vn;
|
output = vn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildXML(StringBuilder resBuf,AddressFactory addrFactory) {
|
public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) {
|
||||||
resBuf.append("<op");
|
resBuf.append("<op");
|
||||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode);
|
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode);
|
||||||
resBuf.append('>');
|
resBuf.append('>');
|
||||||
|
@ -446,29 +444,26 @@ public class PcodeOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read p-code from XML stream
|
* Decode p-code from a stream
|
||||||
*
|
*
|
||||||
* @param parser is the XML stream
|
* @param decoder is the stream decoder
|
||||||
* @param pfact factory used to create p-code correctly
|
* @param pfact factory used to create p-code correctly
|
||||||
*
|
*
|
||||||
* @return new PcodeOp
|
* @return new PcodeOp
|
||||||
* @throws PcodeXMLException if XML layout is incorrect
|
* @throws PcodeXMLException if encodings are invalid
|
||||||
*/
|
*/
|
||||||
public static PcodeOp readXML(XmlPullParser parser, PcodeFactory pfact)
|
public static PcodeOp decode(Decoder decoder, PcodeFactory pfact) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int el = decoder.openElement(ElementId.ELEM_OP);
|
||||||
XmlElement el = parser.start("op");
|
int opc = (int) decoder.readSignedInteger(AttributeId.ATTRIB_CODE);
|
||||||
int opc = SpecXmlUtils.decodeInt(el.getAttribute("code"));
|
SequenceNumber seqnum = SequenceNumber.decode(decoder);
|
||||||
if (!parser.peek().isStart()) {
|
Varnode output = Varnode.decode(decoder, pfact);
|
||||||
throw new PcodeXMLException("Missing <seqnum> in PcodeOp");
|
ArrayList<Varnode> inputlist = new ArrayList<>();
|
||||||
|
for (;;) {
|
||||||
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
SequenceNumber seqnum = SequenceNumber.readXML(parser, pfact.getAddressFactory());
|
Varnode vn = Varnode.decode(decoder, pfact);
|
||||||
if (!parser.peek().isStart()) {
|
|
||||||
throw new PcodeXMLException("Missing output in PcodeOp");
|
|
||||||
}
|
|
||||||
Varnode output = Varnode.readXML(parser, pfact);
|
|
||||||
ArrayList<Varnode> inputlist = new ArrayList<Varnode>();
|
|
||||||
while (parser.peek().isStart()) {
|
|
||||||
Varnode vn = Varnode.readXML(parser, pfact);
|
|
||||||
inputlist.add(vn);
|
inputlist.add(vn);
|
||||||
}
|
}
|
||||||
PcodeOp res;
|
PcodeOp res;
|
||||||
|
@ -478,7 +473,7 @@ public class PcodeOp {
|
||||||
catch (UnknownInstructionException e) {
|
catch (UnknownInstructionException e) {
|
||||||
throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e);
|
throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +517,7 @@ public class PcodeOp {
|
||||||
* Generate a lookup table that maps pcode mnemonic strings to pcode operation codes.
|
* Generate a lookup table that maps pcode mnemonic strings to pcode operation codes.
|
||||||
*/
|
*/
|
||||||
private static void generateOpcodeTable() {
|
private static void generateOpcodeTable() {
|
||||||
opcodeTable = new Hashtable<String, Integer>();
|
opcodeTable = new Hashtable<>();
|
||||||
for (int i = 0; i < PCODE_MAX; i++) {
|
for (int i = 0; i < PCODE_MAX; i++) {
|
||||||
opcodeTable.put(getMnemonic(i), i);
|
opcodeTable.put(getMnemonic(i), i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,6 @@ import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
import ghidra.program.model.lang.UnknownInstructionException;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -99,26 +96,23 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||||
return new Varnode(space.getAddress(offset), size);
|
return new Varnode(space.getAddress(offset), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an XML join address with "piece" attributes
|
|
||||||
*
|
|
||||||
* @param el SAX parse tree element
|
|
||||||
* @param addr join address associated with pieces
|
|
||||||
*
|
|
||||||
* @return the VariableStorage associated with xml
|
|
||||||
* @throws PcodeXMLException for improperly formatted XML
|
|
||||||
* @throws InvalidInputException if the pieces are not valid storage locations
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr)
|
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
|
||||||
throws PcodeXMLException, InvalidInputException {
|
throws PcodeXMLException, InvalidInputException {
|
||||||
ArrayList<Varnode> list = new ArrayList<>();
|
ArrayList<Varnode> list = new ArrayList<>();
|
||||||
int index = 1;
|
for (;;) {
|
||||||
String nextPiece = "piece" + index;
|
int attribId = decoder.getNextAttributeId();
|
||||||
while (el.hasAttribute(nextPiece)) {
|
if (attribId == 0) {
|
||||||
String pieceStr = el.getAttribute(nextPiece);
|
break;
|
||||||
list.add(getVarnodePiece(pieceStr, addrFactory));
|
}
|
||||||
nextPiece = "piece" + ++index;
|
else if (attribId >= AttributeId.ATTRIB_PIECE1.getId() &&
|
||||||
|
attribId <= AttributeId.ATTRIB_PIECE9.getId()) {
|
||||||
|
int index = attribId - AttributeId.ATTRIB_PIECE1.getId();
|
||||||
|
if (index != list.size()) {
|
||||||
|
throw new PcodeXMLException("\"piece\" attributes must be in order");
|
||||||
|
}
|
||||||
|
list.add(getVarnodePiece(decoder.readString(), decoder.getAddressFactory()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Varnode[] pieces = new Varnode[list.size()];
|
Varnode[] pieces = new Varnode[list.size()];
|
||||||
list.toArray(pieces);
|
list.toArray(pieces);
|
||||||
|
@ -526,23 +520,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException {
|
private void decodeVarnode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("varnodes");
|
int el = decoder.openElement(ElementId.ELEM_VARNODES);
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
Varnode.readXML(parser, this);
|
int subId = decoder.peekElement();
|
||||||
|
if (subId == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
parser.end(el);
|
Varnode.decode(decoder, this);
|
||||||
|
}
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBasicBlockXML(XmlPullParser parser, BlockMap resolver)
|
private void decodeBasicBlock(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int el = decoder.openElement(ElementId.ELEM_BLOCK);
|
||||||
XmlElement el = parser.start("block");
|
|
||||||
int order = 0;
|
int order = 0;
|
||||||
PcodeBlockBasic bl = new PcodeBlockBasic();
|
PcodeBlockBasic bl = new PcodeBlockBasic();
|
||||||
bl.restoreXmlHeader(el);
|
bl.decodeHeader(decoder);
|
||||||
bl.restoreXmlBody(parser, resolver);
|
bl.decodeBody(decoder, resolver);
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
PcodeOp op = PcodeOp.readXML(parser, this);
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PcodeOp op = PcodeOp.decode(decoder, this);
|
||||||
op.setOrder(order);
|
op.setOrder(order);
|
||||||
order += 1;
|
order += 1;
|
||||||
bl.insertEnd(op);
|
bl.insertEnd(op);
|
||||||
|
@ -552,37 +553,44 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||||
bblocks.add(null);
|
bblocks.add(null);
|
||||||
}
|
}
|
||||||
bblocks.set(index, bl);
|
bblocks.set(index, bl);
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBlockEdgeXML(XmlPullParser parser) throws PcodeXMLException {
|
private void decodeBlockEdge(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("blockedge");
|
int el = decoder.openElement(ElementId.ELEM_BLOCKEDGE);
|
||||||
int blockInd = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
int blockInd = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||||
PcodeBlockBasic curBlock = bblocks.get(blockInd);
|
PcodeBlockBasic curBlock = bblocks.get(blockInd);
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
curBlock.restoreNextInEdge(parser, bblocks);
|
int subel = decoder.peekElement();
|
||||||
|
if (subel == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
parser.end(el);
|
curBlock.decodeNextInEdge(decoder, bblocks);
|
||||||
|
}
|
||||||
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("ast");
|
int el = decoder.openElement(ElementId.ELEM_AST);
|
||||||
if (!vbank.isEmpty()) {
|
if (!vbank.isEmpty()) {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
readVarnodeXML(parser);
|
decodeVarnode(decoder);
|
||||||
buildVarnodeRefs(); // Build the HashMap
|
buildVarnodeRefs(); // Build the HashMap
|
||||||
BlockMap blockMap = new BlockMap(addrFactory);
|
BlockMap blockMap = new BlockMap(addrFactory);
|
||||||
while (parser.peek().isStart()) {
|
for (;;) {
|
||||||
XmlElement subel = parser.peek();
|
int subel = decoder.peekElement();
|
||||||
if (subel.getName().equals("block")) {
|
if (subel == 0) {
|
||||||
readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps
|
break;
|
||||||
|
}
|
||||||
|
else if (subel == ElementId.ELEM_BLOCK.getId()) {
|
||||||
|
decodeBasicBlock(decoder, blockMap); // Read a basic block and all its PcodeOps
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
readBlockEdgeXML(parser);
|
decodeBlockEdge(decoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.xml.*;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.xml.*;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -99,19 +99,28 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof SequenceNumber)) return false;
|
if (!(o instanceof SequenceNumber)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
SequenceNumber sq = (SequenceNumber) o;
|
SequenceNumber sq = (SequenceNumber) o;
|
||||||
return (pc.equals(sq.pc)&&(uniq==sq.uniq));
|
return (pc.equals(sq.pc) && (uniq == sq.uniq));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int compareTo(SequenceNumber sq) {
|
public int compareTo(SequenceNumber sq) {
|
||||||
int val = pc.compareTo(sq.pc);
|
int val = pc.compareTo(sq.pc);
|
||||||
if (val != 0) return val;
|
if (val != 0) {
|
||||||
if (uniq < sq.uniq) return -1;
|
return val;
|
||||||
if (sq.uniq < uniq) return 1;
|
}
|
||||||
|
if (uniq < sq.uniq) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sq.uniq < uniq) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,33 +133,37 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||||
AddressSpace space = pc.getAddressSpace();
|
AddressSpace space = pc.getAddressSpace();
|
||||||
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName());
|
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName());
|
||||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset());
|
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset());
|
||||||
if (uniq != -1)
|
if (uniq != -1) {
|
||||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq);
|
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq);
|
||||||
|
}
|
||||||
resBuf.append("/>");
|
resBuf.append("/>");
|
||||||
return resBuf;
|
return resBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Sequence number from XML SAX tree element.
|
* Decode a new Sequence number from the stream
|
||||||
*
|
*
|
||||||
* @param parser the xml parser
|
* @param decoder is the stream decoder
|
||||||
* @param factory pcode factory used to create new pcode
|
|
||||||
*
|
*
|
||||||
* @return new sequence number
|
* @return new sequence number
|
||||||
|
* @throws PcodeXMLException for an invalid encoding
|
||||||
*/
|
*/
|
||||||
public static SequenceNumber readXML(XmlPullParser parser,AddressFactory factory) {
|
public static SequenceNumber decode(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement el = parser.start("seqnum");
|
int el = decoder.openElement(ElementId.ELEM_SEQNUM);
|
||||||
String attrstring = el.getAttribute("uniq");
|
int uniq = -1;
|
||||||
int uniq;
|
for (;;) {
|
||||||
if (attrstring != null)
|
int attribId = decoder.getNextAttributeId();
|
||||||
uniq = SpecXmlUtils.decodeInt(attrstring);
|
if (attribId == 0) {
|
||||||
else
|
break;
|
||||||
uniq = -1; // Should fill in with something from factory
|
}
|
||||||
String space = el.getAttribute("space");
|
else if (attribId == AttributeId.ATTRIB_UNIQ.getId()) {
|
||||||
AddressSpace spc = factory.getAddressSpace(space);
|
uniq = (int) decoder.readUnsignedInteger();
|
||||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
|
}
|
||||||
parser.end(el);
|
}
|
||||||
return new SequenceNumber(spc.getAddress(offset),uniq);
|
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||||
|
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFFSET);
|
||||||
|
decoder.closeElement(el);
|
||||||
|
return new SequenceNumber(spc.getAddress(offset), uniq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -158,15 +171,8 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return ("("
|
return ("(" + pc.getAddressSpace().getName() + ", 0x" + Long.toHexString(pc.getOffset()) +
|
||||||
+ pc.getAddressSpace().getName()
|
", " + uniq + ", " + order + ")");
|
||||||
+ ", 0x"
|
|
||||||
+ Long.toHexString(pc.getOffset())
|
|
||||||
+ ", "
|
|
||||||
+ uniq
|
|
||||||
+ ", "
|
|
||||||
+ order
|
|
||||||
+ ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|
|
@ -19,8 +19,6 @@ import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping from a HighSymbol object to the storage that holds the symbol's value.
|
* A mapping from a HighSymbol object to the storage that holds the symbol's value.
|
||||||
|
@ -39,12 +37,11 @@ public abstract class SymbolEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore this entry from the given XML stream. Typically more than one tag is consumed
|
* Decode this entry from the stream. Typically more than one element is consumed.
|
||||||
* @param parser is the given XML stream
|
* @param decoder is the stream decoder
|
||||||
* @throws PcodeXMLException if the XML is invalid
|
* @throws PcodeXMLException for invalid encodings
|
||||||
*/
|
*/
|
||||||
public abstract void restoreXML(XmlPullParser parser)
|
public abstract void decode(Decoder decoder) throws PcodeXMLException;
|
||||||
throws PcodeXMLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save this entry as (a set of) XML tags to the given stream
|
* Save this entry as (a set of) XML tags to the given stream
|
||||||
|
@ -83,21 +80,22 @@ public abstract class SymbolEntry {
|
||||||
return pcaddr;
|
return pcaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseRangeList(XmlPullParser parser) {
|
protected void decodeRangeList(Decoder decoder) throws PcodeXMLException {
|
||||||
XmlElement rangelistel = parser.start("rangelist");
|
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
|
||||||
if (parser.peek().isStart()) {
|
if (decoder.peekElement() != 0) {
|
||||||
// we only use this to establish first-use
|
// we only use this to establish first-use
|
||||||
XmlElement rangeel = parser.start("range");
|
int rangeel = decoder.openElement(ElementId.ELEM_RANGE);
|
||||||
String spc = rangeel.getAttribute("space");
|
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||||
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
|
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
|
||||||
pcaddr = symbol.function.getAddressFactory().getAddressSpace(spc).getAddress(offset);
|
pcaddr = spc.getAddress(offset);
|
||||||
pcaddr =
|
pcaddr = symbol.function.getFunction()
|
||||||
symbol.function.getFunction().getEntryPoint().getAddressSpace().getOverlayAddress(
|
.getEntryPoint()
|
||||||
pcaddr);
|
.getAddressSpace()
|
||||||
parser.end(rangeel);
|
.getOverlayAddress(pcaddr);
|
||||||
|
decoder.closeElement(rangeel);
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.end(rangelistel);
|
decoder.closeElement(rangelistel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildRangelistXML(StringBuilder res) {
|
protected void buildRangelistXML(StringBuilder res) {
|
||||||
|
|
|
@ -21,9 +21,6 @@ import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.xml.SpecXmlUtils;
|
|
||||||
import ghidra.xml.XmlElement;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -322,42 +319,48 @@ public class Varnode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a Varnode from an XML stream
|
* Decode a Varnode from a stream
|
||||||
*
|
*
|
||||||
* @param parser the parser
|
* @param decoder is the stream decoder
|
||||||
* @param factory pcode factory used to create valid pcode
|
* @param factory pcode factory used to create valid pcode
|
||||||
* @return new varnode element based on info in the XML.
|
* @return the new Varnode
|
||||||
* @throws PcodeXMLException if XML is improperly formed
|
* @throws PcodeXMLException if XML is improperly formed
|
||||||
*/
|
*/
|
||||||
public static Varnode readXML(XmlPullParser parser, PcodeFactory factory)
|
public static Varnode decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
|
||||||
throws PcodeXMLException {
|
int el = decoder.peekElement();
|
||||||
XmlElement el = parser.start();
|
if (el == ElementId.ELEM_VOID.getId()) {
|
||||||
try {
|
decoder.openElement();
|
||||||
if (el.getName().equals("void")) {
|
decoder.closeElement(el);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Varnode vn;
|
else if (el == ElementId.ELEM_SPACEID.getId() || el == ElementId.ELEM_IOP.getId()) {
|
||||||
String attrstring = el.getAttribute("ref");
|
Address addr = AddressXML.decode(decoder);
|
||||||
|
return factory.newVarnode(4, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
el = decoder.openElement();
|
||||||
int ref = -1;
|
int ref = -1;
|
||||||
if (attrstring != null) {
|
int sz = 4;
|
||||||
ref = SpecXmlUtils.decodeInt(attrstring); // If we have a reference
|
for (;;) {
|
||||||
vn = factory.getRef(ref); // The varnode may already exist
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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
|
||||||
if (vn != null) {
|
if (vn != null) {
|
||||||
|
decoder.closeElement(el);
|
||||||
return vn;
|
return vn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Address addr = AddressXML.readXML(el, factory.getAddressFactory());
|
else if (attribId == AttributeId.ATTRIB_SIZE.getId()) {
|
||||||
if (addr == null) {
|
sz = (int) decoder.readSignedInteger();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
int sz;
|
|
||||||
attrstring = el.getAttribute("size");
|
|
||||||
if (attrstring != null) {
|
|
||||||
sz = SpecXmlUtils.decodeInt(attrstring);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sz = 4;
|
|
||||||
}
|
}
|
||||||
|
decoder.rewindAttributes();
|
||||||
|
Varnode vn;
|
||||||
|
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||||
if (ref != -1) {
|
if (ref != -1) {
|
||||||
vn = factory.newVarnode(sz, addr, ref);
|
vn = factory.newVarnode(sz, addr, ref);
|
||||||
}
|
}
|
||||||
|
@ -366,40 +369,48 @@ public class Varnode {
|
||||||
}
|
}
|
||||||
AddressSpace spc = addr.getAddressSpace();
|
AddressSpace spc = addr.getAddressSpace();
|
||||||
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
|
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
|
||||||
|
decoder.rewindAttributes();
|
||||||
try {
|
try {
|
||||||
factory.readXMLVarnodePieces(el, addr);
|
factory.decodeVarnodePieces(decoder, addr);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
|
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attrstring = el.getAttribute("grp");
|
decoder.rewindAttributes();
|
||||||
if (attrstring != null) {
|
for (;;) {
|
||||||
short val = (short) SpecXmlUtils.decodeInt(attrstring);
|
int attribId = decoder.getNextAttributeId();
|
||||||
|
if (attribId == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (attribId == AttributeId.ATTRIB_GRP.getId()) {
|
||||||
|
short val = (short) decoder.readSignedInteger();
|
||||||
factory.setMergeGroup(vn, val);
|
factory.setMergeGroup(vn, val);
|
||||||
}
|
}
|
||||||
attrstring = el.getAttribute("persists");
|
else if (attribId == AttributeId.ATTRIB_PERSISTS.getId()) {
|
||||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
if (decoder.readBool()) {
|
||||||
factory.setPersistent(vn, true);
|
factory.setPersistent(vn, true);
|
||||||
}
|
}
|
||||||
attrstring = el.getAttribute("addrtied");
|
}
|
||||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
else if (attribId == AttributeId.ATTRIB_ADDRTIED.getId()) {
|
||||||
|
if (decoder.readBool()) {
|
||||||
factory.setAddrTied(vn, true);
|
factory.setAddrTied(vn, true);
|
||||||
}
|
}
|
||||||
attrstring = el.getAttribute("unaff");
|
}
|
||||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
else if (attribId == AttributeId.ATTRIB_UNAFF.getId()) {
|
||||||
|
if (decoder.readBool()) {
|
||||||
factory.setUnaffected(vn, true);
|
factory.setUnaffected(vn, true);
|
||||||
}
|
}
|
||||||
attrstring = el.getAttribute("input");
|
}
|
||||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
else if (attribId == AttributeId.ATTRIB_INPUT.getId()) {
|
||||||
|
if (decoder.readBool()) {
|
||||||
vn = factory.setInput(vn, true);
|
vn = factory.setInput(vn, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoder.closeElement(sz);
|
||||||
return vn;
|
return vn;
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
parser.end(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trim a varnode in a constant space to the correct starting offset.
|
* Trim a varnode in a constant space to the correct starting offset.
|
||||||
|
|
|
@ -0,0 +1,289 @@
|
||||||
|
/* ###
|
||||||
|
* 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.InputStream;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.xml.sax.*;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.AddressFactory;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
import ghidra.xml.*;
|
||||||
|
|
||||||
|
public class XmlDecode implements Decoder {
|
||||||
|
|
||||||
|
private XmlPullParser parser;
|
||||||
|
private XmlElement currentEl;
|
||||||
|
private Iterator<Map.Entry<String, String>> attribIterator;
|
||||||
|
private String attribValue;
|
||||||
|
private AddressFactory spcManager;
|
||||||
|
|
||||||
|
public XmlDecode(AddressFactory factory) {
|
||||||
|
parser = null;
|
||||||
|
currentEl = null;
|
||||||
|
attribIterator = null;
|
||||||
|
attribValue = null;
|
||||||
|
spcManager = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressFactory getAddressFactory() {
|
||||||
|
return spcManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
parser = null;
|
||||||
|
currentEl = null;
|
||||||
|
attribIterator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ingestStream(InputStream stream, String source) throws PcodeXMLException {
|
||||||
|
ErrorHandler handler = new ErrorHandler() {
|
||||||
|
@Override
|
||||||
|
public void error(SAXParseException exception) throws SAXException {
|
||||||
|
Msg.error(this, "Error parsing " + source, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fatalError(SAXParseException exception) throws SAXException {
|
||||||
|
Msg.error(this, "Fatal error parsing " + source, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(SAXParseException exception) throws SAXException {
|
||||||
|
Msg.warn(this, "Warning parsing " + source, exception);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
parser = XmlPullParserFactory.create(stream, source, handler, false);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int peekElement() {
|
||||||
|
XmlElement el = parser.peek();
|
||||||
|
if (!el.isStart()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ElementId.find(el.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int openElement() {
|
||||||
|
XmlElement el = parser.softStart();
|
||||||
|
if (el == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
currentEl = el;
|
||||||
|
attribIterator = null;
|
||||||
|
return ElementId.find(currentEl.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int openElement(ElementId elemId) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.softStart(elemId.getName());
|
||||||
|
if (el == null) {
|
||||||
|
throw new PcodeXMLException("Expecting element <" + elemId.getName() + '>');
|
||||||
|
}
|
||||||
|
currentEl = el;
|
||||||
|
attribIterator = null;
|
||||||
|
return ElementId.find(currentEl.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeElement(int id) throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.next();
|
||||||
|
if (!el.isEnd()) {
|
||||||
|
throw new PcodeXMLException("Expecting end, but got start <" + el.getName() + '>');
|
||||||
|
}
|
||||||
|
currentEl = null;
|
||||||
|
// int elemId = ElementId.find(el.getName());
|
||||||
|
// if (elemId != id) {
|
||||||
|
// throw new PcodeXMLException("Unexpected end, <" + el.getName() + '>');
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeElementSkipping(int id) throws PcodeXMLException {
|
||||||
|
currentEl = null;
|
||||||
|
XmlElement el = parser.peek();
|
||||||
|
if (el == null) {
|
||||||
|
throw new PcodeXMLException("No more elements");
|
||||||
|
}
|
||||||
|
int level = el.getLevel();
|
||||||
|
if (el.isStart()) {
|
||||||
|
level -= 1;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
el = parser.next();
|
||||||
|
int curlevel = el.getLevel();
|
||||||
|
if (curlevel > level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (curlevel < level) {
|
||||||
|
throw new PcodeXMLException("Missing end element");
|
||||||
|
}
|
||||||
|
if (el.isEnd()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int elemId = ElementId.find(el.getName());
|
||||||
|
if (elemId != id) {
|
||||||
|
throw new PcodeXMLException("Unexpected element end: " + el.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextAttributeId() {
|
||||||
|
if (attribIterator == null) {
|
||||||
|
attribIterator = currentEl.getAttributeIterator();
|
||||||
|
}
|
||||||
|
if (!attribIterator.hasNext()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Map.Entry<String, String> entry = attribIterator.next();
|
||||||
|
attribValue = entry.getValue();
|
||||||
|
return AttributeId.find(entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rewindAttributes() {
|
||||||
|
attribIterator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readContent() throws PcodeXMLException {
|
||||||
|
XmlElement el = parser.peek();
|
||||||
|
if (el == null || !el.isEnd()) {
|
||||||
|
throw new PcodeXMLException("Cannot request ATTRIB_CONTENT here");
|
||||||
|
}
|
||||||
|
return el.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean readBool() throws PcodeXMLException {
|
||||||
|
return SpecXmlUtils.decodeBoolean(attribValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean readBool(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
String value;
|
||||||
|
if (attribId == AttributeId.ATTRIB_CONTENT) {
|
||||||
|
value = readContent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = currentEl.getAttribute(attribId.getName());
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
attribIterator = null;
|
||||||
|
return SpecXmlUtils.decodeBoolean(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readSignedInteger() throws PcodeXMLException {
|
||||||
|
return SpecXmlUtils.decodeLong(attribValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
String value;
|
||||||
|
if (attribId == AttributeId.ATTRIB_CONTENT) {
|
||||||
|
value = readContent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = currentEl.getAttribute(attribId.getName());
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
attribIterator = null;
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readUnsignedInteger() throws PcodeXMLException {
|
||||||
|
return SpecXmlUtils.decodeLong(attribValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
String value;
|
||||||
|
if (attribId == AttributeId.ATTRIB_CONTENT) {
|
||||||
|
value = readContent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = currentEl.getAttribute(attribId.getName());
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
attribIterator = null;
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readString() throws PcodeXMLException {
|
||||||
|
return attribValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readString(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
String value;
|
||||||
|
if (attribId == AttributeId.ATTRIB_CONTENT) {
|
||||||
|
value = readContent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = currentEl.getAttribute(attribId.getName());
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
attribIterator = null;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSpace readSpace() throws PcodeXMLException {
|
||||||
|
return spcManager.getAddressSpace(attribValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
String value;
|
||||||
|
if (attribId == AttributeId.ATTRIB_CONTENT) {
|
||||||
|
value = readContent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = currentEl.getAttribute(attribId.getName());
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
attribIterator = null;
|
||||||
|
return spcManager.getAddressSpace(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,398 @@
|
||||||
|
/* ###
|
||||||
|
* 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.InputStream;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.AddressFactory;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
|
import ghidra.util.xml.SpecXmlUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lightweight XML decoder.
|
||||||
|
* - Element and attribute identifiers must contain only letters or digits
|
||||||
|
* - No XML comments
|
||||||
|
* - No escape codes
|
||||||
|
* - No content (except white space)
|
||||||
|
*/
|
||||||
|
public class XmlDecodeLight implements Decoder {
|
||||||
|
|
||||||
|
private AddressFactory addressFactory;
|
||||||
|
private String raw;
|
||||||
|
private int currentPos;
|
||||||
|
private boolean startOpen;
|
||||||
|
private int attribStart;
|
||||||
|
private int currentElement;
|
||||||
|
|
||||||
|
public XmlDecodeLight(AddressFactory addrFactory) {
|
||||||
|
addressFactory = addrFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressFactory getAddressFactory() {
|
||||||
|
return addressFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
raw = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ingestString(String data) {
|
||||||
|
raw = data;
|
||||||
|
currentPos = 0;
|
||||||
|
startOpen = false;
|
||||||
|
attribStart = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scanWhiteSpace(int start) throws PcodeXMLException {
|
||||||
|
while (start < raw.length()) {
|
||||||
|
char tok = raw.charAt(start);
|
||||||
|
if (!Character.isWhitespace(tok)) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
throw new PcodeXMLException("Premature end of stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scanIdentifier(int start) throws PcodeXMLException {
|
||||||
|
while (start < raw.length()) {
|
||||||
|
char tok = raw.charAt(start);
|
||||||
|
if (!Character.isLetterOrDigit(tok)) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
throw new PcodeXMLException("Premature end of stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scanToEndOfStart(int start) throws PcodeXMLException {
|
||||||
|
int state = 0;
|
||||||
|
while (start < raw.length()) {
|
||||||
|
char tok = raw.charAt(start);
|
||||||
|
if (state == 0) {
|
||||||
|
if (tok == '/' || tok == '>') {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
if (tok == '\"') {
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == 1) {
|
||||||
|
if (tok == '\"') {
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
throw new PcodeXMLException("Premature end of stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String scanElement() throws PcodeXMLException {
|
||||||
|
int pos = currentPos;
|
||||||
|
if (startOpen) {
|
||||||
|
pos = scanToEndOfStart(pos);
|
||||||
|
if (raw.charAt(pos) == '>') {
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(pos);
|
||||||
|
if (raw.charAt(pos) != '<') {
|
||||||
|
throw new PcodeXMLException("Expecting start of element");
|
||||||
|
}
|
||||||
|
pos += 1;
|
||||||
|
if (pos < raw.length() && raw.charAt(pos) == '/') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(pos);
|
||||||
|
int endPos = scanIdentifier(pos);
|
||||||
|
if (pos == endPos) {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
currentPos = endPos;
|
||||||
|
startOpen = true;
|
||||||
|
return raw.substring(pos, endPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scanQuote() throws PcodeXMLException {
|
||||||
|
int pos = currentPos + 1;
|
||||||
|
while (pos < raw.length()) {
|
||||||
|
if (raw.charAt(pos) == '\"') {
|
||||||
|
return pos + 1;
|
||||||
|
}
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
throw new PcodeXMLException("Premature end of stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String scanAttribute() throws PcodeXMLException {
|
||||||
|
int pos = currentPos;
|
||||||
|
currentPos = scanQuote();
|
||||||
|
return raw.substring(pos + 1, currentPos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ingestStream(InputStream stream, String source) throws PcodeXMLException {
|
||||||
|
throw new PcodeXMLException("Unimplemented method");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int peekElement() {
|
||||||
|
int savePos = currentPos;
|
||||||
|
boolean saveStartOpen = startOpen;
|
||||||
|
String el;
|
||||||
|
try {
|
||||||
|
el = scanElement();
|
||||||
|
currentPos = savePos;
|
||||||
|
startOpen = saveStartOpen;
|
||||||
|
if (el == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PcodeXMLException e) {
|
||||||
|
currentPos = savePos;
|
||||||
|
startOpen = saveStartOpen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ElementId.find(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int openElement() {
|
||||||
|
String el;
|
||||||
|
try {
|
||||||
|
el = scanElement();
|
||||||
|
if (el == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PcodeXMLException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
attribStart = currentPos;
|
||||||
|
currentElement = ElementId.find(el);
|
||||||
|
return currentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int openElement(ElementId elemId) throws PcodeXMLException {
|
||||||
|
String el = scanElement();
|
||||||
|
if (el == null) {
|
||||||
|
throw new PcodeXMLException("Expecting start of " + elemId.getName());
|
||||||
|
}
|
||||||
|
attribStart = currentPos;
|
||||||
|
currentElement = ElementId.find(el);
|
||||||
|
if (currentElement != elemId.getId()) {
|
||||||
|
throw new PcodeXMLException("Expecting element " + elemId.getName());
|
||||||
|
}
|
||||||
|
return currentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeElement(int id) throws PcodeXMLException {
|
||||||
|
int pos = currentPos;
|
||||||
|
if (startOpen) {
|
||||||
|
pos = scanToEndOfStart(currentPos);
|
||||||
|
char tok = raw.charAt(pos);
|
||||||
|
if (tok == '/') {
|
||||||
|
pos += 1;
|
||||||
|
if (pos >= raw.length()) {
|
||||||
|
throw new PcodeXMLException("Premature end of stream");
|
||||||
|
}
|
||||||
|
if (raw.charAt(pos) != '>') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
currentPos = pos + 1;
|
||||||
|
if (id != currentElement) {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
startOpen = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tok != '>') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
startOpen = false;
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(pos);
|
||||||
|
if (raw.charAt(pos) != '<') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
pos += 1;
|
||||||
|
if (pos >= raw.length() || raw.charAt(pos) != '/') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(pos + 1);
|
||||||
|
int endpos = scanIdentifier(pos);
|
||||||
|
String ident = raw.substring(pos, endpos);
|
||||||
|
if (id != ElementId.find(ident)) {
|
||||||
|
throw new PcodeXMLException("Expecting end token");
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(endpos);
|
||||||
|
if (raw.charAt(pos) != '>') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
currentPos = pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeElementSkipping(int id) throws PcodeXMLException {
|
||||||
|
throw new PcodeXMLException("closeElementSkipping unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextAttributeId() {
|
||||||
|
if (!startOpen) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int pos = scanWhiteSpace(currentPos);
|
||||||
|
char tok = raw.charAt(pos);
|
||||||
|
if (tok == '\"') {
|
||||||
|
pos = scanQuote();
|
||||||
|
pos = scanWhiteSpace(pos);
|
||||||
|
tok = raw.charAt(pos);
|
||||||
|
}
|
||||||
|
if (tok == '>' || tok == '/') {
|
||||||
|
currentPos = pos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int endPos = scanIdentifier(pos);
|
||||||
|
if (pos == endPos) {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
String ident = raw.substring(pos, endPos);
|
||||||
|
pos = scanWhiteSpace(endPos);
|
||||||
|
if (raw.charAt(pos) != '=') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
pos = scanWhiteSpace(pos + 1);
|
||||||
|
if (raw.charAt(pos) != '\"') {
|
||||||
|
throw new PcodeXMLException("Parse error");
|
||||||
|
}
|
||||||
|
currentPos = pos;
|
||||||
|
return AttributeId.find(ident);
|
||||||
|
}
|
||||||
|
catch (PcodeXMLException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findAttribute(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
for (;;) {
|
||||||
|
int id = getNextAttributeId();
|
||||||
|
if (id == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (id == attribId.getId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rewindAttributes() {
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean readBool() throws PcodeXMLException {
|
||||||
|
String value = scanAttribute();
|
||||||
|
return SpecXmlUtils.decodeBoolean(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean readBool(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
findAttribute(attribId);
|
||||||
|
String value = scanAttribute();
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
return SpecXmlUtils.decodeBoolean(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readSignedInteger() throws PcodeXMLException {
|
||||||
|
String value = scanAttribute();
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
findAttribute(attribId);
|
||||||
|
String value = scanAttribute();
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readUnsignedInteger() throws PcodeXMLException {
|
||||||
|
String value = scanAttribute();
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
findAttribute(attribId);
|
||||||
|
String value = scanAttribute();
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
return SpecXmlUtils.decodeLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readString() throws PcodeXMLException {
|
||||||
|
return scanAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readString(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
findAttribute(attribId);
|
||||||
|
String value = scanAttribute();
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSpace readSpace() throws PcodeXMLException {
|
||||||
|
String value = scanAttribute();
|
||||||
|
AddressSpace spc = addressFactory.getAddressSpace(value);
|
||||||
|
if (spc == null) {
|
||||||
|
throw new PcodeXMLException("Unknown address space: " + value);
|
||||||
|
}
|
||||||
|
return spc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException {
|
||||||
|
findAttribute(attribId);
|
||||||
|
String value = scanAttribute();
|
||||||
|
currentPos = attribStart;
|
||||||
|
startOpen = true;
|
||||||
|
AddressSpace spc = addressFactory.getAddressSpace(value);
|
||||||
|
if (spc == null) {
|
||||||
|
throw new PcodeXMLException("Unknown address space: " + value);
|
||||||
|
}
|
||||||
|
return spc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.xml;
|
package ghidra.xml;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface XmlElement {
|
public interface XmlElement {
|
||||||
|
@ -31,6 +31,8 @@ public interface XmlElement {
|
||||||
|
|
||||||
public Map<String, String> getAttributes();
|
public Map<String, String> getAttributes();
|
||||||
|
|
||||||
|
public Iterator<Map.Entry<String, String>> getAttributeIterator();
|
||||||
|
|
||||||
public boolean hasAttribute(String key);
|
public boolean hasAttribute(String key);
|
||||||
|
|
||||||
public String getAttribute(String key);
|
public String getAttribute(String key);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.xml;
|
package ghidra.xml;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class XmlElementImpl implements XmlElement {
|
public class XmlElementImpl implements XmlElement {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -31,7 +29,8 @@ public class XmlElementImpl implements XmlElement {
|
||||||
private final int lineNumber;
|
private final int lineNumber;
|
||||||
|
|
||||||
public XmlElementImpl(boolean isStart, boolean isEnd, String name, int level,
|
public XmlElementImpl(boolean isStart, boolean isEnd, String name, int level,
|
||||||
LinkedHashMap<String, String> attributes, String text, int columnNumber, int lineNumber) {
|
LinkedHashMap<String, String> attributes, String text, int columnNumber,
|
||||||
|
int lineNumber) {
|
||||||
if (isStart && isEnd) {
|
if (isStart && isEnd) {
|
||||||
throw new XmlException(
|
throw new XmlException(
|
||||||
"empty elements must be split into separate start and end elements (see splitEmptyElement)");
|
"empty elements must be split into separate start and end elements (see splitEmptyElement)");
|
||||||
|
@ -47,14 +46,17 @@ public class XmlElementImpl implements XmlElement {
|
||||||
this.lineNumber = lineNumber;
|
this.lineNumber = lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getColumnNumber() {
|
public int getColumnNumber() {
|
||||||
return columnNumber;
|
return columnNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getLineNumber() {
|
public int getLineNumber() {
|
||||||
return lineNumber;
|
return lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean hasAttribute(String key) {
|
public boolean hasAttribute(String key) {
|
||||||
if (attributes == null) {
|
if (attributes == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -62,6 +64,7 @@ public class XmlElementImpl implements XmlElement {
|
||||||
return attributes.containsKey(key);
|
return attributes.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getAttribute(String key) {
|
public String getAttribute(String key) {
|
||||||
if (attributes == null) {
|
if (attributes == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -69,34 +72,50 @@ public class XmlElementImpl implements XmlElement {
|
||||||
return attributes.get(key);
|
return attributes.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public LinkedHashMap<String, String> getAttributes() {
|
public LinkedHashMap<String, String> getAttributes() {
|
||||||
return attributes == null ? null : new LinkedHashMap<String, String>(attributes);
|
return attributes == null ? null : new LinkedHashMap<String, String>(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String, String>> getAttributeIterator() {
|
||||||
|
if (attributes == null) {
|
||||||
|
return Collections.emptyIterator();
|
||||||
|
}
|
||||||
|
return attributes.entrySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setAttribute(String key, String value) {
|
public void setAttribute(String key, String value) {
|
||||||
attributes.put(key, value);
|
attributes.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getLevel() {
|
public int getLevel() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isContent() {
|
public boolean isContent() {
|
||||||
return isContent;
|
return isContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEnd() {
|
public boolean isEnd() {
|
||||||
return isEnd;
|
return isEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isStart() {
|
public boolean isStart() {
|
||||||
return isStart;
|
return isStart;
|
||||||
}
|
}
|
||||||
|
@ -158,13 +177,12 @@ public class XmlElementImpl implements XmlElement {
|
||||||
public static XmlElement[] splitEmptyElement(final XmlElementImpl element) {
|
public static XmlElement[] splitEmptyElement(final XmlElementImpl element) {
|
||||||
XmlElement[] result;
|
XmlElement[] result;
|
||||||
if (element.isStart() && element.isEnd()) {
|
if (element.isStart() && element.isEnd()) {
|
||||||
result =
|
result = new XmlElement[] {
|
||||||
new XmlElement[] {
|
|
||||||
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
|
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
|
||||||
element.getAttributes(), null, element.getColumnNumber(),
|
element.getAttributes(), null, element.getColumnNumber(),
|
||||||
element.getLineNumber()),
|
element.getLineNumber()),
|
||||||
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null,
|
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null, "",
|
||||||
"", element.getColumnNumber(), element.getLineNumber()) };
|
element.getColumnNumber(), element.getLineNumber()) };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = new XmlElement[] { element };
|
result = new XmlElement[] { element };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue