mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-19 16:40:38 -09:00
Merge remote-tracking branch 'origin/GP-3832_d-millar_Sarif_RB--SQUASHED'
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/* ###
|
||||
* 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.app.plugin.core.datamgr.actions;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import docking.widgets.tree.GTree;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.ISF.IsfDataTypeWriter;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DataTypeWriterTask extends Task {
|
||||
|
||||
private final DataTypeManager programDataTypeMgr;
|
||||
private final List<DataType> dataTypeList;
|
||||
private final File file;
|
||||
private final GTree gTree;
|
||||
|
||||
public DataTypeWriterTask(GTree gTree, DataTypeManager programDataTypeMgr, List<DataType> dataTypeList, File file) {
|
||||
super("Export Data Types", true, false, true);
|
||||
this.gTree = gTree;
|
||||
this.programDataTypeMgr = programDataTypeMgr;
|
||||
this.dataTypeList = dataTypeList;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) {
|
||||
try {
|
||||
//monitor.setMessage("Export to " + file.getName() + "...");
|
||||
FileWriter baseWriter = file == null ? null : new FileWriter(file);
|
||||
IsfDataTypeWriter dataTypeWriter = new IsfDataTypeWriter(programDataTypeMgr, dataTypeList, baseWriter);
|
||||
|
||||
try {
|
||||
JsonObject object = dataTypeWriter.getRootObject(monitor);
|
||||
if (file != null) {
|
||||
dataTypeWriter.write(object);
|
||||
}
|
||||
} finally {
|
||||
dataTypeWriter.close();
|
||||
}
|
||||
} catch (CancelledException e) {
|
||||
// user cancelled; ignore
|
||||
} catch (IOException e) {
|
||||
Msg.showError(getClass(), gTree, "Export Data Types Failed", "Error exporting Data Types: " + e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,14 +188,14 @@ public class ExportToIsfAction extends DockingAction {
|
||||
fileChooser.dispose();
|
||||
}
|
||||
|
||||
private class DataTypeWriterTask extends Task {
|
||||
public class DataTypeWriterTask extends Task {
|
||||
|
||||
private final DataTypeManager programDataTypeMgr;
|
||||
private final List<DataType> dataTypeList;
|
||||
private final File file;
|
||||
private final GTree gTree;
|
||||
|
||||
DataTypeWriterTask(GTree gTree, DataTypeManager programDataTypeMgr,
|
||||
public DataTypeWriterTask(GTree gTree, DataTypeManager programDataTypeMgr,
|
||||
List<DataType> dataTypeList, File file) {
|
||||
super("Export Data Types", true, false, true);
|
||||
this.gTree = gTree;
|
||||
@@ -209,12 +209,9 @@ public class ExportToIsfAction extends DockingAction {
|
||||
try {
|
||||
monitor.setMessage("Export to " + file.getName() + "...");
|
||||
IsfDataTypeWriter dataTypeWriter =
|
||||
new IsfDataTypeWriter(programDataTypeMgr, new FileWriter(file));
|
||||
new IsfDataTypeWriter(programDataTypeMgr, dataTypeList, new FileWriter(file));
|
||||
|
||||
try {
|
||||
for (DataType dataType : dataTypeList) {
|
||||
dataTypeWriter.requestType(dataType);
|
||||
}
|
||||
JsonObject object = dataTypeWriter.getRootObject(monitor);
|
||||
dataTypeWriter.write(object);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class IsfClientHandler {
|
||||
private String lookType(String ns, String key) throws IOException {
|
||||
IsfDataTypeWriter isfWriter = createDataTypeWriter(server.getDataTypeManager(ns));
|
||||
isfWriter.setSkipSymbols(true);
|
||||
isfWriter.requestType(key);
|
||||
//isfWriter.requestType(key);
|
||||
return writeFrom(isfWriter);
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public class IsfClientHandler {
|
||||
|
||||
private IsfDataTypeWriter createDataTypeWriter(DataTypeManager dtm) throws IOException {
|
||||
StringWriter out = new StringWriter();
|
||||
return new IsfDataTypeWriter(dtm, out);
|
||||
return new IsfDataTypeWriter(dtm, null, out);
|
||||
}
|
||||
|
||||
private String writeFrom(IsfDataTypeWriter dataTypeWriter) throws IOException {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* ###
|
||||
* 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.data.ISF;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.ISF.AbstractIsfWriter.Exclude;
|
||||
|
||||
public abstract class AbstractIsfObject implements IsfObject {
|
||||
|
||||
@Exclude
|
||||
public String name;
|
||||
@Exclude
|
||||
public String location;
|
||||
@Exclude
|
||||
public List<IsfSetting> settings;
|
||||
|
||||
public AbstractIsfObject(DataType dt) {
|
||||
if (dt != null) {
|
||||
name = dt.getName();
|
||||
location = dt.getCategoryPath().getPath();
|
||||
Settings defaultSettings = dt.getDefaultSettings();
|
||||
processSettings(dt, defaultSettings);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processSettings(DataType dt, Settings defaultSettings) {
|
||||
SettingsDefinition[] settingsDefinitions = dt.getSettingsDefinitions();
|
||||
for (SettingsDefinition def : settingsDefinitions) {
|
||||
if (def.hasValue(defaultSettings)) {
|
||||
settings = new ArrayList<>();
|
||||
String[] names = defaultSettings.getNames();
|
||||
for (String n : names) {
|
||||
Object value = defaultSettings.getValue(n);
|
||||
if (value != null) {
|
||||
IsfSetting setting = new IsfSetting(n, value);
|
||||
settings.add(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/* ###
|
||||
* 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.data.ISF;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public abstract class AbstractIsfWriter implements Closeable {
|
||||
|
||||
protected JsonWriter writer;
|
||||
protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
protected JsonObject root = new JsonObject();
|
||||
protected JsonArray objects = new JsonArray();
|
||||
|
||||
public AbstractIsfWriter(Writer baseWriter) throws IOException {
|
||||
if (writer != null) {
|
||||
this.writer = new JsonWriter(baseWriter);
|
||||
writer.setIndent(" ");
|
||||
}
|
||||
this.gson = new GsonBuilder().addSerializationExclusionStrategy(strategy).setPrettyPrinting().create();
|
||||
}
|
||||
|
||||
protected abstract void genRoot(TaskMonitor monitor) throws CancelledException, IOException;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Exclude {
|
||||
// EMPTY
|
||||
}
|
||||
|
||||
// Am setting this as the default, but it's possible we may want more latitude
|
||||
// in the future
|
||||
protected boolean STRICT = true;
|
||||
|
||||
// @Exclude used for properties that might be desirable for a non-STRICT
|
||||
// implementation.
|
||||
ExclusionStrategy strategy = new ExclusionStrategy() {
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes field) {
|
||||
return STRICT && field.getAnnotation(Exclude.class) != null;
|
||||
}
|
||||
};
|
||||
|
||||
public JsonObject getRootObject(TaskMonitor monitor) throws CancelledException, IOException {
|
||||
genRoot(monitor);
|
||||
return root;
|
||||
}
|
||||
|
||||
public JsonArray getResults() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
public JsonElement getTree(Object obj) {
|
||||
return gson.toJsonTree(obj);
|
||||
}
|
||||
|
||||
public Object getObject(JsonElement element, Class<? extends Object> clazz) {
|
||||
return gson.fromJson(element, clazz);
|
||||
}
|
||||
|
||||
public void write(JsonObject object) {
|
||||
gson.toJson(object, writer);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,16 +17,15 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.BuiltInDataType;
|
||||
|
||||
public class IsfBuiltIn implements IsfObject {
|
||||
public class IsfBuiltIn extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
public Boolean signed;
|
||||
public String kind;
|
||||
public String endian;
|
||||
|
||||
public IsfBuiltIn(BuiltInDataType builtin) {
|
||||
super(builtin);
|
||||
size = IsfUtilities.getLength(builtin);
|
||||
signed = IsfUtilities.getSigned(builtin);
|
||||
kind = IsfUtilities.getBuiltInKind(builtin);
|
||||
endian = IsfUtilities.getEndianness(builtin);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.ISF.IsfDataTypeWriter.Exclude;
|
||||
import ghidra.program.model.data.ISF.AbstractIsfWriter.Exclude;
|
||||
|
||||
public class IsfComponent implements IsfObject {
|
||||
public class IsfComponent extends AbstractIsfObject {
|
||||
|
||||
public Integer offset;
|
||||
public IsfObject type;
|
||||
@@ -30,16 +30,25 @@ public class IsfComponent implements IsfObject {
|
||||
@Exclude
|
||||
public String field_name;
|
||||
@Exclude
|
||||
public Boolean noFieldName;
|
||||
@Exclude
|
||||
public String comment;
|
||||
|
||||
|
||||
public IsfComponent(DataTypeComponent component, IsfObject typeObj) {
|
||||
super(component.getDataType());
|
||||
offset = component.getOffset();
|
||||
type = typeObj;
|
||||
|
||||
field_name = component.getFieldName();
|
||||
if (field_name == null || field_name.equals("")) {
|
||||
noFieldName = true;
|
||||
}
|
||||
ordinal = component.getOrdinal();
|
||||
length = component.getLength();
|
||||
comment = component.getComment();
|
||||
|
||||
processSettings(component.getDataType(), component.getDefaultSettings());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,52 +15,50 @@
|
||||
*/
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.ISF.IsfDataTypeWriter.Exclude;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class IsfComposite implements IsfObject {
|
||||
public class IsfComposite extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public Integer size;
|
||||
public JsonObject fields;
|
||||
|
||||
@Exclude
|
||||
public int alignment;
|
||||
|
||||
|
||||
public IsfComposite(Composite composite, IsfDataTypeWriter writer, TaskMonitor monitor) {
|
||||
super(composite);
|
||||
size = composite.getLength();
|
||||
kind = composite instanceof Structure ? "struct" : "union";
|
||||
alignment = composite.getAlignment();
|
||||
|
||||
DataTypeComponent[] components = composite.getComponents();
|
||||
Map<String, DataTypeComponent> comps = new HashMap<>();
|
||||
for (DataTypeComponent component : components) {
|
||||
String key = component.getFieldName();
|
||||
if (key == null) {
|
||||
key = component.getDefaultFieldName();
|
||||
}
|
||||
comps.put(key, component);
|
||||
if (components.length == 0) {
|
||||
// NB: composite.getLength always returns > 0
|
||||
size = 0;
|
||||
}
|
||||
ArrayList<String> keylist = new ArrayList<>(comps.keySet());
|
||||
Collections.sort(keylist);
|
||||
|
||||
fields = new JsonObject();
|
||||
for (String key : keylist) {
|
||||
for (DataTypeComponent component : components) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
DataTypeComponent component = comps.get(key);
|
||||
IsfObject type = writer.getObjectTypeDeclaration(component);
|
||||
IsfComponent cobj = new IsfComponent(component, type);
|
||||
IsfComponent cobj = getComponent(component, type);
|
||||
String key = component.getFieldName();
|
||||
if (key == null) {
|
||||
key = DataTypeComponent.DEFAULT_FIELD_NAME_PREFIX + component.getOrdinal();
|
||||
if (component.getParent() instanceof Structure) {
|
||||
key += "_0x" + Integer.toHexString(component.getOffset());
|
||||
}
|
||||
}
|
||||
fields.add(key, writer.getTree(cobj));
|
||||
}
|
||||
}
|
||||
|
||||
protected IsfComponent getComponent(DataTypeComponent component, IsfObject type) {
|
||||
return new IsfComponent(component, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.Array;
|
||||
|
||||
public class IsfDataTypeArray implements IsfObject {
|
||||
public class IsfDataTypeArray extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public Integer count;
|
||||
public IsfObject subtype;
|
||||
|
||||
public IsfDataTypeArray(Array arr, IsfObject typeObj) {
|
||||
super(arr);
|
||||
kind = IsfUtilities.getKind(arr);
|
||||
count = arr.getNumElements();
|
||||
subtype = typeObj;
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.BitFieldDataType;
|
||||
import ghidra.program.model.data.ISF.IsfDataTypeWriter.Exclude;
|
||||
import ghidra.program.model.data.ISF.AbstractIsfWriter.Exclude;
|
||||
|
||||
public class IsfDataTypeBitField implements IsfObject {
|
||||
public class IsfDataTypeBitField extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public Integer bit_length;
|
||||
@@ -31,6 +31,7 @@ public class IsfDataTypeBitField implements IsfObject {
|
||||
private int storage_size;
|
||||
|
||||
public IsfDataTypeBitField(BitFieldDataType bf, int componentOffset, IsfObject typeObj) {
|
||||
super(bf);
|
||||
kind = IsfUtilities.getKind(bf);
|
||||
bit_length = bf.getBitSize();
|
||||
bit_offset = bf.getBitOffset();
|
||||
|
||||
@@ -17,14 +17,15 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
||||
public class IsfDataTypeDefault implements IsfObject {
|
||||
public class IsfDataTypeDefault extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public String name;
|
||||
int size;
|
||||
|
||||
public IsfDataTypeDefault(DataType dt) {
|
||||
super(dt);
|
||||
kind = IsfUtilities.getKind(dt);
|
||||
name = dt.getName();
|
||||
size = dt.getLength();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,12 +17,13 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
||||
public class IsfDataTypeTypeDef implements IsfObject {
|
||||
public class IsfDataTypeTypeDef extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public IsfObject subtype;
|
||||
|
||||
public IsfDataTypeTypeDef(DataType dt, IsfObject typeObj) {
|
||||
super(dt);
|
||||
kind = IsfUtilities.getKind(dt);
|
||||
subtype = typeObj;
|
||||
}
|
||||
|
||||
@@ -17,20 +17,43 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import ghidra.program.database.data.ProgramDataTypeManager;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFormatException;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.Array;
|
||||
import ghidra.program.model.data.BitFieldDataType;
|
||||
import ghidra.program.model.data.BuiltInDataType;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.program.model.data.DataOrganization;
|
||||
import ghidra.program.model.data.DataOrganizationImpl;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.Dynamic;
|
||||
import ghidra.program.model.data.Enum;
|
||||
import ghidra.program.model.data.FactoryDataType;
|
||||
import ghidra.program.model.data.FunctionDefinition;
|
||||
import ghidra.program.model.data.Pointer;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.program.model.symbol.ReferenceManager;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolIterator;
|
||||
import ghidra.program.model.symbol.SymbolTable;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
@@ -40,29 +63,28 @@ import ghidra.util.task.TaskMonitor;
|
||||
*
|
||||
* The ISF JSON should be valid for Volatility is STRICT==true.
|
||||
*/
|
||||
public class IsfDataTypeWriter {
|
||||
public class IsfDataTypeWriter extends AbstractIsfWriter {
|
||||
|
||||
private Map<DataType, IsfObject> resolved = new HashMap<>();
|
||||
protected Map<DataType, IsfObject> resolved = new HashMap<>();
|
||||
private Map<String, DataType> resolvedTypeMap = new HashMap<>();
|
||||
private List<String> deferredKeys = new ArrayList<>();
|
||||
public List<String> deferredKeys = new ArrayList<>();
|
||||
|
||||
private Writer baseWriter;
|
||||
private JsonWriter writer;
|
||||
private Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
private DataTypeManager dtm;
|
||||
protected DataTypeManager dtm;
|
||||
private DataOrganization dataOrganization;
|
||||
|
||||
private JsonObject data = new JsonObject();
|
||||
private JsonObject metadata = new JsonObject();
|
||||
private JsonObject baseTypes = new JsonObject();
|
||||
private JsonObject userTypes = new JsonObject();
|
||||
private JsonObject enums = new JsonObject();
|
||||
private JsonObject symbols = new JsonObject();
|
||||
protected JsonObject data = new JsonObject();
|
||||
protected JsonElement metadata;
|
||||
protected JsonElement baseTypes;
|
||||
protected JsonElement userTypes;
|
||||
protected JsonElement enums;
|
||||
protected JsonElement functions;
|
||||
protected JsonElement symbols;
|
||||
|
||||
private List<Address> requestedAddresses = new ArrayList<>();
|
||||
private List<String> requestedSymbols = new ArrayList<>();
|
||||
private List<String> requestedTypes = new ArrayList<>();
|
||||
// private List<String> requestedTypes = new ArrayList<>();
|
||||
private List<DataType> requestedDataTypes = new ArrayList<>();
|
||||
private boolean skipSymbols = false;
|
||||
private boolean skipTypes = false;
|
||||
@@ -70,11 +92,13 @@ public class IsfDataTypeWriter {
|
||||
/**
|
||||
* Constructs a new instance of this class using the given writer
|
||||
*
|
||||
* @param dtm data-type manager corresponding to target program or null for default
|
||||
* @param dtm data-type manager corresponding to target program or null
|
||||
* for default
|
||||
* @param baseWriter the writer to use when writing data types
|
||||
* @throws IOException if there is an exception writing the output
|
||||
*/
|
||||
public IsfDataTypeWriter(DataTypeManager dtm, Writer baseWriter) throws IOException {
|
||||
public IsfDataTypeWriter(DataTypeManager dtm, List<DataType> target, Writer baseWriter) throws IOException {
|
||||
super(baseWriter);
|
||||
this.dtm = dtm;
|
||||
if (dtm != null) {
|
||||
dataOrganization = dtm.getDataOrganization();
|
||||
@@ -82,66 +106,43 @@ public class IsfDataTypeWriter {
|
||||
if (dataOrganization == null) {
|
||||
dataOrganization = DataOrganizationImpl.getDefaultOrganization();
|
||||
}
|
||||
this.baseWriter = baseWriter;
|
||||
this.writer = new JsonWriter(baseWriter);
|
||||
writer.setIndent(" ");
|
||||
this.gson = new GsonBuilder()
|
||||
.addSerializationExclusionStrategy(strategy)
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
metadata = new JsonObject();
|
||||
baseTypes = new JsonObject();
|
||||
userTypes = new JsonObject();
|
||||
enums = new JsonObject();
|
||||
functions = new JsonObject();
|
||||
symbols = new JsonObject();
|
||||
requestedDataTypes = target;
|
||||
STRICT = true;
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Exclude {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
// Am setting this as the default, but it's possible we may want more latitude in the future
|
||||
private boolean STRICT = true;
|
||||
|
||||
// @Exclude used for properties that might be desirable for a non-STRICT implementation.
|
||||
ExclusionStrategy strategy = new ExclusionStrategy() {
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes field) {
|
||||
return STRICT && field.getAnnotation(Exclude.class) != null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Exports all data types in the list as ISF JSON.
|
||||
*
|
||||
* @param monitor the task monitor
|
||||
* @return the resultant JSON object
|
||||
* @throws IOException if there is an exception writing the output
|
||||
* @throws CancelledException if the action is cancelled by the user
|
||||
*/
|
||||
public JsonObject getRootObject(TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
||||
@Override
|
||||
protected void genRoot(TaskMonitor monitor) throws CancelledException, IOException {
|
||||
genMetadata();
|
||||
genTypes(monitor);
|
||||
genSymbols();
|
||||
genRoot();
|
||||
genSymbols(monitor);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private void genRoot() {
|
||||
data.add("metadata", metadata);
|
||||
data.add("base_types", baseTypes);
|
||||
data.add("user_types", userTypes);
|
||||
data.add("enums", enums);
|
||||
// Would be nice to support this in the futere, but Volatility does not
|
||||
//data.add("typedefs", typedefs);
|
||||
// Would be nice to support this in the future, but Volatility does not
|
||||
// data.add("functions", functions);
|
||||
data.add("symbols", symbols);
|
||||
}
|
||||
|
||||
public void add(JsonElement parent, String optKey, JsonElement child) {
|
||||
if (parent instanceof JsonObject) {
|
||||
JsonObject p = (JsonObject) parent;
|
||||
p.add(optKey, child);
|
||||
}
|
||||
if (parent instanceof JsonArray) {
|
||||
JsonArray p = (JsonArray) parent;
|
||||
p.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void genMetadata() {
|
||||
String oskey = "UNKNOWN";
|
||||
if (dtm instanceof ProgramDataTypeManager) {
|
||||
@@ -154,20 +155,21 @@ public class IsfDataTypeWriter {
|
||||
oskey = metaData.get("Compiler ID");
|
||||
if (metaData.containsKey("PDB Loaded")) {
|
||||
os = gson.toJsonTree(new IsfWinOS(metaData));
|
||||
}
|
||||
else if (metaData.containsKey("Executable Format")) {
|
||||
} else if (metaData.containsKey("Executable Format")) {
|
||||
if (metaData.get("Executable Format").contains("ELF")) {
|
||||
oskey = "linux";
|
||||
os = gson.toJsonTree(new IsfLinuxOS(gson, metaData));
|
||||
}
|
||||
}
|
||||
metadata.addProperty("format", "6.2.0");
|
||||
metadata.add("producer", producer);
|
||||
metadata.add(oskey, os);
|
||||
if (metadata instanceof JsonObject) {
|
||||
((JsonObject) metadata).addProperty("format", "6.2.0");
|
||||
}
|
||||
add(metadata, "producer", producer);
|
||||
add(metadata, oskey, os);
|
||||
}
|
||||
}
|
||||
|
||||
private void genSymbols() {
|
||||
private void genSymbols(TaskMonitor monitor) {
|
||||
if (!skipSymbols && dtm instanceof ProgramDataTypeManager) {
|
||||
ProgramDataTypeManager pgmDtm = (ProgramDataTypeManager) dtm;
|
||||
Program program = pgmDtm.getProgram();
|
||||
@@ -194,18 +196,15 @@ public class IsfDataTypeWriter {
|
||||
Symbol symbol = iterator.next();
|
||||
symbolToJson(imageBase, symbolTable, linkages, map, symbol);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (Address addr : requestedAddresses) {
|
||||
Symbol[] symsFromAddr =
|
||||
symbolTable.getSymbols(addr.add(imageBase.getOffset()));
|
||||
Symbol[] symsFromAddr = symbolTable.getSymbols(addr.add(imageBase.getOffset()));
|
||||
for (Symbol symbol : symsFromAddr) {
|
||||
symbolToJson(imageBase, symbolTable, linkages, map, symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (String key : requestedSymbols) {
|
||||
SymbolIterator iter = symbolTable.getSymbols(key);
|
||||
while (iter.hasNext()) {
|
||||
@@ -215,33 +214,29 @@ public class IsfDataTypeWriter {
|
||||
}
|
||||
}
|
||||
for (Entry<String, JsonObject> entry : map.entrySet()) {
|
||||
symbols.add(entry.getKey(), entry.getValue());
|
||||
add(symbols, entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Entry<String, JsonObject> entry : map.entrySet()) {
|
||||
if (entry.getKey().startsWith("_")) {
|
||||
String nu = entry.getKey().substring(1);
|
||||
if (symbols.get(nu) == null) {
|
||||
symbols.add(nu, entry.getValue());
|
||||
}
|
||||
add(symbols, nu, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void genTypes(TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
private void genTypes(TaskMonitor monitor) throws CancelledException, IOException {
|
||||
if (skipTypes) {
|
||||
return;
|
||||
}
|
||||
Map<String, DataType> map = new HashMap<>();
|
||||
if (requestedDataTypes.isEmpty()) {
|
||||
dtm.getAllDataTypes(requestedDataTypes);
|
||||
baseTypes.add("pointer", getTree(new IsfTypedefPointer()));
|
||||
baseTypes.add("undefined", getTree(new IsfTypedefPointer()));
|
||||
addSingletons();
|
||||
}
|
||||
monitor.initialize(requestedDataTypes.size());
|
||||
for (DataType dataType : requestedDataTypes) {
|
||||
String key = dataType.getName();
|
||||
String key = dataType.getPathName();
|
||||
map.put(key, dataType);
|
||||
}
|
||||
|
||||
@@ -260,10 +255,9 @@ public class IsfDataTypeWriter {
|
||||
private void processMap(Map<String, DataType> map, List<String> keylist, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
JsonObject obj = new JsonObject();
|
||||
int cnt = 0;
|
||||
monitor.setMaximum(keylist.size());
|
||||
for (String key : keylist) {
|
||||
DataType dataType = map.get(key);
|
||||
monitor.checkCancelled();
|
||||
if (key.contains(".conflict")) {
|
||||
continue;
|
||||
}
|
||||
@@ -272,36 +266,29 @@ public class IsfDataTypeWriter {
|
||||
continue;
|
||||
}
|
||||
if (dataType instanceof FunctionDefinition) {
|
||||
// Would be nice to support this in the futere, but Volatility does not
|
||||
//typedefs.add(dataType.getName(), obj);
|
||||
}
|
||||
else if (IsfUtilities.isBaseDataType(dataType)) {
|
||||
baseTypes.add(dataType.getName(), obj);
|
||||
}
|
||||
else if (dataType instanceof TypeDef) {
|
||||
// Would be nice to support this in the future, but Volatility does not
|
||||
add(functions, dataType.getPathName(), obj);
|
||||
} else if (IsfUtilities.isBaseDataType(dataType)) {
|
||||
add(baseTypes, dataType.getPathName(), obj);
|
||||
} else if (dataType instanceof TypeDef) {
|
||||
DataType baseDataType = ((TypeDef) dataType).getBaseDataType();
|
||||
if (IsfUtilities.isBaseDataType(baseDataType)) {
|
||||
baseTypes.add(dataType.getName(), obj);
|
||||
}
|
||||
else if (baseDataType instanceof Enum) {
|
||||
enums.add(dataType.getName(), obj);
|
||||
}
|
||||
else {
|
||||
userTypes.add(dataType.getName(), obj);
|
||||
add(baseTypes, dataType.getPathName(), obj);
|
||||
} else if (baseDataType instanceof Enum) {
|
||||
add(enums, dataType.getPathName(), obj);
|
||||
} else {
|
||||
add(userTypes, dataType.getPathName(), obj);
|
||||
}
|
||||
} else if (dataType instanceof Enum) {
|
||||
add(enums, dataType.getPathName(), obj);
|
||||
} else if (dataType instanceof Composite) {
|
||||
add(userTypes, dataType.getPathName(), obj);
|
||||
}
|
||||
else if (dataType instanceof Enum) {
|
||||
enums.add(dataType.getName(), obj);
|
||||
}
|
||||
else if (dataType instanceof Composite) {
|
||||
userTypes.add(dataType.getName(), obj);
|
||||
}
|
||||
monitor.setProgress(++cnt);
|
||||
monitor.increment();
|
||||
}
|
||||
}
|
||||
|
||||
private void symbolToJson(Address imageBase, SymbolTable symbolTable,
|
||||
Map<String, Symbol> linkages,
|
||||
private void symbolToJson(Address imageBase, SymbolTable symbolTable, Map<String, Symbol> linkages,
|
||||
Map<String, JsonObject> map, Symbol symbol) {
|
||||
String key = symbol.getName();
|
||||
Address address = symbol.getAddress();
|
||||
@@ -313,9 +300,12 @@ public class IsfDataTypeWriter {
|
||||
sym.addProperty("linkage_name", linkage.getName());
|
||||
sym.addProperty("address", linkage.getAddress().getOffset());
|
||||
}
|
||||
}
|
||||
else {
|
||||
sym.addProperty("address", address.subtract(imageBase));
|
||||
} else {
|
||||
if (address.getAddressSpace().equals(imageBase.getAddressSpace())) {
|
||||
sym.addProperty("address", address.subtract(imageBase));
|
||||
} else {
|
||||
sym.addProperty("address", address.getOffset());
|
||||
}
|
||||
}
|
||||
map.put(symbol.getName(), sym);
|
||||
if (!symbol.isPrimary()) {
|
||||
@@ -332,8 +322,12 @@ public class IsfDataTypeWriter {
|
||||
gson.toJson(obj, writer);
|
||||
}
|
||||
|
||||
JsonObject getObjectForDataType(DataType dt, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
protected void addSingletons() {
|
||||
add(baseTypes, "pointer", getTree(newTypedefPointer(null)));
|
||||
add(baseTypes, "undefined", getTree(newTypedefPointer(null)));
|
||||
}
|
||||
|
||||
protected JsonObject getObjectForDataType(DataType dt, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
IsfObject isf = getIsfObject(dt, monitor);
|
||||
if (isf != null) {
|
||||
JsonObject jobj = (JsonObject) getTree(isf);
|
||||
@@ -344,26 +338,27 @@ public class IsfDataTypeWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the data type as ISF JSON using the underlying writer. For now, ignoring top-level
|
||||
* bit-fields and function defs as unsupported by ISF. Typedefs really deserve their own
|
||||
* category, but again unsupported.
|
||||
* Writes the data type as ISF JSON using the underlying writer. For now,
|
||||
* ignoring top-level bit-fields and function defs as unsupported by ISF.
|
||||
* Typedefs really deserve their own category, but again unsupported.
|
||||
*
|
||||
* @param dt the data type to write as ISF JSON
|
||||
* @param dt the data type to write as ISF JSON
|
||||
* @param monitor the task monitor
|
||||
* @throws IOException if there is an exception writing the output
|
||||
*/
|
||||
private IsfObject getIsfObject(DataType dt, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
protected IsfObject getIsfObject(DataType dt, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
if (dt == null) {
|
||||
Msg.error(this, "Shouldn't get here - null datatype passed");
|
||||
return null;
|
||||
throw new IOException("Null datatype passed to getIsfObject");
|
||||
}
|
||||
if (dt instanceof FactoryDataType) {
|
||||
Msg.error(this, "Factory data types may not be written - type: " + dt);
|
||||
}
|
||||
if (dt instanceof Pointer || dt instanceof Array || dt instanceof BitFieldDataType) {
|
||||
if (dt instanceof BitFieldDataType) {
|
||||
Msg.error(this, "BitField data types may not be written - type: " + dt);
|
||||
}
|
||||
if (dt instanceof Pointer || dt instanceof Array) {
|
||||
IsfObject type = getObjectDataType(IsfUtilities.getBaseDataType(dt));
|
||||
IsfObject obj = new IsfTypedObject(dt, type);
|
||||
IsfObject obj = newTypedObject(dt, type);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -377,41 +372,33 @@ public class IsfDataTypeWriter {
|
||||
if (dt instanceof Dynamic dynamic) {
|
||||
DataType rep = dynamic.getReplacementBaseType();
|
||||
return rep == null ? null : getIsfObject(rep, monitor);
|
||||
}
|
||||
else if (dt instanceof TypeDef typedef) {
|
||||
} else if (dt instanceof TypeDef typedef) {
|
||||
return getObjectTypeDef(typedef, monitor);
|
||||
}
|
||||
else if (dt instanceof Composite composite) {
|
||||
} else if (dt instanceof Composite composite) {
|
||||
return new IsfComposite(composite, this, monitor);
|
||||
}
|
||||
else if (dt instanceof Enum enumm) {
|
||||
} else if (dt instanceof Enum enumm) {
|
||||
return new IsfEnum(enumm);
|
||||
}
|
||||
else if (dt instanceof BuiltInDataType builtin) {
|
||||
} else if (dt instanceof BuiltInDataType builtin) {
|
||||
return new IsfBuiltIn(builtin);
|
||||
}
|
||||
else if (dt instanceof BitFieldDataType) {
|
||||
} else if (dt instanceof BitFieldDataType) {
|
||||
// skip - not hit
|
||||
}
|
||||
else if (dt instanceof FunctionDefinition) { ///FAIL
|
||||
} else if (dt instanceof FunctionDefinition) { /// FAIL
|
||||
// skip - not hit
|
||||
}
|
||||
else if (dt.equals(DataType.DEFAULT)) {
|
||||
} else if (dt.equals(DataType.DEFAULT)) {
|
||||
// skip - not hit
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Msg.warn(this, "Unable to write datatype. Type unrecognized: " + dt.getClass());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IsfObject resolve(DataType dt) {
|
||||
public IsfObject resolve(DataType dt) {
|
||||
if (resolved.containsKey(dt)) {
|
||||
return resolved.get(dt);
|
||||
}
|
||||
|
||||
DataType resolvedType = resolvedTypeMap.get(dt.getName());
|
||||
DataType resolvedType = resolvedTypeMap.get(dt.getPathName());
|
||||
if (resolvedType != null) {
|
||||
if (resolvedType.isEquivalent(dt)) {
|
||||
return resolved.get(dt); // skip equivalent type with same name as a resolved type
|
||||
@@ -425,31 +412,32 @@ public class IsfDataTypeWriter {
|
||||
}
|
||||
}
|
||||
}
|
||||
Msg.warn(this, "WARNING! conflicting data type names: " + dt.getPathName() +
|
||||
" - " + resolvedType.getPathName());
|
||||
Msg.warn(this,
|
||||
"WARNING! conflicting data type names: " + dt.getPathName() + " - " + resolvedType.getPathName());
|
||||
return resolved.get(dt);
|
||||
}
|
||||
|
||||
resolvedTypeMap.put(dt.getName(), dt);
|
||||
resolvedTypeMap.put(dt.getPathName(), dt);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void clearResolve(String typedefName, DataType baseType) {
|
||||
if (baseType instanceof Composite || baseType instanceof Enum) {
|
||||
// auto-typedef generated with composite and enum
|
||||
if (typedefName.equals(baseType.getName())) {
|
||||
if (typedefName.equals(baseType.getPathName())) {
|
||||
resolvedTypeMap.remove(typedefName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Inherited from DataTypeWriter (logic lost to time):
|
||||
// A comment explaining the special 'P' case would be helpful!! Smells like fish.
|
||||
// Inherited from DataTypeWriter (logic lost to time):
|
||||
// A comment explaining the special 'P' case would be helpful!! Smells like
|
||||
// fish.
|
||||
else if (baseType instanceof Pointer && typedefName.startsWith("P")) {
|
||||
DataType dt = ((Pointer) baseType).getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof Composite && dt.getName().equals(typedefName.substring(1))) {
|
||||
if (dt instanceof Composite && dt.getPathName().equals(typedefName.substring(1))) {
|
||||
// auto-pointer-typedef generated with composite
|
||||
resolvedTypeMap.remove(typedefName);
|
||||
return;
|
||||
@@ -469,13 +457,11 @@ public class IsfDataTypeWriter {
|
||||
int elementLen = replacementBaseType.getLength();
|
||||
if (elementLen > 0) {
|
||||
int elementCnt = (component.getLength() + elementLen - 1) / elementLen;
|
||||
return new IsfDynamicComponent(dynamic, type, elementCnt);
|
||||
return newIsfDynamicComponent(dynamic, type, elementCnt);
|
||||
|
||||
}
|
||||
Msg.error(this,
|
||||
dynamic.getClass().getSimpleName() +
|
||||
" returned bad replacementBaseType: " +
|
||||
replacementBaseType.getClass().getSimpleName());
|
||||
Msg.error(this, dynamic.getClass().getSimpleName() + " returned bad replacementBaseType: "
|
||||
+ replacementBaseType.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -492,7 +478,7 @@ public class IsfDataTypeWriter {
|
||||
return getObjectDataType(dataType, -1);
|
||||
}
|
||||
|
||||
private IsfObject getObjectDataType(DataType dataType, int componentOffset) {
|
||||
public IsfObject getObjectDataType(DataType dataType, int componentOffset) {
|
||||
if (dataType == null) {
|
||||
return new IsfDataTypeNull();
|
||||
}
|
||||
@@ -509,9 +495,9 @@ public class IsfDataTypeWriter {
|
||||
IsfObject baseObject = getObjectDataType(IsfUtilities.getBaseDataType(dataType));
|
||||
return new IsfDataTypeTypeDef(dataType, baseObject);
|
||||
}
|
||||
if (dataType.getName().contains(".conflict")) {
|
||||
if (!deferredKeys.contains(dataType.getName())) {
|
||||
deferredKeys.add(dataType.getName());
|
||||
if (dataType.getPathName().contains(".conflict")) {
|
||||
if (!deferredKeys.contains(dataType.getPathName())) {
|
||||
deferredKeys.add(dataType.getPathName());
|
||||
}
|
||||
}
|
||||
return new IsfDataTypeDefault(dataType);
|
||||
@@ -522,27 +508,21 @@ public class IsfDataTypeWriter {
|
||||
*
|
||||
* @throws CancelledException if the action is cancelled by the user
|
||||
*/
|
||||
private IsfObject getObjectTypeDef(TypeDef typeDef, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
//UNVERIFIED
|
||||
protected IsfObject getObjectTypeDef(TypeDef typeDef, TaskMonitor monitor) throws CancelledException {
|
||||
DataType dataType = typeDef.getDataType();
|
||||
String typedefName = typeDef.getDisplayName();
|
||||
String dataTypeName = dataType.getDisplayName();
|
||||
if (IsfUtilities.isIntegral(typedefName, dataTypeName)) {
|
||||
return new IsfTypedefIntegral(typeDef);
|
||||
}
|
||||
String typedefName = typeDef.getPathName();
|
||||
|
||||
DataType baseType = typeDef.getBaseDataType();
|
||||
DataType baseType = typeDef.getDataType();
|
||||
try {
|
||||
if (baseType instanceof BuiltInDataType builtin) {
|
||||
return new IsfTypedefBase(typeDef);
|
||||
return newTypedefBase(typeDef);
|
||||
}
|
||||
if (!(baseType instanceof Pointer)) {
|
||||
return getIsfObject(dataType, monitor);
|
||||
IsfObject isfObject = getIsfObject(dataType, monitor);
|
||||
return newTypedefUser(typeDef, isfObject);
|
||||
}
|
||||
return new IsfTypedefPointer();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return newTypedefPointer(typeDef);
|
||||
} catch (Exception e) {
|
||||
Msg.error(this, "TypeDef error: " + e);
|
||||
}
|
||||
clearResolve(typedefName, baseType);
|
||||
@@ -550,11 +530,7 @@ public class IsfDataTypeWriter {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JsonElement getTree(Object obj) {
|
||||
return gson.toJsonTree(obj);
|
||||
}
|
||||
|
||||
public void requestAddress(String key) {
|
||||
public void requestAddress(String key) throws IOException {
|
||||
if (dtm instanceof ProgramDataTypeManager pgmDtm) {
|
||||
try {
|
||||
Address address = pgmDtm.getProgram().getMinAddress().getAddress(key);
|
||||
@@ -563,9 +539,8 @@ public class IsfDataTypeWriter {
|
||||
return;
|
||||
}
|
||||
requestedAddresses.add(address);
|
||||
}
|
||||
catch (AddressFormatException e) {
|
||||
e.printStackTrace();
|
||||
} catch (AddressFormatException e) {
|
||||
throw new IOException("Bad address format: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -578,24 +553,6 @@ public class IsfDataTypeWriter {
|
||||
requestedSymbols.add(symbol);
|
||||
}
|
||||
|
||||
public void requestType(String path) {
|
||||
requestedTypes.add(path);
|
||||
DataType dataType = dtm.getDataType(path);
|
||||
if (dataType == null) {
|
||||
Msg.error(this, path + " not found");
|
||||
return;
|
||||
}
|
||||
requestedDataTypes.add(dataType);
|
||||
}
|
||||
|
||||
public void requestType(DataType dataType) {
|
||||
if (dataType == null) {
|
||||
Msg.error(this, dataType + " not found");
|
||||
return;
|
||||
}
|
||||
requestedDataTypes.add(dataType);
|
||||
}
|
||||
|
||||
public JsonWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
@@ -605,16 +562,6 @@ public class IsfDataTypeWriter {
|
||||
return baseWriter.toString();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSkipSymbols(boolean val) {
|
||||
skipSymbols = val;
|
||||
}
|
||||
@@ -623,7 +570,28 @@ public class IsfDataTypeWriter {
|
||||
skipTypes = val;
|
||||
}
|
||||
|
||||
public void setStrict(boolean val) {
|
||||
STRICT = val;
|
||||
public IsfTypedefBase newTypedefBase(TypeDef typeDef) {
|
||||
return new IsfTypedefBase(typeDef);
|
||||
}
|
||||
|
||||
// public IsfTypedefIntegral newTypedefIntegral(TypeDef typeDef) {
|
||||
// return new IsfTypedefIntegral(typeDef);
|
||||
// }
|
||||
|
||||
public IsfTypedefPointer newTypedefPointer(TypeDef typeDef) {
|
||||
return new IsfTypedefPointer(typeDef);
|
||||
}
|
||||
|
||||
public IsfObject newTypedefUser(TypeDef typeDef, IsfObject object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
public IsfTypedObject newTypedObject(DataType dt, IsfObject type) {
|
||||
return new IsfTypedObject(dt, type);
|
||||
}
|
||||
|
||||
public IsfObject newIsfDynamicComponent(Dynamic dynamic, IsfObject type, int elementCnt) {
|
||||
return new IsfDynamicComponent(dynamic, type, elementCnt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.Dynamic;
|
||||
|
||||
public class IsfDynamicComponent implements IsfObject {
|
||||
public class IsfDynamicComponent extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public Integer count;
|
||||
public IsfObject subtype;
|
||||
|
||||
public IsfDynamicComponent(Dynamic dynamicType, IsfObject type, int elementCnt) {
|
||||
super(dynamicType);
|
||||
kind = "array";
|
||||
subtype = type;
|
||||
count = elementCnt;
|
||||
|
||||
@@ -19,13 +19,14 @@ import com.google.gson.JsonObject;
|
||||
|
||||
import ghidra.program.model.data.Enum;
|
||||
|
||||
public class IsfEnum implements IsfObject {
|
||||
public class IsfEnum extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
public String base;
|
||||
public JsonObject constants = new JsonObject();
|
||||
|
||||
public IsfEnum(Enum enumm) {
|
||||
super(enumm);
|
||||
size = enumm.getLength();
|
||||
base = "int";
|
||||
String[] names = enumm.getNames();
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
*/
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
public class IsfFunction implements IsfObject {
|
||||
import ghidra.program.model.data.FunctionDefinition;
|
||||
|
||||
public class IsfFunction extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
|
||||
public IsfFunction() {
|
||||
public IsfFunction(FunctionDefinition def) {
|
||||
super(def);
|
||||
kind = "function";
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,15 @@ package ghidra.program.model.data.ISF;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.FunctionDefinition;
|
||||
|
||||
public class IsfFunctionPointer implements IsfObject {
|
||||
public class IsfFunctionPointer extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public IsfObject subtype;
|
||||
|
||||
public IsfFunctionPointer(FunctionDefinition def, DataType dt) {
|
||||
super(def);
|
||||
kind = "pointer";
|
||||
subtype = new IsfFunction();
|
||||
subtype = new IsfFunction(def);
|
||||
//TODO?
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
public interface IsfObject {
|
||||
|
||||
// EMPTY by design
|
||||
|
||||
// EMPTY
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* 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.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.Pointer;
|
||||
|
||||
public class IsfPointer implements IsfObject {
|
||||
|
||||
public Integer size;
|
||||
public String kind;
|
||||
public String endian;
|
||||
|
||||
public IsfPointer(Pointer ptr) {
|
||||
size = ptr.hasLanguageDependantLength() ? -1 : IsfUtilities.getLength(ptr);
|
||||
kind = "pointer";
|
||||
endian = IsfUtilities.getEndianness(ptr);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/* ###
|
||||
* 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.data.ISF;
|
||||
|
||||
public class IsfSetting implements IsfObject {
|
||||
|
||||
public String name;
|
||||
public String kind;
|
||||
public String value;
|
||||
|
||||
public IsfSetting(String name, Object value) {
|
||||
this.name = name;
|
||||
this.value = value.toString();
|
||||
this.kind = value instanceof String ? "string" : "long";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,15 +17,16 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
||||
public class IsfTypedObject implements IsfObject {
|
||||
public class IsfTypedObject extends AbstractIsfObject {
|
||||
|
||||
public String kind;
|
||||
public Integer size;
|
||||
public IsfObject type;
|
||||
|
||||
public IsfTypedObject(DataType dt, IsfObject typeObj) {
|
||||
super(dt);
|
||||
kind = IsfUtilities.getKind(dt);
|
||||
size = dt.getLength();
|
||||
size = dt.hasLanguageDependantLength() ? -1 : dt.getLength();
|
||||
type = typeObj;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,17 @@ package ghidra.program.model.data.ISF;
|
||||
import ghidra.program.model.data.BuiltInDataType;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
|
||||
public class IsfTypedefBase implements IsfObject {
|
||||
public class IsfTypedefBase extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
public String kind;
|
||||
public Boolean signed;
|
||||
public String endian;
|
||||
|
||||
public IsfTypedefBase(TypeDef typeDef) {
|
||||
super(typeDef);
|
||||
BuiltInDataType builtin = (BuiltInDataType) typeDef.getBaseDataType();
|
||||
size = typeDef.getLength();
|
||||
kind = IsfUtilities.getBuiltInKind(builtin);
|
||||
signed = IsfUtilities.getSigned(typeDef);
|
||||
endian = IsfUtilities.getEndianness(typeDef);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,12 @@ package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
|
||||
public class IsfTypedefIntegral implements IsfObject {
|
||||
public class IsfTypedefIntegral extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
|
||||
public IsfTypedefIntegral(TypeDef td) {
|
||||
super(td);
|
||||
size = td.getLength();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,21 +15,30 @@
|
||||
*/
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.Pointer;
|
||||
import ghidra.program.model.data.PointerDataType;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
|
||||
public class IsfTypedefPointer implements IsfObject {
|
||||
public class IsfTypedefPointer extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
public Boolean signed;
|
||||
public String kind;
|
||||
public String endian;
|
||||
public IsfObject type;
|
||||
|
||||
public IsfTypedefPointer() {
|
||||
PointerDataType ptr = new PointerDataType();
|
||||
size = ptr.getLength();
|
||||
signed = false; //IsfUtilities.getSigned(ptr);
|
||||
kind = IsfUtilities.getBuiltInKind(ptr);
|
||||
public IsfTypedefPointer(TypeDef typeDef) {
|
||||
super(typeDef);
|
||||
Pointer ptr;
|
||||
if (typeDef != null) {
|
||||
ptr = (Pointer) typeDef.getBaseDataType();
|
||||
}
|
||||
else {
|
||||
ptr = new PointerDataType();
|
||||
}
|
||||
size = ptr.hasLanguageDependantLength() ? -1 : ptr.getLength();
|
||||
kind = "typedef";
|
||||
endian = IsfUtilities.getEndianness(ptr);
|
||||
type = new IsfPointer(ptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
*/
|
||||
package ghidra.program.model.data.ISF;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
|
||||
public class IsfTypedefUser implements IsfObject {
|
||||
public class IsfTypedefUser extends AbstractIsfObject {
|
||||
|
||||
public Integer size;
|
||||
public String kind;
|
||||
public IsfObject type;
|
||||
|
||||
public IsfTypedefUser(TypeDef typeDef, IsfObject typeObj) {
|
||||
DataType baseType = typeDef.getBaseDataType();
|
||||
super(typeDef);
|
||||
size = typeDef.getLength();
|
||||
kind = IsfUtilities.getKind(baseType);
|
||||
kind = "typedef";
|
||||
//kind = IsfUtilities.getKind(baseType);
|
||||
type = typeObj;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,46 +20,6 @@ import ghidra.program.model.data.Enum;
|
||||
|
||||
public class IsfUtilities {
|
||||
|
||||
// list of Ghidra built-in type names which correspond to C primitive types
|
||||
private static String[] INTEGRAL_TYPES = { "char", "short", "int", "long", "long long",
|
||||
"__int64", "float", "double", "long double", "void" };
|
||||
|
||||
private static String[] INTEGRAL_MODIFIERS =
|
||||
{ "signed", "unsigned", "const", "static", "volatile", "mutable", };
|
||||
|
||||
public static boolean isIntegral(String typedefName, String basetypeName) {
|
||||
for (String type : INTEGRAL_TYPES) {
|
||||
if (typedefName.equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean endsWithIntegralType = false;
|
||||
for (String type : INTEGRAL_TYPES) {
|
||||
if (typedefName.endsWith(" " + type)) {
|
||||
endsWithIntegralType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean containsIntegralModifier = false;
|
||||
for (String modifier : INTEGRAL_MODIFIERS) {
|
||||
if (typedefName.indexOf(modifier + " ") >= 0 ||
|
||||
typedefName.indexOf(" " + modifier) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (endsWithIntegralType && containsIntegralModifier) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typedefName.endsWith(" " + basetypeName)) {
|
||||
return containsIntegralModifier;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static DataType getBaseDataType(DataType dt) {
|
||||
while (dt != null) {
|
||||
if (dt instanceof Array) {
|
||||
@@ -117,7 +77,7 @@ public class IsfUtilities {
|
||||
return "enum";
|
||||
}
|
||||
if (dt instanceof TypeDef) {
|
||||
return "base"; //"typedef";
|
||||
return "typedef";
|
||||
}
|
||||
if (dt instanceof FunctionDefinition) {
|
||||
return "function";
|
||||
@@ -133,7 +93,7 @@ public class IsfUtilities {
|
||||
|
||||
public static String getBuiltInKind(BuiltInDataType dt) {
|
||||
if (dt instanceof AbstractIntegerDataType) {
|
||||
return dt.getLength() == 1 ? "char" : "int";
|
||||
return dt.getName();
|
||||
}
|
||||
if (dt instanceof AbstractFloatDataType) {
|
||||
return "float";
|
||||
@@ -145,7 +105,7 @@ public class IsfUtilities {
|
||||
return "char"; // "string";
|
||||
}
|
||||
if (dt instanceof PointerDataType) {
|
||||
return "void"; //"pointer";
|
||||
return "pointer";
|
||||
}
|
||||
if (dt instanceof VoidDataType) {
|
||||
return "void";
|
||||
@@ -185,11 +145,48 @@ public class IsfUtilities {
|
||||
return dt.getLength();
|
||||
}
|
||||
|
||||
public static Boolean getSigned(DataType dt) {
|
||||
return dt.getDataOrganization().isSignedChar();
|
||||
}
|
||||
|
||||
public static String getEndianness(DataType dt) {
|
||||
return dt.getDataOrganization().isBigEndian() ? "big" : "little";
|
||||
}
|
||||
|
||||
// // list of Ghidra built-in type names which correspond to C primitive types
|
||||
// private static String[] INTEGRAL_TYPES = { "char", "short", "int", "long", "long long",
|
||||
// "__int64", "float", "double", "long double", "void" };
|
||||
//
|
||||
// private static String[] INTEGRAL_MODIFIERS =
|
||||
// { "signed", "unsigned", "const", "static", "volatile", "mutable", };
|
||||
//
|
||||
// public static boolean isIntegral(String typedefName, String basetypeName) {
|
||||
// for (String type : INTEGRAL_TYPES) {
|
||||
// if (typedefName.equals(type)) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// boolean endsWithIntegralType = false;
|
||||
// for (String type : INTEGRAL_TYPES) {
|
||||
// if (typedefName.endsWith(" " + type)) {
|
||||
// endsWithIntegralType = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// boolean containsIntegralModifier = false;
|
||||
// for (String modifier : INTEGRAL_MODIFIERS) {
|
||||
// if (typedefName.indexOf(modifier + " ") >= 0 ||
|
||||
// typedefName.indexOf(" " + modifier) >= 0) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (endsWithIntegralType && containsIntegralModifier) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if (typedefName.endsWith(" " + basetypeName)) {
|
||||
// return containsIntegralModifier;
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user