Merge remote-tracking branch 'origin/GP-3832_d-millar_Sarif_RB--SQUASHED'

This commit is contained in:
ghidra1
2023-11-30 16:19:13 -05:00
173 changed files with 15711 additions and 333 deletions

View File

@@ -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;
}
}
}

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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";
}

View File

@@ -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?
}

View File

@@ -17,6 +17,6 @@ package ghidra.program.model.data.ISF;
public interface IsfObject {
// EMPTY by design
// EMPTY
}

View File

@@ -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);
}
}

View File

@@ -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";
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
// }
}