mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GT-3198 remove usage of java.beans.XMLDecoder/ XMLEncoder #1090.
Java's built-in XMLEncoder / XMLDecoder is too flexible and allows the XML data being decoded to execute arbitrary commands and other non-niceness to happen. Replace FunctionBitPatternExplorerPlugin's usage with manual serializing.
This commit is contained in:
parent
2ce191d865
commit
2c9b771d13
7 changed files with 409 additions and 20 deletions
|
@ -16,7 +16,6 @@
|
||||||
//This script dumps information about byte and instructions in neighborhoods around function starts
|
//This script dumps information about byte and instructions in neighborhoods around function starts
|
||||||
//and returns to an XML file
|
//and returns to an XML file
|
||||||
//@category FunctionStartPatterns
|
//@category FunctionStartPatterns
|
||||||
import java.beans.XMLEncoder;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -118,10 +117,7 @@ public class DumpFunctionPatternInfoScript extends GhidraScript {
|
||||||
File savedFile = new File(saveDir.getAbsolutePath() + File.separator +
|
File savedFile = new File(saveDir.getAbsolutePath() + File.separator +
|
||||||
currentProgram.getDomainFile().getPathname().replaceAll("/", "_") + "_" +
|
currentProgram.getDomainFile().getPathname().replaceAll("/", "_") + "_" +
|
||||||
currentProgram.getExecutableMD5() + "_funcInfo.xml");
|
currentProgram.getExecutableMD5() + "_funcInfo.xml");
|
||||||
try (XMLEncoder xmlEncoder =
|
funcPatternList.toXmlFile(savedFile);
|
||||||
new XMLEncoder(new BufferedOutputStream(new FileOutputStream(savedFile)))) {
|
|
||||||
xmlEncoder.writeObject(funcPatternList);
|
|
||||||
}
|
|
||||||
Msg.info(this,
|
Msg.info(this,
|
||||||
"Programs analyzed: " + programsAnalyzed + "; total functions: " + totalFuncs);
|
"Programs analyzed: " + programsAnalyzed + "; total functions: " + totalFuncs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,15 @@ package ghidra.bitpatterns.info;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class for representing the values a specific context register assumes within a function body.
|
* class for representing the values a specific context register assumes within a function body.
|
||||||
*/
|
*/
|
||||||
public class ContextRegisterInfo {
|
public class ContextRegisterInfo {
|
||||||
|
|
||||||
|
static final String XML_ELEMENT_NAME = "ContextRegisterInfo";
|
||||||
|
|
||||||
String contextRegister;//the context register
|
String contextRegister;//the context register
|
||||||
String value;//the value it assumes (needed because a BigInteger will not serialize to xml)
|
String value;//the value it assumes (needed because a BigInteger will not serialize to xml)
|
||||||
BigInteger valueAsBigInteger;//the value it assumes
|
BigInteger valueAsBigInteger;//the value it assumes
|
||||||
|
@ -133,4 +138,36 @@ public class ContextRegisterInfo {
|
||||||
hashCode = 31 * hashCode + value.hashCode();
|
hashCode = 31 * hashCode + value.hashCode();
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link ContextRegisterInfo} object using data in the supplied XML node.
|
||||||
|
*
|
||||||
|
* @param ele xml Element
|
||||||
|
* @return new {@link ContextRegisterInfo} object, never null
|
||||||
|
*/
|
||||||
|
public static ContextRegisterInfo fromXml(Element ele) {
|
||||||
|
|
||||||
|
String contextRegister = ele.getAttributeValue("contextRegister");
|
||||||
|
String value = ele.getAttributeValue("value");
|
||||||
|
|
||||||
|
ContextRegisterInfo result = new ContextRegisterInfo();
|
||||||
|
result.setContextRegister(contextRegister);
|
||||||
|
result.setValue(value);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this object into XML
|
||||||
|
*
|
||||||
|
* @return new jdom Element
|
||||||
|
*/
|
||||||
|
public Element toXml() {
|
||||||
|
|
||||||
|
Element e = new Element(XML_ELEMENT_NAME);
|
||||||
|
e.setAttribute("contextRegister", contextRegister);
|
||||||
|
e.setAttribute("value", value);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.bitpatterns.info;
|
package ghidra.bitpatterns.info;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jdom.*;
|
||||||
|
import org.jdom.input.SAXBuilder;
|
||||||
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.xml.XmlUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object of this class stores all the function bit pattern information for an executable.
|
* An object of this class stores all the function bit pattern information for an executable.
|
||||||
* It records the number of bytes and instructions for each category (first, pre, and return), as
|
* It records the number of bytes and instructions for each category (first, pre, and return), as
|
||||||
|
@ -27,6 +34,8 @@ import java.util.List;
|
||||||
|
|
||||||
public class FileBitPatternInfo {
|
public class FileBitPatternInfo {
|
||||||
|
|
||||||
|
static final String XML_ELEMENT_NAME = "FileBitPatternInfo";
|
||||||
|
|
||||||
private int numFirstBytes = 0;
|
private int numFirstBytes = 0;
|
||||||
private int numFirstInstructions = 0;
|
private int numFirstInstructions = 0;
|
||||||
private int numPreBytes = 0;
|
private int numPreBytes = 0;
|
||||||
|
@ -195,4 +204,110 @@ public class FileBitPatternInfo {
|
||||||
public void setNumReturnInstructions(int numReturnInstructions) {
|
public void setNumReturnInstructions(int numReturnInstructions) {
|
||||||
this.numReturnInstructions = numReturnInstructions;
|
this.numReturnInstructions = numReturnInstructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this object into XML
|
||||||
|
*
|
||||||
|
* @return new jdom {@link Element}
|
||||||
|
*/
|
||||||
|
public Element toXml() {
|
||||||
|
Element result = new Element(XML_ELEMENT_NAME);
|
||||||
|
XmlUtilities.setStringAttr(result, "ghidraURL", ghidraURL);
|
||||||
|
XmlUtilities.setStringAttr(result, "languageID", languageID);
|
||||||
|
XmlUtilities.setIntAttr(result, "numFirstBytes", numFirstBytes);
|
||||||
|
XmlUtilities.setIntAttr(result, "numFirstInstructions", numFirstInstructions);
|
||||||
|
XmlUtilities.setIntAttr(result, "numPreBytes", numPreBytes);
|
||||||
|
XmlUtilities.setIntAttr(result, "numPreInstructions", numPreInstructions);
|
||||||
|
XmlUtilities.setIntAttr(result, "numReturnBytes", numReturnBytes);
|
||||||
|
XmlUtilities.setIntAttr(result, "numReturnInstructions", numReturnInstructions);
|
||||||
|
|
||||||
|
Element funcBitPatternInfoListEle = new Element("funcBitPatternInfoList");
|
||||||
|
for (FunctionBitPatternInfo fbpi : funcBitPatternInfo) {
|
||||||
|
funcBitPatternInfoListEle.addContent(fbpi.toXml());
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addContent(funcBitPatternInfoListEle);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link FileBitPatternInfo} instance from XML.
|
||||||
|
*
|
||||||
|
* @param e XML element to convert
|
||||||
|
* @return new {@link FileBitPatternInfo}, never null
|
||||||
|
* @throws IOException if file IO error or xml data problem
|
||||||
|
*/
|
||||||
|
public static FileBitPatternInfo fromXml(Element e) throws IOException {
|
||||||
|
|
||||||
|
String ghidraURL = e.getAttributeValue("ghidraURL");
|
||||||
|
String languageID = e.getAttributeValue("languageID");
|
||||||
|
int numFirstBytes =
|
||||||
|
XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numFirstBytes"));
|
||||||
|
int numFirstInstructions =
|
||||||
|
XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numFirstInstructions"));
|
||||||
|
int numPreBytes = XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numPreBytes"));
|
||||||
|
int numPreInstructions =
|
||||||
|
XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numPreInstructions"));
|
||||||
|
int numReturnBytes =
|
||||||
|
XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numReturnBytes"));
|
||||||
|
int numReturnInstructions =
|
||||||
|
XmlUtilities.parseInt(XmlUtilities.requireStringAttr(e, "numReturnInstructions"));
|
||||||
|
|
||||||
|
List<FunctionBitPatternInfo> funcBitPatternInfoList = new ArrayList<>();
|
||||||
|
Element funcBitPatternInfoListEle = e.getChild("funcBitPatternInfoList");
|
||||||
|
if (funcBitPatternInfoListEle != null) {
|
||||||
|
for (Element childElement : XmlUtilities.getChildren(funcBitPatternInfoListEle,
|
||||||
|
FunctionBitPatternInfo.XML_ELEMENT_NAME)) {
|
||||||
|
funcBitPatternInfoList.add(FunctionBitPatternInfo.fromXml(childElement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileBitPatternInfo result = new FileBitPatternInfo();
|
||||||
|
result.setFuncBitPatternInfo(funcBitPatternInfoList);
|
||||||
|
result.setGhidraURL(ghidraURL);
|
||||||
|
result.setLanguageID(languageID);
|
||||||
|
result.setNumFirstBytes(numFirstBytes);
|
||||||
|
result.setNumFirstInstructions(numFirstInstructions);
|
||||||
|
result.setNumPreBytes(numPreBytes);
|
||||||
|
result.setNumPreInstructions(numPreInstructions);
|
||||||
|
result.setNumReturnBytes(numReturnBytes);
|
||||||
|
result.setNumReturnInstructions(numReturnInstructions);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this object to XML and writes it to the specified file.
|
||||||
|
*
|
||||||
|
* @param destFile name of xml file to create
|
||||||
|
* @throws IOException if file io error
|
||||||
|
*/
|
||||||
|
public void toXmlFile(File destFile) throws IOException {
|
||||||
|
Element rootEle = toXml();
|
||||||
|
Document doc = new Document(rootEle);
|
||||||
|
|
||||||
|
XmlUtilities.writeDocToFile(doc, destFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link FileBitPatternInfo} instance from a XML file.
|
||||||
|
*
|
||||||
|
* @param inputFile name of xml file to read
|
||||||
|
* @return new {@link FileBitPatternInfo} instance, never null
|
||||||
|
* @throws IOException if file io error or xml data format problem
|
||||||
|
*/
|
||||||
|
public static FileBitPatternInfo fromXmlFile(File inputFile) throws IOException {
|
||||||
|
SAXBuilder sax = XmlUtilities.createSecureSAXBuilder(false, false);
|
||||||
|
try (InputStream fis = new FileInputStream(inputFile)) {
|
||||||
|
Document doc = sax.build(fis);
|
||||||
|
Element rootElem = doc.getRootElement();
|
||||||
|
return fromXml(rootElem);
|
||||||
|
}
|
||||||
|
catch (JDOMException | IOException e) {
|
||||||
|
Msg.error(FileBitPatternInfo.class, "Bad file bit pattern file " + inputFile, e);
|
||||||
|
throw new IOException("Failed to read file bit pattern " + inputFile, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.bitpatterns.info;
|
package ghidra.bitpatterns.info;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.beans.XMLDecoder;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -184,23 +183,19 @@ public class FileBitPatternInfoReader {
|
||||||
numFiles++;
|
numFiles++;
|
||||||
|
|
||||||
FileBitPatternInfo fileInfo = null;
|
FileBitPatternInfo fileInfo = null;
|
||||||
try (XMLDecoder xmlDecoder = new XMLDecoder(new FileInputStream(dataFile))) {
|
try {
|
||||||
fileInfo = (FileBitPatternInfo) xmlDecoder.readObject();
|
fileInfo = FileBitPatternInfo.fromXmlFile(dataFile);
|
||||||
}
|
|
||||||
catch (ArrayIndexOutOfBoundsException e) {
|
|
||||||
// Probably wrong type of XML file...skip
|
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Msg.error(this, "IOException", e);
|
Msg.error(this, "Error reading FileBitPatternInfo file " + dataFile, e);
|
||||||
}
|
|
||||||
if (fileInfo == null) {
|
|
||||||
Msg.info(this, "null FileBitPatternInfo for " + dataFile);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileInfo.getFuncBitPatternInfo() == null) {
|
if (fileInfo.getFuncBitPatternInfo() == null) {
|
||||||
Msg.info(this, "fList.getFuncBitPatternInfoList null for " + dataFile);
|
Msg.info(this, "fList.getFuncBitPatternInfoList null for " + dataFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
//TODO: this will set the params to the params of the first valid file
|
//TODO: this will set the params to the params of the first valid file
|
||||||
//these should agree with the parameters for all of the files
|
//these should agree with the parameters for all of the files
|
||||||
|
|
|
@ -18,6 +18,8 @@ package ghidra.bitpatterns.info;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -26,15 +28,17 @@ import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.symbol.FlowType;
|
import ghidra.program.model.symbol.FlowType;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.xml.XmlUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents information about small neighborhoods around the start and returns of a
|
* This class represents information about small neighborhoods around the start and returns of a
|
||||||
* single function
|
* single function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@XmlRootElement
|
|
||||||
public class FunctionBitPatternInfo {
|
public class FunctionBitPatternInfo {
|
||||||
|
|
||||||
|
static final String XML_ELEMENT_NAME = "FunctionBitPatternInfo";
|
||||||
|
|
||||||
private InstructionSequence firstInst;
|
private InstructionSequence firstInst;
|
||||||
private InstructionSequence preInst;
|
private InstructionSequence preInst;
|
||||||
private List<InstructionSequence> returnInst;
|
private List<InstructionSequence> returnInst;
|
||||||
|
@ -59,7 +63,7 @@ public class FunctionBitPatternInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-arg constructor for use by JAXB when restoring from XML
|
* No-arg constructor
|
||||||
*/
|
*/
|
||||||
public FunctionBitPatternInfo() {
|
public FunctionBitPatternInfo() {
|
||||||
returnBytes = new ArrayList<String>();
|
returnBytes = new ArrayList<String>();
|
||||||
|
@ -494,4 +498,99 @@ public class FunctionBitPatternInfo {
|
||||||
this.contextRegisters = contextRegisters;
|
this.contextRegisters = contextRegisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a XML element into a FunctionBitPatternInfo object.
|
||||||
|
*
|
||||||
|
* @param e xml {@link Element} to convert
|
||||||
|
* @return new {@link FunctionBitPatternInfo} object, never null
|
||||||
|
*/
|
||||||
|
public static FunctionBitPatternInfo fromXml(Element e) {
|
||||||
|
String preBytes = e.getAttributeValue("preBytes");
|
||||||
|
String firstBytes = e.getAttributeValue("firstBytes");
|
||||||
|
String address = e.getAttributeValue("address");
|
||||||
|
|
||||||
|
List<String> returnBytes = new ArrayList<>();
|
||||||
|
Element returnBytesListEle = e.getChild("returnBytesList");
|
||||||
|
if (returnBytesListEle != null) {
|
||||||
|
for (Element rbEle : XmlUtilities.getChildren(returnBytesListEle, "returnBytes")) {
|
||||||
|
returnBytes.add(rbEle.getAttributeValue("value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstructionSequence firstInst = InstructionSequence.fromXml(e.getChild("firstInst"));
|
||||||
|
InstructionSequence preInst = InstructionSequence.fromXml(e.getChild("preInst"));
|
||||||
|
|
||||||
|
List<InstructionSequence> returnInst = new ArrayList<>();
|
||||||
|
Element returnInstListEle = e.getChild("returnInstList");
|
||||||
|
if (returnInstListEle != null) {
|
||||||
|
for (Element isEle : XmlUtilities.getChildren(returnInstListEle,
|
||||||
|
InstructionSequence.XML_ELEMENT_NAME)) {
|
||||||
|
returnInst.add(InstructionSequence.fromXml(isEle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ContextRegisterInfo> contextRegisters = new ArrayList<>();
|
||||||
|
Element contextRegistersListEle = e.getChild("contextRegistersList");
|
||||||
|
if ( contextRegistersListEle != null ) {
|
||||||
|
for (Element criElement : XmlUtilities.getChildren(contextRegistersListEle,
|
||||||
|
ContextRegisterInfo.XML_ELEMENT_NAME)) {
|
||||||
|
contextRegisters.add(ContextRegisterInfo.fromXml(criElement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionBitPatternInfo result = new FunctionBitPatternInfo();
|
||||||
|
result.setPreBytes(preBytes);
|
||||||
|
result.setFirstBytes(firstBytes);
|
||||||
|
result.setAddress(address);
|
||||||
|
result.setReturnBytes(returnBytes);
|
||||||
|
result.setFirstInst(firstInst);
|
||||||
|
result.setPreInst(preInst);
|
||||||
|
result.setReturnInst(returnInst);
|
||||||
|
result.setContextRegisters(contextRegisters);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this object instance into XML.
|
||||||
|
*
|
||||||
|
* @return new jdom Element populated with all the datas
|
||||||
|
*/
|
||||||
|
public Element toXml() {
|
||||||
|
Element result = new Element(XML_ELEMENT_NAME);
|
||||||
|
|
||||||
|
XmlUtilities.setStringAttr(result, "preBytes", preBytes);
|
||||||
|
XmlUtilities.setStringAttr(result, "firstBytes", firstBytes);
|
||||||
|
XmlUtilities.setStringAttr(result, "address", address);
|
||||||
|
Element returnBytesListEle = new Element("returnBytesList");
|
||||||
|
result.addContent(returnBytesListEle);
|
||||||
|
for (String s : returnBytes) {
|
||||||
|
Element rbNode = new Element("returnBytes");
|
||||||
|
XmlUtilities.setStringAttr(rbNode, "value", s);
|
||||||
|
returnBytesListEle.addContent(rbNode);
|
||||||
|
}
|
||||||
|
if (firstInst != null) {
|
||||||
|
result.addContent(firstInst.toXml("firstInst"));
|
||||||
|
}
|
||||||
|
if (preInst != null) {
|
||||||
|
result.addContent(preInst.toXml("preInst"));
|
||||||
|
}
|
||||||
|
if (returnInst != null) {
|
||||||
|
Element returnInstListEle = new Element("returnInstList");
|
||||||
|
result.addContent(returnInstListEle);
|
||||||
|
for (InstructionSequence is : returnInst) {
|
||||||
|
returnInstListEle.addContent(is.toXml());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (contextRegisters != null) {
|
||||||
|
Element contextRegistersListEle = new Element("contextRegistersList");
|
||||||
|
result.addContent(contextRegistersListEle);
|
||||||
|
for (ContextRegisterInfo cri : contextRegisters) {
|
||||||
|
contextRegistersListEle.addContent(cri.toXml());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,10 @@ package ghidra.bitpatterns.info;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import ghidra.util.xml.XmlUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object in this class stores a sequence of instructions along with the sizes and operands of each.
|
* An object in this class stores a sequence of instructions along with the sizes and operands of each.
|
||||||
* These sequences come from function starts, function returns, or immediately before function starts.
|
* These sequences come from function starts, function returns, or immediately before function starts.
|
||||||
|
@ -24,12 +28,14 @@ import java.util.*;
|
||||||
|
|
||||||
public class InstructionSequence {
|
public class InstructionSequence {
|
||||||
|
|
||||||
|
final static String XML_ELEMENT_NAME = "InstructionSequence";
|
||||||
|
|
||||||
private String[] instructions;
|
private String[] instructions;
|
||||||
private Integer[] sizes;
|
private Integer[] sizes;
|
||||||
private String[] commaSeparatedOperands;
|
private String[] commaSeparatedOperands;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default no-arg constructor for use by JAXB
|
* Default no-arg constructor
|
||||||
*/
|
*/
|
||||||
public InstructionSequence() {
|
public InstructionSequence() {
|
||||||
}
|
}
|
||||||
|
@ -241,8 +247,9 @@ public class InstructionSequence {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int i = 0, numSeqs = currentSeqs.size(); i < numSeqs; ++i) {
|
for (int i = 0, numSeqs = currentSeqs.size(); i < numSeqs; ++i) {
|
||||||
if (currentSeqs.get(i).getInstructions()[0] != null &&
|
if (currentSeqs.get(i)
|
||||||
currentBytes.get(i).getBytes() != null) {
|
.getInstructions()[0] != null && currentBytes.get(i)
|
||||||
|
.getBytes() != null) {
|
||||||
instSeqs.add(currentSeqs.get(i));
|
instSeqs.add(currentSeqs.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,4 +261,107 @@ public class InstructionSequence {
|
||||||
}
|
}
|
||||||
return instSeqs;
|
return instSeqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this object into a XML node, using {@link #XML_ELEMENT_NAME} as the name for the node.
|
||||||
|
*
|
||||||
|
* @return new XML element
|
||||||
|
*/
|
||||||
|
public Element toXml() {
|
||||||
|
return toXml(XML_ELEMENT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this object into a XML node, using the specified name for the node.
|
||||||
|
*
|
||||||
|
* @param elementName name for the new XML node
|
||||||
|
* @return new XML element
|
||||||
|
*/
|
||||||
|
public Element toXml(String elementName) {
|
||||||
|
Element result = new Element(elementName);
|
||||||
|
|
||||||
|
Element instructionsListEle = new Element("instructions");
|
||||||
|
result.addContent(instructionsListEle);
|
||||||
|
if (instructions != null) {
|
||||||
|
for (String s : instructions) {
|
||||||
|
Element x = new Element("instruction");
|
||||||
|
instructionsListEle.addContent(x);
|
||||||
|
if (s != null) {
|
||||||
|
x.setAttribute("value", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Element sizesListEle = new Element("sizes");
|
||||||
|
result.addContent(sizesListEle);
|
||||||
|
if (sizes != null) {
|
||||||
|
for (Integer s : sizes) {
|
||||||
|
Element x = new Element("size");
|
||||||
|
sizesListEle.addContent(x);
|
||||||
|
if (s != null) {
|
||||||
|
XmlUtilities.setIntAttr(x, "value", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Element csoListEle = new Element("commaSeparatedOperands");
|
||||||
|
result.addContent(csoListEle);
|
||||||
|
if (commaSeparatedOperands != null) {
|
||||||
|
for (String s : commaSeparatedOperands) {
|
||||||
|
Element x = new Element("operands");
|
||||||
|
csoListEle.addContent(x);
|
||||||
|
if (s != null) {
|
||||||
|
x.setAttribute("value", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link InstructionSequence} instance from a XML node.
|
||||||
|
*
|
||||||
|
* @param element jdom Element to read, null ok
|
||||||
|
* @return new {@link InstructionSequence} or null if element was null
|
||||||
|
*/
|
||||||
|
public static InstructionSequence fromXml(Element element) {
|
||||||
|
if (element == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> instructionsList = new ArrayList<>();
|
||||||
|
Element instructionsListEle = element.getChild("instructions");
|
||||||
|
if (instructionsListEle != null) {
|
||||||
|
for (Element instEle : XmlUtilities.getChildren(instructionsListEle, "instruction")) {
|
||||||
|
String val = instEle.getAttributeValue("value");
|
||||||
|
instructionsList.add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Integer> sizesList = new ArrayList<>();
|
||||||
|
Element sizesListEle = element.getChild("sizes");
|
||||||
|
if (sizesListEle != null) {
|
||||||
|
for (Element sizeEle : XmlUtilities.getChildren(sizesListEle, "size")) {
|
||||||
|
String val = sizeEle.getAttributeValue("value");
|
||||||
|
sizesList.add(val != null ? XmlUtilities.parseInt(val) : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> csoList = new ArrayList<>();
|
||||||
|
Element csoListEle = element.getChild("commaSeparatedOperands");
|
||||||
|
if (csoListEle != null) {
|
||||||
|
for (Element csoEle : XmlUtilities.getChildren(csoListEle, "operands")) {
|
||||||
|
String val = csoEle.getAttributeValue("value");
|
||||||
|
csoList.add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstructionSequence result = new InstructionSequence();
|
||||||
|
result.setInstructions(instructionsList.toArray(new String[instructionsList.size()]));
|
||||||
|
result.setCommaSeparatedOperands(csoList.toArray(new String[csoList.size()]));
|
||||||
|
result.setSizes(sizesList.toArray(new Integer[sizesList.size()]));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.util.xml;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ import org.xml.sax.*;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.NumericUtilities;
|
import ghidra.util.NumericUtilities;
|
||||||
|
import util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of utility methods for working with XML.
|
* A set of utility methods for working with XML.
|
||||||
|
@ -603,6 +605,41 @@ public class XmlUtilities {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a string attribute on the specified element.
|
||||||
|
*
|
||||||
|
* @param ele JDom element
|
||||||
|
* @param attrName name of attribute
|
||||||
|
* @param attrValue value of attribute, null ok
|
||||||
|
*/
|
||||||
|
public static void setStringAttr(Element ele, String attrName, String attrValue) {
|
||||||
|
if (attrValue != null) {
|
||||||
|
ele.setAttribute(attrName, attrValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an integer attribute on the specified element.
|
||||||
|
*
|
||||||
|
* @param ele JDom element
|
||||||
|
* @param attrName name of attribute
|
||||||
|
* @param attrValue value of attribute
|
||||||
|
*/
|
||||||
|
public static void setIntAttr(Element ele, String attrName, int attrValue) {
|
||||||
|
ele.setAttribute(attrName, Integer.toString(attrValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-safe way of getting a list of {@link Element}s from JDom.
|
||||||
|
*
|
||||||
|
* @param ele the parent element
|
||||||
|
* @param childName the name of the children elements to return
|
||||||
|
* @return List<Element> of elements
|
||||||
|
*/
|
||||||
|
public static List<Element> getChildren(Element ele, String childName) {
|
||||||
|
return CollectionUtils.asList(ele.getChildren(childName), Element.class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests a string for characters that would cause a problem if added to an
|
* Tests a string for characters that would cause a problem if added to an
|
||||||
* xml attribute or element.
|
* xml attribute or element.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue