mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/Ghidra_10.1'
This commit is contained in:
commit
d6841fbe0f
10 changed files with 468 additions and 633 deletions
|
@ -983,4 +983,27 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
|
|||
emuThread.stepInstruction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that unimplemented instructions (as opposed to instructions with no semantics) result in
|
||||
* an interrupt.
|
||||
*/
|
||||
@Test(expected = PcodeExecutionException.class)
|
||||
public void testUNIMPL() throws Throwable {
|
||||
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "Toy:BE:64:default")) {
|
||||
assertEquals(Register.NO_CONTEXT, tb.language.getContextBaseRegister());
|
||||
|
||||
TraceThread thread = initTrace(tb,
|
||||
List.of(
|
||||
"pc = 0x00400000;",
|
||||
"sp = 0x00110000;"),
|
||||
List.of(
|
||||
"unimpl"));
|
||||
|
||||
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0);
|
||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||
emuThread.overrideContextWithDefault();
|
||||
emuThread.stepInstruction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,10 +122,22 @@ public class PcodeExecutor<T> {
|
|||
}
|
||||
}
|
||||
|
||||
protected void badOp(PcodeOp op) {
|
||||
switch (op.getOpcode()) {
|
||||
case PcodeOp.UNIMPLEMENTED:
|
||||
throw new LowlevelError(
|
||||
"Encountered an unimplemented instruction at " + op.getSeqnum().getTarget());
|
||||
default:
|
||||
throw new LowlevelError(
|
||||
"Unsupported p-code op at " + op.getSeqnum().getTarget() + ": " + op);
|
||||
}
|
||||
}
|
||||
|
||||
public void stepOp(PcodeOp op, PcodeFrame frame, SleighUseropLibrary<T> library) {
|
||||
OpBehavior b = OpBehaviorFactory.getOpBehavior(op.getOpcode());
|
||||
if (b == null) {
|
||||
throw new LowlevelError("Unsupported pcode op" + op);
|
||||
badOp(op);
|
||||
return;
|
||||
}
|
||||
if (b instanceof UnaryOpBehavior) {
|
||||
executeUnaryOp(op, (UnaryOpBehavior) b);
|
||||
|
@ -164,7 +176,8 @@ public class PcodeExecutor<T> {
|
|||
executeReturn(op, frame);
|
||||
return;
|
||||
default:
|
||||
throw new LowlevelError("Unsupported op " + op);
|
||||
badOp(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,18 @@ import ghidra.app.services.GraphDisplayBroker;
|
|||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.WebColors;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GraphClassesScript extends GhidraScript {
|
||||
|
||||
private static final String NO_INHERITANCE = "No Inheritance";
|
||||
private static final String SINGLE_INHERITANCE = "Single Inheritance";
|
||||
private static final String MULTIPLE_INHERITANCE = "Multiple Inheritance";
|
||||
private static final String VIRTUAL_INHERITANCE = "Virtual Inheritance";
|
||||
private static final String NON_VIRTUAL_INHERITANCE = "Non-virtual Inheritance";
|
||||
|
||||
List<Structure> classStructures = new ArrayList<Structure>();
|
||||
|
||||
@Override
|
||||
|
@ -107,7 +114,15 @@ public class GraphClassesScript extends GhidraScript {
|
|||
*/
|
||||
private AttributedGraph createGraph() throws Exception {
|
||||
|
||||
AttributedGraph g = new AttributedGraph("Test Graph", new EmptyGraphType());
|
||||
GraphType graphType =
|
||||
new GraphTypeBuilder("Class Hierarchy Graph").vertexType(NO_INHERITANCE)
|
||||
.vertexType(SINGLE_INHERITANCE)
|
||||
.vertexType(MULTIPLE_INHERITANCE)
|
||||
.edgeType(NON_VIRTUAL_INHERITANCE)
|
||||
.edgeType(VIRTUAL_INHERITANCE)
|
||||
.build();
|
||||
|
||||
AttributedGraph g = new AttributedGraph("Recovered Classes Graph", graphType);
|
||||
|
||||
for (Structure classStructure : classStructures) {
|
||||
|
||||
|
@ -176,24 +191,27 @@ public class GraphClassesScript extends GhidraScript {
|
|||
|
||||
AttributedEdge edge = g.addEdge(parentVertex, classVertex);
|
||||
if (isVirtualParent) {
|
||||
edge.setAttribute("Color", "Orange");
|
||||
edge.setEdgeType(VIRTUAL_INHERITANCE);
|
||||
}
|
||||
else {
|
||||
// else leave it default lime green
|
||||
edge.setEdgeType(NON_VIRTUAL_INHERITANCE);
|
||||
}
|
||||
// else leave it default lime green
|
||||
|
||||
description = removeClassSubstring(description, parentName);
|
||||
}
|
||||
|
||||
// no parent = blue vertex
|
||||
if (numParents == 0) {
|
||||
classVertex.setAttribute("Color", "Blue");
|
||||
classVertex.setVertexType(NO_INHERITANCE);
|
||||
}
|
||||
// single parent = green vertex
|
||||
else if (numParents == 1) {
|
||||
classVertex.setAttribute("Color", "Green");
|
||||
classVertex.setVertexType(SINGLE_INHERITANCE);
|
||||
}
|
||||
// multiple parents = red vertex
|
||||
else {
|
||||
classVertex.setAttribute("Color", "Red");
|
||||
classVertex.setVertexType(MULTIPLE_INHERITANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,7 +313,20 @@ public class GraphClassesScript extends GhidraScript {
|
|||
GraphDisplayBroker broker = tool.getService(GraphDisplayBroker.class);
|
||||
GraphDisplayProvider service = broker.getGraphDisplayProvider("Default Graph Display");
|
||||
display = service.getGraphDisplay(false, TaskMonitor.DUMMY);
|
||||
display.setGraph(graph, "test graph", false, TaskMonitor.DUMMY);
|
||||
|
||||
GraphDisplayOptions graphOptions = new GraphDisplayOptionsBuilder(graph.getGraphType())
|
||||
.vertex(NO_INHERITANCE, VertexShape.RECTANGLE, WebColors.BLUE)
|
||||
.vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.GREEN)
|
||||
.vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.RED)
|
||||
.edge(NON_VIRTUAL_INHERITANCE, WebColors.LIME_GREEN)
|
||||
.edge(VIRTUAL_INHERITANCE, WebColors.ORANGE)
|
||||
.defaultVertexColor(WebColors.PURPLE)
|
||||
.defaultEdgeColor(WebColors.PURPLE)
|
||||
.defaultLayoutAlgorithm("Compact Hierarchical")
|
||||
.build();
|
||||
|
||||
display.setGraph(graph, graphOptions,
|
||||
"Recovered Classes Graph", false, TaskMonitor.DUMMY);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// this script and default vfunctions named by this script are likely to change in the future
|
||||
// once an official design for Object Oriented representation is determined.
|
||||
// NOTE: Windows class recovery is more complete and tested than gcc class recovery, which is still
|
||||
// in early stages of development. Gcc class data types are only recovered for classes without multiple or
|
||||
// in early stages of development. Gcc class data types are only recovered for classes without
|
||||
// virtual inheritance but if the program contains DWARF, there will be some amount of data recovered
|
||||
// by the DWARF analyzer.
|
||||
// NOTE: For likely the best results, run this script on freshly analyzed programs. No testing has been
|
||||
|
@ -65,6 +65,8 @@ import ghidra.app.services.Analyzer;
|
|||
import ghidra.app.services.GraphDisplayBroker;
|
||||
import ghidra.app.util.bin.format.dwarf4.next.DWARFFunctionImporter;
|
||||
import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram;
|
||||
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.DWARFSectionProvider;
|
||||
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.DWARFSectionProviderFactory;
|
||||
import ghidra.app.util.bin.format.pdb.PdbParserConstants;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.options.Options;
|
||||
|
@ -74,6 +76,7 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.WebColors;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.GraphException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -117,6 +120,11 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
// edge between child and parent is orange if child inherits the parent virtually
|
||||
// edge between child and parent is lime green if child inherits the parent non-virtually
|
||||
private static final boolean GRAPH_CLASS_HIERARCHIES = false;
|
||||
private static final String NO_INHERITANCE = "No Inheritance";
|
||||
private static final String SINGLE_INHERITANCE = "Single Inheritance";
|
||||
private static final String MULTIPLE_INHERITANCE = "Multiple Inheritance";
|
||||
private static final String VIRTUAL_INHERITANCE = "Virtual Inheritance";
|
||||
private static final String NON_VIRTUAL_INHERITANCE = "Non-virtual Inheritance";
|
||||
|
||||
// show shortened class template names in class structure field names
|
||||
private static final boolean USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS = true;
|
||||
|
@ -134,23 +142,29 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
|
||||
private static final String INDETERMINATE_BOOKMARK = "INDETERMINATE";
|
||||
|
||||
// DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES
|
||||
// If replacedClassStructuresOption is set to the following, no replaced structures will be removed
|
||||
// from the data type manager
|
||||
private static final int DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES = 0;
|
||||
|
||||
// REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES
|
||||
// If replacedClassStructuresOption is set to the following, only empty existing class structures
|
||||
// that were replaced by this script will be removed from the data type manager
|
||||
private static final int REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES = 1;
|
||||
|
||||
// REMOVE_ALL_REPLACED_CLASS_STRUCTURES
|
||||
// If replacedClassStructuresOption is set to the following, all existing class structures that
|
||||
// were replaced by this script, including non-emtpy ones, will be removed from the data type
|
||||
// manager
|
||||
private static final int REMOVE_ALL_REPLACED_CLASS_STRUCTURES = 2;
|
||||
private static enum removeOption {
|
||||
DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES,
|
||||
REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES,
|
||||
REMOVE_ALL_REPLACED_CLASS_STRUCTURES
|
||||
}
|
||||
|
||||
// NEW OPTION -
|
||||
// This option allows the user to decide whether and how to remove replaced existing class structures
|
||||
// using one of the above three flags
|
||||
int replacedClassStructuresOption = DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES;
|
||||
removeOption replacedClassStructuresOption =
|
||||
removeOption.DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES;
|
||||
|
||||
boolean programHasRTTIApplied = false;
|
||||
boolean hasDebugSymbols;
|
||||
|
@ -178,16 +192,14 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (isWindows()) {
|
||||
|
||||
hasDebugSymbols = isPDBLoadedInProgram();
|
||||
nameVfunctions = !hasDebugSymbols;
|
||||
recoverClassesFromRTTI = new RTTIWindowsClassRecoverer(currentProgram,
|
||||
currentLocation, state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
||||
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
||||
REPLACE_EXISTING_CLASS_STRUCTURES,
|
||||
monitor);
|
||||
recoverClassesFromRTTI =
|
||||
new RTTIWindowsClassRecoverer(currentProgram, currentLocation, state.getTool(),
|
||||
this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
|
||||
nameVfunctions, hasDebugSymbols, REPLACE_EXISTING_CLASS_STRUCTURES, monitor);
|
||||
}
|
||||
else if (isGcc()) {
|
||||
|
||||
|
@ -204,11 +216,10 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
return;
|
||||
}
|
||||
nameVfunctions = !hasDebugSymbols;
|
||||
recoverClassesFromRTTI = new RTTIGccClassRecoverer(currentProgram, currentLocation,
|
||||
state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
||||
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
||||
REPLACE_EXISTING_CLASS_STRUCTURES,
|
||||
monitor);
|
||||
recoverClassesFromRTTI =
|
||||
new RTTIGccClassRecoverer(currentProgram, currentLocation, state.getTool(), this,
|
||||
BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
|
||||
nameVfunctions, hasDebugSymbols, REPLACE_EXISTING_CLASS_STRUCTURES, monitor);
|
||||
}
|
||||
else {
|
||||
println("This script will not work on this program type");
|
||||
|
@ -281,7 +292,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
getNumberOfConstructorsOrDestructors(recoveredClasses) +
|
||||
" class member functions to assign.");
|
||||
|
||||
|
||||
if (!hasDebugSymbols) {
|
||||
|
||||
if (BOOKMARK_FOUND_FUNCTIONS) {
|
||||
|
@ -301,23 +311,32 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
showGraph(graph);
|
||||
}
|
||||
|
||||
if (replacedClassStructuresOption == REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES) {
|
||||
if (replacedClassStructuresOption == removeOption.REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES) {
|
||||
println("Removing all empty replaced class structures from the data type manager");
|
||||
recoverClassesFromRTTI.removeReplacedClassStructures(recoveredClasses, false);
|
||||
}
|
||||
|
||||
if (replacedClassStructuresOption == REMOVE_ALL_REPLACED_CLASS_STRUCTURES) {
|
||||
if (replacedClassStructuresOption == removeOption.REMOVE_ALL_REPLACED_CLASS_STRUCTURES) {
|
||||
println(
|
||||
"Removing all replaced class structures from the data type manager, including non-empty ones");
|
||||
recoverClassesFromRTTI.removeReplacedClassStructures(recoveredClasses, true);
|
||||
}
|
||||
|
||||
|
||||
decompilerUtils.disposeDecompilerInterface();
|
||||
|
||||
}
|
||||
|
||||
private boolean hasDwarf() {
|
||||
return DWARFProgram.isDWARF(currentProgram);
|
||||
if (DWARFProgram.isDWARF(currentProgram)) {
|
||||
DWARFSectionProvider dsp =
|
||||
DWARFSectionProviderFactory.createSectionProviderFor(currentProgram, monitor);
|
||||
if (dsp == null) {
|
||||
return false;
|
||||
}
|
||||
dsp.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,8 +350,10 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
|
||||
private boolean isDwarfLoadedInProgram() {
|
||||
|
||||
return DWARFFunctionImporter.hasDWARFProgModule(currentProgram,
|
||||
DWARFProgram.DWARF_ROOT_NAME);
|
||||
Options options = currentProgram.getOptions(Program.PROGRAM_INFO);
|
||||
|
||||
return (DWARFFunctionImporter.hasDWARFProgModule(currentProgram,
|
||||
DWARFProgram.DWARF_ROOT_NAME) || options.getBoolean("DWARF Loaded", false));
|
||||
}
|
||||
|
||||
public String validate() {
|
||||
|
@ -392,7 +413,15 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
private AttributedGraph createGraph(List<RecoveredClass> recoveredClasses)
|
||||
throws CancelledException {
|
||||
|
||||
AttributedGraph g = new AttributedGraph("Test Graph", new EmptyGraphType());
|
||||
GraphType graphType =
|
||||
new GraphTypeBuilder("Class Hierarchy Graph").vertexType(NO_INHERITANCE)
|
||||
.vertexType(SINGLE_INHERITANCE)
|
||||
.vertexType(MULTIPLE_INHERITANCE)
|
||||
.edgeType(NON_VIRTUAL_INHERITANCE)
|
||||
.edgeType(VIRTUAL_INHERITANCE)
|
||||
.build();
|
||||
|
||||
AttributedGraph g = new AttributedGraph("Recovered Classes Graph", graphType);
|
||||
|
||||
Iterator<RecoveredClass> recoveredClassIterator = recoveredClasses.iterator();
|
||||
while (recoveredClassIterator.hasNext()) {
|
||||
|
@ -408,7 +437,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
|
||||
// no parent = blue vertex
|
||||
if (classHierarchyMap.isEmpty()) {
|
||||
classVertex.setAttribute("Color", "Blue");
|
||||
classVertex.setVertexType(NO_INHERITANCE);
|
||||
classVertex.setDescription(recoveredClass.getClassPath().getPath());
|
||||
continue;
|
||||
}
|
||||
|
@ -417,11 +446,11 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
|
||||
// single parent = green vertex
|
||||
if (parents.size() == 1) {
|
||||
classVertex.setAttribute("Color", "Green");
|
||||
classVertex.setVertexType(SINGLE_INHERITANCE);
|
||||
}
|
||||
// multiple parents = red vertex
|
||||
else {
|
||||
classVertex.setAttribute("Color", "Red");
|
||||
classVertex.setVertexType(MULTIPLE_INHERITANCE);
|
||||
}
|
||||
|
||||
classVertex.setDescription(recoveredClass.getClassPath().getPath());
|
||||
|
@ -448,9 +477,12 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
|
||||
// edge between child and parent is orange if child inherits the parent virtually
|
||||
if (isVirtualParent) {
|
||||
edge.setAttribute("Color", "Orange");
|
||||
edge.setEdgeType(VIRTUAL_INHERITANCE);
|
||||
}
|
||||
// else edge between child and parent is lime green if child inherits the parent non-virtually
|
||||
else {
|
||||
edge.setEdgeType(NON_VIRTUAL_INHERITANCE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -471,7 +503,20 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||
GraphDisplayBroker broker = tool.getService(GraphDisplayBroker.class);
|
||||
GraphDisplayProvider service = broker.getGraphDisplayProvider("Default Graph Display");
|
||||
display = service.getGraphDisplay(false, TaskMonitor.DUMMY);
|
||||
display.setGraph(graph, "test graph", false, TaskMonitor.DUMMY);
|
||||
|
||||
GraphDisplayOptions graphOptions = new GraphDisplayOptionsBuilder(graph.getGraphType())
|
||||
.vertex(NO_INHERITANCE, VertexShape.RECTANGLE, WebColors.BLUE)
|
||||
.vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.GREEN)
|
||||
.vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.RED)
|
||||
.edge(NON_VIRTUAL_INHERITANCE, WebColors.LIME_GREEN)
|
||||
.edge(VIRTUAL_INHERITANCE, WebColors.ORANGE)
|
||||
.defaultVertexColor(WebColors.PURPLE)
|
||||
.defaultEdgeColor(WebColors.PURPLE)
|
||||
.defaultLayoutAlgorithm("Compact Hierarchical")
|
||||
.build();
|
||||
|
||||
display.setGraph(graph, graphOptions,
|
||||
"Recovered Classes Graph", false, TaskMonitor.DUMMY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1045,8 +1045,10 @@ public class ExtraScriptUtils extends FlatProgramAPI {
|
|||
* @param parent parent CategoryPath
|
||||
* @param categoryName name of the new category in the parent path
|
||||
* @return CategoryPath for new categoryName
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
public CategoryPath createDataTypeCategoryPath(CategoryPath parent, String categoryName) {
|
||||
public CategoryPath createDataTypeCategoryPath(CategoryPath parent, String categoryName)
|
||||
throws CancelledException {
|
||||
|
||||
CategoryPath dataTypePath;
|
||||
|
||||
|
@ -1070,12 +1072,8 @@ public class ExtraScriptUtils extends FlatProgramAPI {
|
|||
int index = 0;
|
||||
String newCategoryName = new String();
|
||||
while (index < categoryName.length()) {
|
||||
try {
|
||||
monitor.checkCanceled();
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
monitor.checkCanceled();
|
||||
|
||||
if (categoryName.substring(index).startsWith("::") && !insideBrackets) {
|
||||
newCategoryName = newCategoryName.concat("/");
|
||||
|
|
|
@ -44,7 +44,7 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
RTTIClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
|
||||
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
||||
boolean nameVfunctions, boolean hasDebugSymbols, boolean replaceClassStructures,
|
||||
TaskMonitor monitor) {
|
||||
TaskMonitor monitor) throws Exception {
|
||||
|
||||
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
|
||||
replaceClassStructures,
|
||||
|
@ -76,7 +76,7 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
return dataTypeManager;
|
||||
}
|
||||
|
||||
public boolean containsRTTI() throws CancelledException {
|
||||
public boolean containsRTTI() throws CancelledException, InvalidInputException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -104,12 +104,12 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
|
||||
|
||||
|
||||
public void fixUpProgram() {
|
||||
public void fixUpProgram() throws CancelledException, Exception {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public List<RecoveredClass> createRecoveredClasses() {
|
||||
public List<RecoveredClass> createRecoveredClasses() throws Exception {
|
||||
|
||||
return new ArrayList<RecoveredClass>();
|
||||
}
|
||||
|
@ -121,10 +121,10 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
* Method to promote the namespace is a class namespace.
|
||||
* @param namespace the namespace for the vftable
|
||||
* @return true if namespace is (now) a class namespace or false if it could not be promoted.
|
||||
* @throws InvalidInputException if namespace was contained in function and could not be promoted
|
||||
*/
|
||||
public Namespace promoteToClassNamespace(Namespace namespace) {
|
||||
public Namespace promoteToClassNamespace(Namespace namespace) throws InvalidInputException {
|
||||
|
||||
try {
|
||||
Namespace newClass = NamespaceUtils.convertNamespaceToClass(namespace);
|
||||
|
||||
SymbolType symbolType = newClass.getSymbol().getSymbolType();
|
||||
|
@ -134,13 +134,6 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
Msg.debug(this,
|
||||
"Could not promote " + namespace.getName() + " to a class namespace");
|
||||
return null;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
|
||||
Msg.debug(this, "Could not promote " + namespace.getName() +
|
||||
" to a class namespace because " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,7 +214,7 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||
Structure existingClassStructure =
|
||||
(Structure) dataTypeManager.getDataType(dataTypePath, dataTypeName);
|
||||
|
||||
if (!existingClassStructure.isNotYetDefined()) {
|
||||
if (existingClassStructure != null && !existingClassStructure.isNotYetDefined()) {
|
||||
recoveredClass.addExistingClassStructure(existingClassStructure);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -74,18 +74,16 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
public RTTIGccClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
|
||||
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
||||
boolean nameVfunctions, boolean isDwarfLoaded, boolean replaceExistingClassStructures,
|
||||
TaskMonitor monitor) {
|
||||
TaskMonitor monitor) throws Exception {
|
||||
|
||||
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
|
||||
replaceExistingClassStructures,
|
||||
isDwarfLoaded,
|
||||
monitor);
|
||||
replaceExistingClassStructures, isDwarfLoaded, monitor);
|
||||
this.isDwarfLoaded = isDwarfLoaded;
|
||||
this.replaceClassStructs = replaceExistingClassStructures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsRTTI() throws CancelledException {
|
||||
public boolean containsRTTI() throws CancelledException, InvalidInputException {
|
||||
|
||||
if (!hasSpecialVtable()) {
|
||||
return false;
|
||||
|
@ -103,44 +101,33 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RecoveredClass> createRecoveredClasses() {
|
||||
public List<RecoveredClass> createRecoveredClasses() throws CancelledException, Exception {
|
||||
|
||||
try {
|
||||
|
||||
processGccRTTI();
|
||||
if (recoveredClasses == null) {
|
||||
Msg.debug(this, "Could not recover gcc rtti classes");
|
||||
return null;
|
||||
}
|
||||
|
||||
createCalledFunctionMap(recoveredClasses);
|
||||
|
||||
createClassHierarchyListAndMapForGcc();
|
||||
|
||||
if (isDwarfLoaded) {
|
||||
retrieveExistingClassStructures(recoveredClasses);
|
||||
assignConstructorsAndDestructorsUsingExistingName(recoveredClasses);
|
||||
}
|
||||
else {
|
||||
processConstructorAndDestructors();
|
||||
}
|
||||
|
||||
createVftableOrderMap(recoveredClasses);
|
||||
|
||||
figureOutClassDataMembers(recoveredClasses);
|
||||
|
||||
createAndApplyClassStructures();
|
||||
|
||||
return recoveredClasses;
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
e.printStackTrace();
|
||||
processGccRTTI();
|
||||
if (recoveredClasses == null) {
|
||||
Msg.debug(this, "Could not recover gcc rtti classes");
|
||||
return null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
|
||||
createCalledFunctionMap(recoveredClasses);
|
||||
|
||||
createClassHierarchyListAndMapForGcc();
|
||||
|
||||
if (isDwarfLoaded) {
|
||||
retrieveExistingClassStructures(recoveredClasses);
|
||||
assignConstructorsAndDestructorsUsingExistingName(recoveredClasses);
|
||||
}
|
||||
else {
|
||||
processConstructorAndDestructors();
|
||||
}
|
||||
|
||||
createVftableOrderMap(recoveredClasses);
|
||||
|
||||
figureOutClassDataMembers(recoveredClasses);
|
||||
|
||||
createAndApplyClassStructures();
|
||||
|
||||
return recoveredClasses;
|
||||
|
||||
}
|
||||
|
||||
|
@ -171,8 +158,8 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
|
||||
|
||||
Address found = program.getMemory()
|
||||
.findBytes(commentBlock.getStart(),
|
||||
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
|
||||
.findBytes(commentBlock.getStart(), commentBlock.getEnd(), gccBytes, maskBytes,
|
||||
true, monitor);
|
||||
if (found == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -184,8 +171,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* Method to check for at least one special RTTI vtable
|
||||
* @return true if the program has at least one special vtable, false if none
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws InvalidInputException if bad characters creating labels
|
||||
*/
|
||||
private boolean hasSpecialVtable() throws CancelledException {
|
||||
private boolean hasSpecialVtable() throws CancelledException, InvalidInputException {
|
||||
|
||||
boolean hasSpecialVtable = createSpecialVtables();
|
||||
return hasSpecialVtable;
|
||||
|
@ -287,8 +275,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
}
|
||||
|
||||
private void updateClassesWithParentsAndFlags(List<Symbol> typeinfoSymbols)
|
||||
throws Exception {
|
||||
private void updateClassesWithParentsAndFlags(List<Symbol> typeinfoSymbols) throws Exception {
|
||||
|
||||
// add properties and parents to each class
|
||||
Iterator<Symbol> typeinfoIterator = typeinfoSymbols.iterator();
|
||||
|
@ -464,6 +451,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
while (vtableIterator.hasNext()) {
|
||||
|
||||
|
||||
monitor.checkCanceled();
|
||||
|
||||
Symbol vtableSymbol = vtableIterator.next();
|
||||
|
@ -534,14 +522,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
throw new Exception("typeinfo has global namespace " + typeinfoAddress);
|
||||
}
|
||||
|
||||
try {
|
||||
Symbol vtableSymbol = symbolTable.createLabel(vtableAddress, VTABLE_LABEL,
|
||||
classNamespace, SourceType.ANALYSIS);
|
||||
vtableSymbols.add(vtableSymbol);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
continue;
|
||||
}
|
||||
Symbol vtableSymbol = symbolTable.createLabel(vtableAddress, VTABLE_LABEL,
|
||||
classNamespace, SourceType.ANALYSIS);
|
||||
vtableSymbols.add(vtableSymbol);
|
||||
|
||||
api.setPlateComment(vtableAddress, "vtable for " + classNamespace.getName(true));
|
||||
}
|
||||
|
@ -631,16 +614,10 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
if (namespacesByPath.isEmpty()) {
|
||||
|
||||
try {
|
||||
Namespace newNamespace =
|
||||
NamespaceUtils.createNamespaceHierarchy(name, vtableNamespace,
|
||||
program, SourceType.ANALYSIS);
|
||||
return newNamespace;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
Namespace newNamespace = NamespaceUtils.createNamespaceHierarchy(name, vtableNamespace,
|
||||
program, SourceType.ANALYSIS);
|
||||
return newNamespace;
|
||||
|
||||
}
|
||||
if (namespacesByPath.size() == 1) {
|
||||
return namespacesByPath.get(0);
|
||||
|
@ -684,8 +661,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
// check direct refs to see if they are in undefined area or not in function
|
||||
byte[] bytes = ProgramMemoryUtil.getDirectAddressBytes(program, typeinfoAddress);
|
||||
|
||||
addByteSearchPattern(searcher, validTypeinfoRefs, typeinfoAddress, bytes,
|
||||
monitor);
|
||||
addByteSearchPattern(searcher, validTypeinfoRefs, typeinfoAddress, bytes, monitor);
|
||||
|
||||
}
|
||||
searcher.search(program, searchSet, monitor);
|
||||
|
@ -780,10 +756,10 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* @param vtableNamespace the namespace of the given vtable
|
||||
* @param isPrimary true if the vtable is the primary one for the class
|
||||
* @param listOfAllVtables list of all vtables
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private void processVtable(Address vtableAddress, Namespace vtableNamespace, boolean isPrimary,
|
||||
List<Symbol> listOfAllVtables)
|
||||
throws Exception {
|
||||
List<Symbol> listOfAllVtables) throws CancelledException, Exception {
|
||||
|
||||
// skip the special tables
|
||||
if (vtableAddress.equals(class_type_info_vtable) ||
|
||||
|
@ -818,13 +794,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
Data typeinfoPtr = api.getDataAt(typeinfoAddress);
|
||||
if (typeinfoPtr == null) {
|
||||
DataType nullPointer = dataTypeManager.getPointer(null);
|
||||
try {
|
||||
api.createData(typeinfoAddress, nullPointer);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.debug(this,
|
||||
"Could not create typeinfo pointer at " + typeinfoAddress.toString());
|
||||
}
|
||||
|
||||
api.createData(typeinfoAddress, nullPointer);
|
||||
|
||||
}
|
||||
|
||||
// if not already named a construction-vtable then check to see if it is one so it can
|
||||
|
@ -850,33 +822,19 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
Namespace classNamespace = createConstructionNamespace(vtableSymbol,
|
||||
vttSymbolBeforeConstructionVtable);
|
||||
|
||||
try {
|
||||
vtableSymbol.setNameAndNamespace("construction-vtable",
|
||||
classNamespace, SourceType.ANALYSIS);
|
||||
vtableNamespace = vtableSymbol.getParentNamespace();
|
||||
// label the subVTTaddress
|
||||
symbolTable.createLabel(subVTTAddress, "subVTT_" + n,
|
||||
vttSymbolBeforeConstructionVtable.getParentNamespace(),
|
||||
SourceType.ANALYSIS);
|
||||
vtableSymbol.setNameAndNamespace("construction-vtable", classNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
vtableNamespace = vtableSymbol.getParentNamespace();
|
||||
// label the subVTTaddress
|
||||
symbolTable.createLabel(subVTTAddress, "subVTT_" + n,
|
||||
vttSymbolBeforeConstructionVtable.getParentNamespace(),
|
||||
SourceType.ANALYSIS);
|
||||
|
||||
api.setPlateComment(vtableAddress, "construction vtable " + n +
|
||||
" for class " +
|
||||
api.setPlateComment(vtableAddress,
|
||||
"construction vtable " + n + " for class " +
|
||||
vttSymbolBeforeConstructionVtable.getParentNamespace()
|
||||
.getName(
|
||||
true));
|
||||
.getName(true));
|
||||
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this, e.getMessage());
|
||||
continue;
|
||||
}
|
||||
catch (CircularDependencyException e) {
|
||||
Msg.debug(this, e.getMessage());
|
||||
continue;
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -919,25 +877,10 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
vftableLabel = "internal_" + vftableLabel;
|
||||
}
|
||||
|
||||
try {
|
||||
symbolTable.createLabel(possibleVftableAddress, vftableLabel, vtableNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
symbolTable.createLabel(possibleVftableAddress, vftableLabel, vtableNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
|
||||
createVftableArray(possibleVftableAddress, numFunctionPointers);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Msg.debug(this, "Could not label vftable at " + possibleVftableAddress.toString());
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this, "Could not label vftable at " + possibleVftableAddress.toString());
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
return;
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
Msg.debug(this, "Couldn't create vftable due to Address out of bounds issue");
|
||||
return;
|
||||
}
|
||||
createVftableArray(possibleVftableAddress, numFunctionPointers);
|
||||
|
||||
// check for an internal vtable after the vftable and make a symbol there if there is one
|
||||
// will process them later
|
||||
|
@ -1050,7 +993,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
private boolean createInternalVtable(Address possibleInternalVtableAddress,
|
||||
Namespace vtableNamespace) throws CancelledException {
|
||||
Namespace vtableNamespace) throws CancelledException, InvalidInputException, Exception {
|
||||
// check to see if it is a pointer and if so, it cannot be an internal vtable
|
||||
// as they contain at least one long
|
||||
Address pointer = getPointerToDefinedMemory(possibleInternalVtableAddress);
|
||||
|
@ -1071,27 +1014,12 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
(possibleInternalVtableSymbol.getSource() == SourceType.DEFAULT &&
|
||||
(isValidVtableStart(possibleInternalVtableAddress) ||
|
||||
isValidVftableStart(possibleInternalVtableAddress)))) {
|
||||
try {
|
||||
symbolTable.createLabel(possibleInternalVtableAddress,
|
||||
"internal_vtable_" + possibleInternalVtableAddress.toString(), vtableNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
processVtable(possibleInternalVtableAddress, vtableNamespace, false, null);
|
||||
return true;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Msg.debug(this, "Could not label internal vtable at " +
|
||||
possibleInternalVtableAddress.toString());
|
||||
return true; // still created vtable, just couldn't name it
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this, "Could not label internal vtable at " +
|
||||
possibleInternalVtableAddress.toString());
|
||||
return true; // still created vtable, just couldn't name it
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
symbolTable.createLabel(possibleInternalVtableAddress,
|
||||
"internal_vtable_" + possibleInternalVtableAddress.toString(), vtableNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
processVtable(possibleInternalVtableAddress, vtableNamespace, false, null);
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
|
@ -1102,8 +1030,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* @param classNamespace the given namespace
|
||||
* @param address the address of the potential VTT table
|
||||
* @return true if a valid VTT has been discovered and label created
|
||||
* @throws Exception if data creation results in an exception
|
||||
*/
|
||||
private boolean createVTT(Namespace classNamespace, Address address) {
|
||||
private boolean createVTT(Namespace classNamespace, Address address) throws Exception {
|
||||
|
||||
// get pointer at address
|
||||
Address pointer = getPointerToDefinedMemory(address);
|
||||
|
@ -1120,22 +1049,15 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
// if it is then create the VTT symbol and create pointer there
|
||||
try {
|
||||
symbolTable.createLabel(address, "VTT", classNamespace, SourceType.ANALYSIS);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Msg.debug(this, "Could not label VTT at " + address.toString());
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this, "Could not label VTT at " + address.toString());
|
||||
}
|
||||
|
||||
symbolTable.createLabel(address, "VTT", classNamespace, SourceType.ANALYSIS);
|
||||
|
||||
DataType nullPointer = dataTypeManager.getPointer(null);
|
||||
try {
|
||||
api.createData(pointer, nullPointer);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// already data there
|
||||
// already data there so don't try and overwrite it
|
||||
}
|
||||
|
||||
api.setPlateComment(address, "VTT for " + classNamespace.getName(true));
|
||||
|
@ -1144,7 +1066,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
private Data createVftableArray(Address vftableAddress, int numFunctionPointers)
|
||||
throws CancelledException, AddressOutOfBoundsException {
|
||||
throws Exception {
|
||||
|
||||
api.clearListing(vftableAddress,
|
||||
vftableAddress.add((numFunctionPointers * defaultPointerSize - 1)));
|
||||
|
@ -1152,14 +1074,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
DataType pointerDataType = dataTypeManager.getPointer(null);
|
||||
ArrayDataType vftableArrayDataType =
|
||||
new ArrayDataType(pointerDataType, numFunctionPointers, defaultPointerSize);
|
||||
try {
|
||||
Data vftableArrayData = api.createData(vftableAddress, vftableArrayDataType);
|
||||
return vftableArrayData;
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Data vftableArrayData = api.createData(vftableAddress, vftableArrayDataType);
|
||||
return vftableArrayData;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1349,35 +1266,25 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* @param vtableAddress the given special vtable address
|
||||
* @return the address of the typeinfo in the vtable if replace was successful, null otherwise
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws InvalidInputException if bad characters when creating label
|
||||
*/
|
||||
private Address createSpecialVtable(Address vtableAddress) throws CancelledException {
|
||||
private Address createSpecialVtable(Address vtableAddress)
|
||||
throws CancelledException, InvalidInputException {
|
||||
|
||||
Symbol vtableSymbol = symbolTable.getPrimarySymbol(vtableAddress);
|
||||
|
||||
api.clearListing(vtableAddress);
|
||||
try {
|
||||
int vtableLongs = createVtableLongs(vtableAddress);
|
||||
|
||||
if (vtableLongs > 0) {
|
||||
int vtableLongs = createVtableLongs(vtableAddress);
|
||||
|
||||
Address typeinfoAddress = vtableAddress.add(vtableLongs * defaultPointerSize);
|
||||
symbolTable.createLabel(typeinfoAddress, "typeinfo",
|
||||
vtableSymbol.getParentNamespace(), SourceType.ANALYSIS);
|
||||
return typeinfoAddress;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (vtableLongs > 0) {
|
||||
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
return null;
|
||||
Address typeinfoAddress = vtableAddress.add(vtableLongs * defaultPointerSize);
|
||||
symbolTable.createLabel(typeinfoAddress, "typeinfo", vtableSymbol.getParentNamespace(),
|
||||
SourceType.ANALYSIS);
|
||||
return typeinfoAddress;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1409,7 +1316,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
api.createData(address, pointer);
|
||||
Address referencedAddress = extraUtils.getSingleReferencedAddress(address);
|
||||
|
||||
// if it isn't valid, clear what we just created and increment to offset so
|
||||
// if it isn't a valid pointer, clear what we just created and increment to offset so
|
||||
// the next can be checked
|
||||
if (referencedAddress == null || !programAddressSet.contains(referencedAddress)) {
|
||||
api.clearListing(address);
|
||||
|
@ -1422,6 +1329,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
return numLongs;
|
||||
}
|
||||
}
|
||||
// if bump into existing data return the number found so far
|
||||
catch (Exception e) {
|
||||
return numLongs;
|
||||
}
|
||||
|
@ -1534,20 +1442,13 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
private Data applyTypeinfoStructure(Structure typeInfoStructure, Address typeinfoAddress)
|
||||
throws CancelledException, AddressOutOfBoundsException {
|
||||
throws CancelledException, AddressOutOfBoundsException, Exception {
|
||||
|
||||
api.clearListing(typeinfoAddress, typeinfoAddress.add(typeInfoStructure.getLength() - 1));
|
||||
Data newStructure;
|
||||
try {
|
||||
newStructure = api.createData(typeinfoAddress, typeInfoStructure);
|
||||
}
|
||||
catch (Exception e) {
|
||||
newStructure = null;
|
||||
}
|
||||
if (newStructure == null) {
|
||||
Msg.debug(this,
|
||||
"Could not create " + typeInfoStructure.getName() + " at " + typeinfoAddress);
|
||||
}
|
||||
|
||||
newStructure = api.createData(typeinfoAddress, typeInfoStructure);
|
||||
|
||||
return newStructure;
|
||||
}
|
||||
|
||||
|
@ -1560,14 +1461,14 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
try {
|
||||
numBases = api.getInt(typeinfoAddress.add(offsetOfNumBases));
|
||||
}
|
||||
// if there isn't enough memory to get the int then return null
|
||||
catch (MemoryAccessException | AddressOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// get or create the vmiClassTypeInfoStruct
|
||||
Structure vmiClassTypeinfoStructure =
|
||||
(Structure) dataTypeManager.getDataType(classDataTypesCategoryPath,
|
||||
VMI_CLASS_TYPE_INFO_STRUCTURE + numBases);
|
||||
Structure vmiClassTypeinfoStructure = (Structure) dataTypeManager
|
||||
.getDataType(classDataTypesCategoryPath, VMI_CLASS_TYPE_INFO_STRUCTURE + numBases);
|
||||
if (vmiClassTypeinfoStructure == null) {
|
||||
vmiClassTypeinfoStructure =
|
||||
createVmiClassTypeInfoStructure(baseClassTypeInfoStructure, numBases);
|
||||
|
@ -1575,7 +1476,8 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
return vmiClassTypeinfoStructure;
|
||||
}
|
||||
|
||||
private Symbol createDemangledTypeinfoSymbol(Address typeinfoAddress) {
|
||||
private Symbol createDemangledTypeinfoSymbol(Address typeinfoAddress)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
String mangledTypeinfo = getTypeinfoName(typeinfoAddress);
|
||||
if (mangledTypeinfo == null) {
|
||||
|
@ -1614,25 +1516,14 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
// create the new typeinfo symbol in the demangled namespace
|
||||
try {
|
||||
Symbol newSymbol = symbolTable.createLabel(typeinfoAddress, "typeinfo", classNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
return newSymbol;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.error(this,
|
||||
typeinfoAddress.toString() + " invalid input exception " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Msg.debug(this,
|
||||
typeinfoAddress.toString() + " illegal argument exception " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
Symbol newSymbol = symbolTable.createLabel(typeinfoAddress, "typeinfo", classNamespace,
|
||||
SourceType.ANALYSIS);
|
||||
return newSymbol;
|
||||
}
|
||||
|
||||
private Namespace createTypeinfoClassNamespace(String namespaceString) {
|
||||
private Namespace createTypeinfoClassNamespace(String namespaceString)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
int indexOfColons = namespaceString.indexOf("::");
|
||||
Namespace namespace = globalNamespace;
|
||||
|
@ -1659,20 +1550,14 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
return classNamespace;
|
||||
}
|
||||
|
||||
private Namespace getOrCreateNamespace(String namespaceName, Namespace parentNamespace) {
|
||||
private Namespace getOrCreateNamespace(String namespaceName, Namespace parentNamespace)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
Namespace namespace = symbolTable.getNamespace(namespaceName, parentNamespace);
|
||||
if (namespace == null) {
|
||||
try {
|
||||
namespace = symbolTable.createNameSpace(parentNamespace, namespaceName,
|
||||
SourceType.ANALYSIS);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// shouldn't happen since it only gets here if the symbol didn't exist in the first place
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
namespace =
|
||||
symbolTable.createNameSpace(parentNamespace, namespaceName, SourceType.ANALYSIS);
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
@ -1710,12 +1595,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
StringDataType sdt = new StringDataType();
|
||||
|
||||
String str;
|
||||
try {
|
||||
str = (String) sdt.getValue(buf, sdt.getDefaultSettings(), stringLen);
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
str = (String) sdt.getValue(buf, sdt.getDefaultSettings(), stringLen);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -1814,26 +1696,37 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the references to the special type infos that exist in the current program.
|
||||
* @return the references to the special type infos that exist in the current program
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private List<Address> getTypeinfoAddressesUsingSpecialTypeinfos() throws CancelledException {
|
||||
|
||||
List<Address> specialTypeinfoRefs = new ArrayList<Address>();
|
||||
|
||||
Reference[] refsToClassTypeinfo = api.getReferencesTo(class_type_info);
|
||||
for (Reference ref : refsToClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
if (class_type_info != null) {
|
||||
Reference[] refsToClassTypeinfo = api.getReferencesTo(class_type_info);
|
||||
for (Reference ref : refsToClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
}
|
||||
}
|
||||
|
||||
Reference[] refsToSiClassTypeinfo = api.getReferencesTo(si_class_type_info);
|
||||
for (Reference ref : refsToSiClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
if (si_class_type_info != null) {
|
||||
Reference[] refsToSiClassTypeinfo = api.getReferencesTo(si_class_type_info);
|
||||
for (Reference ref : refsToSiClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
}
|
||||
}
|
||||
|
||||
Reference[] refsToVmiClassTypeinfo = api.getReferencesTo(vmi_class_type_info);
|
||||
for (Reference ref : refsToVmiClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
if (vmi_class_type_info != null) {
|
||||
Reference[] refsToVmiClassTypeinfo = api.getReferencesTo(vmi_class_type_info);
|
||||
for (Reference ref : refsToVmiClassTypeinfo) {
|
||||
monitor.checkCanceled();
|
||||
specialTypeinfoRefs.add(ref.getFromAddress());
|
||||
}
|
||||
}
|
||||
|
||||
return specialTypeinfoRefs;
|
||||
|
@ -2153,8 +2046,10 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
//virtual base offset for the virtual base referenced (negative).
|
||||
long offset = (publicVirtualOffsetFlag & offsetMask) >> 8;
|
||||
|
||||
Msg.debug(this, "typeinfo " + typeinfoAddress + " base [" + i + "] isVirtual = " +
|
||||
isVirtual + " isPublic = " + isPublic + " offset = " + offset);
|
||||
if (DEBUG) {
|
||||
Msg.debug(this, "typeinfo " + typeinfoAddress + " base [" + i + "] isVirtual = " +
|
||||
isVirtual + " isPublic = " + isPublic + " offset = " + offset);
|
||||
}
|
||||
|
||||
// add order to parent and parent offset
|
||||
orderToParentMap.put(i, parentClass);
|
||||
|
@ -2232,8 +2127,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* correct data types. Also creates a type info symbol at the correct offset in the table.
|
||||
* @return true if all found tables have a typeinfo symbol created successfully
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws InvalidInputException if bad characters creating labels
|
||||
*/
|
||||
private boolean createSpecialVtables() throws CancelledException {
|
||||
private boolean createSpecialVtables() throws CancelledException, InvalidInputException {
|
||||
|
||||
class_type_info_vtable = findSpecialVtable("__cxxabiv1", "__class_type_info");
|
||||
class_type_info = null;
|
||||
|
@ -2517,8 +2413,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* Use information from RTTI Base class Arrays to create class hierarchy lists and maps
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private void createClassHierarchyListAndMapForGcc()
|
||||
throws CancelledException, Exception {
|
||||
private void createClassHierarchyListAndMapForGcc() throws CancelledException, Exception {
|
||||
|
||||
Iterator<RecoveredClass> recoveredClassIterator = recoveredClasses.iterator();
|
||||
while (recoveredClassIterator.hasNext()) {
|
||||
|
@ -2683,22 +2578,20 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
* address
|
||||
* @param start the starting address
|
||||
* @param end the ending address
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws Exception if data has conflict when created
|
||||
*/
|
||||
private void createLongs(Address start, Address end) {
|
||||
private void createLongs(Address start, Address end) throws CancelledException, Exception {
|
||||
|
||||
LongDataType longDT = new LongDataType();
|
||||
int offset = 0;
|
||||
Address address = start;
|
||||
while (address != null && !address.equals(end)) {
|
||||
try {
|
||||
api.clearListing(address);
|
||||
api.createData(address, longDT);
|
||||
offset += defaultPointerSize;
|
||||
address = getAddress(start, offset);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.clearListing(address, address.add(defaultPointerSize - 1));
|
||||
api.createData(address, longDT);
|
||||
offset += defaultPointerSize;
|
||||
address = getAddress(start, offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2868,9 +2761,10 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
// can't handle creating class data types for classes with virtual parents yet
|
||||
if (recoveredClass.inheritsVirtualAncestor()) {
|
||||
if (DEBUG) {
|
||||
Msg.debug(this, "Cannot create class data type for " +
|
||||
recoveredClass.getClassNamespace().getName(true) +
|
||||
" because it has virtual ancestors and we don't yet handle that use case.");
|
||||
Msg.debug(this,
|
||||
"Cannot create class data type for " +
|
||||
recoveredClass.getClassNamespace().getName(true) +
|
||||
" because it has virtual ancestors and we don't yet handle that use case.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2901,27 +2795,23 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||
// and class member data structure
|
||||
Structure classStruct = createSimpleClassStructure(recoveredClass, vfPointerDataTypes);
|
||||
|
||||
// check for DWARF -- if none add c/d/etc to class
|
||||
//TODO: if decide to replace dwarf data types then remove this check so the replaces
|
||||
// in the following methods can replace the dwarf data types
|
||||
if (!isDwarfLoaded) {
|
||||
|
||||
// Now that we have a class data type
|
||||
// name constructor and destructor functions and put into the class namespace
|
||||
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
||||
addDestructorsToClassNamespace(recoveredClass, classStruct);
|
||||
// Now that we have a class data type
|
||||
// name constructor and destructor functions and put into the class namespace
|
||||
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
||||
addDestructorsToClassNamespace(recoveredClass, classStruct);
|
||||
//TODO:
|
||||
// addNonThisDestructorsToClassNamespace(recoveredClass);
|
||||
// addVbaseDestructorsToClassNamespace(recoveredClass);
|
||||
// addVbtableToClassNamespace(recoveredClass);
|
||||
//
|
||||
//TODO:
|
||||
// // add secondary label on functions with inlined constructors or destructors
|
||||
// createInlinedConstructorComments(recoveredClass);
|
||||
// createInlinedDestructorComments(recoveredClass);
|
||||
// createIndeterminateInlineComments(recoveredClass);
|
||||
|
||||
// add label on constructor destructor functions that could not be determined which were which
|
||||
createIndeterminateLabels(recoveredClass, classStruct);
|
||||
}
|
||||
// add label on constructor destructor functions that could not be determined which were which
|
||||
createIndeterminateLabels(recoveredClass, classStruct);
|
||||
|
||||
|
||||
// This is done after the class structure is created and added to the dtmanager
|
||||
// because if done before the class structures are created
|
||||
|
|
|
@ -70,7 +70,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
public RTTIWindowsClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
|
||||
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
||||
boolean nameVFunctions, boolean isPDBLoaded, boolean replaceClassStructures,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
TaskMonitor monitor) throws Exception {
|
||||
|
||||
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVFunctions,
|
||||
isPDBLoaded, replaceClassStructures, monitor);
|
||||
|
@ -98,121 +98,98 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void fixUpProgram() {
|
||||
public void fixUpProgram() throws CancelledException, Exception {
|
||||
|
||||
if (ghidraVersion.compareTo("10.0") < 0) {
|
||||
try {
|
||||
fixUpRttiAnalysis();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
fixUpRttiAnalysis();
|
||||
|
||||
}
|
||||
// if there are undefined areas that reference vftables attempt to create functions
|
||||
// containing them
|
||||
List<Symbol> vftableSymbols;
|
||||
try {
|
||||
vftableSymbols = getListOfVftableSymbols();
|
||||
createMissingFunctions(vftableSymbols);
|
||||
}
|
||||
catch (CancelledException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
List<Symbol> vftableSymbols = getListOfVftableSymbols();
|
||||
|
||||
createMissingFunctions(vftableSymbols);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecoveredClass> createRecoveredClasses() {
|
||||
public List<RecoveredClass> createRecoveredClasses() throws Exception {
|
||||
|
||||
List<Symbol> vftableSymbols;
|
||||
try {
|
||||
vftableSymbols = getListOfVftableSymbols();
|
||||
|
||||
List<RecoveredClass> recoveredClasses =
|
||||
recoverClassesFromClassHierarchyDescriptors(vftableSymbols);
|
||||
vftableSymbols = getListOfVftableSymbols();
|
||||
|
||||
determineVftableOffsetsfromRTTI(recoveredClasses);
|
||||
List<RecoveredClass> recoveredClasses =
|
||||
recoverClassesFromClassHierarchyDescriptors(vftableSymbols);
|
||||
|
||||
// If no new classes have been recovered, no need to continue. Return out of script.
|
||||
if (recoveredClasses.isEmpty()) {
|
||||
determineVftableOffsetsfromRTTI(recoveredClasses);
|
||||
|
||||
return recoveredClasses;
|
||||
}
|
||||
|
||||
createCalledFunctionMap(recoveredClasses);
|
||||
|
||||
// figure out class hierarchies using either RTTI or vftable refs
|
||||
|
||||
monitor.setMessage("Assigning class inheritance and hierarchies");
|
||||
assignClassInheritanceAndHierarchies(recoveredClasses);
|
||||
|
||||
// Since PDB has applied so much information, use it to figure out the class member data 4
|
||||
// items (if it has them) and the constructors and destructors.
|
||||
if (isPDBLoaded) {
|
||||
monitor.setMessage(
|
||||
"Attempting to use pdb to assign class hierarchies and extend known pdb data " +
|
||||
"type information ...");
|
||||
|
||||
retrieveExistingClassStructures(recoveredClasses);
|
||||
|
||||
// assign constructors and destructors based on name
|
||||
assignConstructorsAndDestructorsUsingExistingName(recoveredClasses);
|
||||
}
|
||||
// otherwise figure everything out from scratch
|
||||
else {
|
||||
monitor.setMessage("Figuring out class method types");
|
||||
// println(
|
||||
// "Figuring out class method types (constructor, destructor, inline constructor, " +
|
||||
// "inline destructor, deleting destructor, clone) ...");
|
||||
processConstructorAndDestructors(recoveredClasses);
|
||||
|
||||
}
|
||||
|
||||
// create order of vftable in constructor map for each class that has a constructor so far
|
||||
createVftableOrderMap(recoveredClasses);
|
||||
|
||||
determineParentClassInfoFromBaseClassArray(recoveredClasses);
|
||||
|
||||
assignParentClassToVftables(recoveredClasses);
|
||||
|
||||
// using all the information found above, create the class structures, add the constructor,
|
||||
// destructor, vfunctions to class which finds the appropriate class structure and assigns
|
||||
// to "this" param
|
||||
//println("Creating class data types and applying class structures...");
|
||||
monitor.setMessage("Creating class data types and applying class structures");
|
||||
figureOutClassDataMembers(recoveredClasses);
|
||||
|
||||
if (USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS) {
|
||||
extraUtils.createShortenedTemplateNamesForClasses(recoveredClasses);
|
||||
}
|
||||
|
||||
createAndApplyClassStructures(recoveredClasses);
|
||||
|
||||
if (!isPDBLoaded) {
|
||||
// create better vftable labels for multi vftable classes
|
||||
updateMultiVftableLabels(recoveredClasses);
|
||||
//println("Removing erroneous FID namespaces and corresponding class data types");
|
||||
removeEmptyClassesAndStructures();
|
||||
}
|
||||
// If no new classes have been recovered, no need to continue. Return out of script.
|
||||
if (recoveredClasses.isEmpty()) {
|
||||
|
||||
return recoveredClasses;
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
|
||||
createCalledFunctionMap(recoveredClasses);
|
||||
|
||||
// figure out class hierarchies using either RTTI or vftable refs
|
||||
|
||||
monitor.setMessage("Assigning class inheritance and hierarchies");
|
||||
assignClassInheritanceAndHierarchies(recoveredClasses);
|
||||
|
||||
// Since PDB has applied so much information, use it to figure out the class member data 4
|
||||
// items (if it has them) and the constructors and destructors.
|
||||
if (isPDBLoaded) {
|
||||
monitor.setMessage(
|
||||
"Attempting to use pdb to assign class hierarchies and extend known pdb data " +
|
||||
"type information ...");
|
||||
|
||||
retrieveExistingClassStructures(recoveredClasses);
|
||||
|
||||
// assign constructors and destructors based on name
|
||||
assignConstructorsAndDestructorsUsingExistingName(recoveredClasses);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
// otherwise figure everything out from scratch
|
||||
else {
|
||||
monitor.setMessage("Figuring out class method types");
|
||||
// println(
|
||||
// "Figuring out class method types (constructor, destructor, inline constructor, " +
|
||||
// "inline destructor, deleting destructor, clone) ...");
|
||||
processConstructorAndDestructors(recoveredClasses);
|
||||
|
||||
}
|
||||
|
||||
// create order of vftable in constructor map for each class that has a constructor so far
|
||||
createVftableOrderMap(recoveredClasses);
|
||||
|
||||
determineParentClassInfoFromBaseClassArray(recoveredClasses);
|
||||
|
||||
assignParentClassToVftables(recoveredClasses);
|
||||
|
||||
// using all the information found above, create the class structures, add the constructor,
|
||||
// destructor, vfunctions to class which finds the appropriate class structure and assigns
|
||||
// to "this" param
|
||||
//println("Creating class data types and applying class structures...");
|
||||
monitor.setMessage("Creating class data types and applying class structures");
|
||||
figureOutClassDataMembers(recoveredClasses);
|
||||
|
||||
if (USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS) {
|
||||
extraUtils.createShortenedTemplateNamesForClasses(recoveredClasses);
|
||||
}
|
||||
|
||||
createAndApplyClassStructures(recoveredClasses);
|
||||
|
||||
if (!isPDBLoaded) {
|
||||
// create better vftable labels for multi vftable classes
|
||||
updateMultiVftableLabels(recoveredClasses);
|
||||
//println("Removing erroneous FID namespaces and corresponding class data types");
|
||||
removeEmptyClassesAndStructures();
|
||||
}
|
||||
|
||||
return recoveredClasses;
|
||||
|
||||
}
|
||||
|
||||
private boolean isVisualStudioOrClangPe() {
|
||||
|
@ -351,7 +328,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
continue;
|
||||
}
|
||||
|
||||
//println("Cannot create RTTI_CompleteObjectLocator at " + symbol.getAddress());
|
||||
Msg.debug(this, "Cannot create RTTI_CompleteObjectLocator at " + symbol.getAddress());
|
||||
|
||||
}
|
||||
return completeObjectLocatorSymbols;
|
||||
|
@ -417,7 +394,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
continue;
|
||||
}
|
||||
|
||||
//println("Cannot create RTTI_Base_Class_Descriptor at " + symbol.getAddress());
|
||||
Msg.debug(this, "Cannot create RTTI_Base_Class_Descriptor at " + symbol.getAddress());
|
||||
|
||||
}
|
||||
return baseClassDescriptorSymbols;
|
||||
|
@ -661,8 +638,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
continue;
|
||||
}
|
||||
|
||||
// println("Failed to create a baseClassDescArray structure at " +
|
||||
// baseClassArrayAddress.toString());
|
||||
Msg.debug(this, "Failed to create a baseClassDescArray structure at " +
|
||||
baseClassArrayAddress.toString());
|
||||
}
|
||||
return baseClassArrayAddresses;
|
||||
}
|
||||
|
@ -736,13 +713,14 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
Namespace classNamespace = completeObjectLocatorSymbol.getParentNamespace();
|
||||
if (classNamespace.equals(globalNamespace)) {
|
||||
//println("no class namespace for " + completeObjectLocatorAddress.toString());
|
||||
Msg.debug(this,
|
||||
"No class namespace for " + completeObjectLocatorAddress.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference[] referencesTo = extraUtils.getReferencesTo(completeObjectLocatorAddress);
|
||||
if (referencesTo.length == 0) {
|
||||
//println("no refs to " + completeObjectLocatorAddress.toString());
|
||||
Msg.debug(this, "No refs to " + completeObjectLocatorAddress.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -995,7 +973,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
* @throws Exception when cancelled
|
||||
*/
|
||||
private void determineVftableOffsetsfromRTTI(List<RecoveredClass> recoveredClasses)
|
||||
throws Exception {
|
||||
throws AddressOutOfBoundsException, Exception {
|
||||
|
||||
PointerDataType pointerDataType = new PointerDataType();
|
||||
|
||||
|
@ -1020,22 +998,16 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
Address colAddress = extraUtils.getReferencedAddress(ptrToColAddress, false);
|
||||
|
||||
if (colAddress == null) {
|
||||
// println(recoveredClass.getName() + " couldn't get referenced col from " +
|
||||
// ptrToColAddress.toString());
|
||||
Msg.debug(this, recoveredClass.getName() +
|
||||
" couldn't get referenced col from " + ptrToColAddress.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Address addressOfOffset = colAddress.add(4);
|
||||
Address addressOfOffset = colAddress.add(4);
|
||||
|
||||
int offset = extraUtils.getInt(addressOfOffset);
|
||||
int offset = extraUtils.getInt(addressOfOffset);
|
||||
|
||||
recoveredClass.addClassOffsetToVftableMapping(offset, vftableAddress);
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
// println(recoveredClass.getName() + "error getting offset at address " +
|
||||
// colAddress.toString() + " + 4");
|
||||
}
|
||||
recoveredClass.addClassOffsetToVftableMapping(offset, vftableAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1063,9 +1035,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
int inheritanceFlag = getClassInheritanceFlag(recoveredClass.getClassNamespace());
|
||||
if (inheritanceFlag == NONE) {
|
||||
// println(
|
||||
// "Could not get inheritance attribute from class hierarchy structure for " +
|
||||
// "class " + recoveredClass.getName());
|
||||
Msg.debug(this,
|
||||
"Could not get inheritance attribute from class hierarchy structure for " +
|
||||
"class " + recoveredClass.getName());
|
||||
recoveredClassesIterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
@ -1250,21 +1222,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
RTTI_CLASS_HIERARCHY_DESCRIPTOR_LABEL, classNamespace, false);
|
||||
|
||||
if (symbols.size() >= 1) {
|
||||
|
||||
try {
|
||||
return (extraUtils.getInt(symbols.get(0).getAddress().add(4)));
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// println("Could not get class inheritance flag at address " +
|
||||
// symbols.get(0).getAddress().toString());
|
||||
return NONE;
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
// println("Could not get class inheritance flag at address " +
|
||||
// symbols.get(0).getAddress().toString());
|
||||
return NONE;
|
||||
}
|
||||
return (extraUtils.getInt(symbols.get(0).getAddress().add(4)));
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
|
@ -1399,7 +1359,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
// this should never happen
|
||||
if (baseClassArray.size() != 1) {
|
||||
throw new Exception(
|
||||
recoveredClass.getName() + " has more than one base class array");
|
||||
recoveredClass.getName() + " has more than one RTTI base class array");
|
||||
}
|
||||
|
||||
Address baseClassArrayAddress = baseClassArray.get(0).getAddress();
|
||||
|
@ -1407,7 +1367,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
|
||||
if (!baseClassArrayData.isArray()) {
|
||||
throw new Exception(
|
||||
recoveredClass.getName() + " base class array is not an array data type");
|
||||
recoveredClass.getName() + " RTTI base class array is not an array data type " +
|
||||
baseClassArrayAddress.toString());
|
||||
|
||||
}
|
||||
|
||||
|
@ -2690,9 +2651,11 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
* @return the offset of the single virtual parent or null if there is not a single virtual parent
|
||||
* or if there is no mapping in the offset map for that parent
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws AddressOutOfBoundsException
|
||||
* @throws MemoryAccessException
|
||||
*/
|
||||
public Integer getSingleVirtualParentOffset(RecoveredClass recoveredClass)
|
||||
throws CancelledException {
|
||||
throws CancelledException, MemoryAccessException, AddressOutOfBoundsException {
|
||||
|
||||
List<RecoveredClass> virtualParentClasses = getVirtualParentClasses(recoveredClass);
|
||||
if (virtualParentClasses.size() != 1) {
|
||||
|
@ -2706,7 +2669,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
}
|
||||
|
||||
private Map<RecoveredClass, Integer> getBaseClassOffsetMap(RecoveredClass recoveredClass)
|
||||
throws CancelledException {
|
||||
throws CancelledException, MemoryAccessException, AddressOutOfBoundsException {
|
||||
|
||||
Map<RecoveredClass, Integer> parentOffsetMap = new HashMap<RecoveredClass, Integer>();
|
||||
|
||||
|
@ -2727,52 +2690,39 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
RecoveredClass baseClass =
|
||||
getClassFromBaseClassDescriptor(baseClassDescriptorAddress);
|
||||
if (baseClass == null) {
|
||||
// TODO: msg and return null
|
||||
continue;
|
||||
}
|
||||
|
||||
// Continue if the class has mult inh but base class is not on the parent list
|
||||
//TODO: possibly update to include all base classes
|
||||
if (!recoveredClass.getParentList().contains(baseClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int mdisp = api.getInt(baseClassDescriptorAddress.add(8));
|
||||
int pdisp = api.getInt(baseClassDescriptorAddress.add(12));
|
||||
int vdisp = api.getInt(baseClassDescriptorAddress.add(16));
|
||||
if (pdisp == -1) {
|
||||
|
||||
baseClassOffset = mdisp;
|
||||
}
|
||||
else {
|
||||
// else need to fill in the virtually inherited ones
|
||||
// get the offset of this base class in the class using the vbtable
|
||||
Address vbtableAddress = recoveredClass.getVbtableAddress();
|
||||
if (vbtableAddress == null) {
|
||||
Msg.error(this,
|
||||
"Cannot retrieve vbtable address so cannot create base class offset map for class " +
|
||||
recoveredClass.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
baseClassOffset =
|
||||
api.getInt(recoveredClass.getVbtableAddress().add(vdisp)) + pdisp;
|
||||
}
|
||||
|
||||
parentOffsetMap.put(baseClass, baseClassOffset);
|
||||
|
||||
RecoveredClass baseClass = getClassFromBaseClassDescriptor(baseClassDescriptorAddress);
|
||||
if (baseClass == null) {
|
||||
// TODO: return null?
|
||||
Msg.debug(this, "Could not get base class from baseClassDescriptor " +
|
||||
baseClassDescriptorAddress.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
catch (MemoryAccessException | AddressOutOfBoundsException e) {
|
||||
Msg.error(this,
|
||||
"Cannot create base class offset map for class " + recoveredClass.getName());
|
||||
return null;
|
||||
// Continue if the class has mult inh but base class is not on the parent list
|
||||
//TODO: possibly update to include all base classes
|
||||
if (!recoveredClass.getParentList().contains(baseClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int mdisp = api.getInt(baseClassDescriptorAddress.add(8));
|
||||
int pdisp = api.getInt(baseClassDescriptorAddress.add(12));
|
||||
int vdisp = api.getInt(baseClassDescriptorAddress.add(16));
|
||||
if (pdisp == -1) {
|
||||
baseClassOffset = mdisp;
|
||||
}
|
||||
else {
|
||||
// else need to fill in the virtually inherited ones
|
||||
// get the offset of this base class in the class using the vbtable
|
||||
Address vbtableAddress = recoveredClass.getVbtableAddress();
|
||||
if (vbtableAddress == null) {
|
||||
Msg.error(this,
|
||||
"Cannot retrieve vbtable address so cannot create base class offset map for class " +
|
||||
recoveredClass.getName());
|
||||
return null;
|
||||
}
|
||||
baseClassOffset = api.getInt(recoveredClass.getVbtableAddress().add(vdisp)) + pdisp;
|
||||
}
|
||||
parentOffsetMap.put(baseClass, baseClassOffset);
|
||||
}
|
||||
return parentOffsetMap;
|
||||
}
|
||||
|
@ -2885,9 +2835,11 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
* order to distinguish which base class the vftable is for.
|
||||
* @param recoveredClasses the list of RecoveredClass objects
|
||||
* @throws CancelledException if cancelled
|
||||
* @throws InvalidInputException if bad chars trying to label
|
||||
* @throws DuplicateNameException if duplicate name
|
||||
*/
|
||||
private void updateMultiVftableLabels(List<RecoveredClass> recoveredClasses)
|
||||
throws CancelledException {
|
||||
throws CancelledException, DuplicateNameException, InvalidInputException {
|
||||
|
||||
if (recoveredClasses.isEmpty()) {
|
||||
return;
|
||||
|
@ -2914,19 +2866,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||
if (!shortenedTemplateName.isBlank()) {
|
||||
baseClassName = shortenedTemplateName;
|
||||
}
|
||||
try {
|
||||
primarySymbol.setName("vftable_for_" + baseClassName,
|
||||
primarySymbol.getSource());
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// skip if it's already the correct name
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this,
|
||||
"Could not create vftable_for_" + baseClassName +
|
||||
" due to invalid input exeption at address " +
|
||||
vftableAddress.toString());
|
||||
}
|
||||
|
||||
primarySymbol.setName("vftable_for_" + baseClassName,
|
||||
primarySymbol.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,8 @@ public class RecoveredClassUtils {
|
|||
|
||||
public RecoveredClassUtils(Program program, ProgramLocation location, PluginTool tool,
|
||||
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
||||
boolean nameVunctions, boolean replaceClassStructures, TaskMonitor monitor) {
|
||||
boolean nameVunctions, boolean replaceClassStructures, TaskMonitor monitor)
|
||||
throws Exception {
|
||||
|
||||
this.monitor = monitor;
|
||||
this.program = program;
|
||||
|
@ -551,13 +552,13 @@ public class RecoveredClassUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Method to return reference to the class vftable in the given function
|
||||
* Method to return the first reference to the class vftable in the given function
|
||||
* @param recoveredClass the given class
|
||||
* @param function the given function
|
||||
* @return the reference to the class vftable in the given function or null if there isn't one
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
public Address getClassVftableReference(RecoveredClass recoveredClass,
|
||||
public Address getFirstClassVftableReference(RecoveredClass recoveredClass,
|
||||
Function function) throws CancelledException {
|
||||
|
||||
List<Address> vftableReferenceList = functionToVftableRefsMap.get(function);
|
||||
|
@ -566,6 +567,8 @@ public class RecoveredClassUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
Collections.sort(vftableReferenceList);
|
||||
|
||||
Iterator<Address> vftableRefs = vftableReferenceList.iterator();
|
||||
while (vftableRefs.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
|
@ -589,39 +592,6 @@ public class RecoveredClassUtils {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the vftable reference in the given function that corresponds to the given class
|
||||
* @param function the given function
|
||||
* @param recoveredClass the given class
|
||||
* @return the vftableRef address in the given function that corresponds to the given class
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
public Address getClassVftableRefInFunction(Function function, RecoveredClass recoveredClass)
|
||||
throws CancelledException {
|
||||
|
||||
List<Address> listOfClassRefsInFunction =
|
||||
getSortedListOfAncestorRefsInFunction(function, recoveredClass);
|
||||
|
||||
Iterator<Address> iterator = listOfClassRefsInFunction.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
Address classRef = iterator.next();
|
||||
Address vftableAddress = vftableRefToVftableMap.get(classRef);
|
||||
|
||||
// skip the ones that aren't vftable refs
|
||||
if (vftableAddress == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// return the first one that is a vftable ref to the given class
|
||||
RecoveredClass vftableClass = vftableToClassMap.get(vftableAddress);
|
||||
if (vftableClass.equals(recoveredClass)) {
|
||||
return classRef;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a sorted list of both vftable and call refs to ancestor classes of the given
|
||||
* class in the given function
|
||||
|
@ -3389,7 +3359,7 @@ public class RecoveredClassUtils {
|
|||
replaceClassStructure(destructorFunction, className, classStruct);
|
||||
}
|
||||
|
||||
destructorFunction.setReturnType(DataType.VOID, SourceType.ANALYSIS);
|
||||
destructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3445,7 +3415,7 @@ public class RecoveredClassUtils {
|
|||
classStruct);
|
||||
}
|
||||
|
||||
vbaseDestructorFunction.setReturnType(DataType.VOID, SourceType.ANALYSIS);
|
||||
vbaseDestructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3635,7 +3605,9 @@ public class RecoveredClassUtils {
|
|||
return true;
|
||||
}
|
||||
|
||||
//TODO: decide whether to replace dwarf or not
|
||||
if (categoryPath.contains("DWARF")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// test to see if the data type is an empty structure with "PlaceHolder Class Structure" in
|
||||
// the description
|
||||
|
@ -5146,25 +5118,12 @@ public class RecoveredClassUtils {
|
|||
while (inlinedDestructorIterator.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
Function destructorFunction = inlinedDestructorIterator.next();
|
||||
Address classVftableRef =
|
||||
getClassVftableRefInFunction(destructorFunction, recoveredClass);
|
||||
|
||||
//TODO: use this one instead if testing pans out
|
||||
Address otherWayRef = getClassVftableReference(recoveredClass, destructorFunction);
|
||||
Address classVftableRef = getFirstClassVftableReference(recoveredClass, destructorFunction);
|
||||
|
||||
if (classVftableRef == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: remove after testing
|
||||
if (!classVftableRef.equals(otherWayRef)) {
|
||||
if (DEBUG) {
|
||||
Msg.debug(this, recoveredClass.getName() + " function " +
|
||||
destructorFunction.getEntryPoint().toString() + " first ref: " +
|
||||
classVftableRef.toString() + " other way ref: " + otherWayRef.toString());
|
||||
}
|
||||
}
|
||||
|
||||
String markupString = classNamespace.getName(true) + "::~" + className;
|
||||
api.setPreComment(classVftableRef, "inlined destructor: " + markupString);
|
||||
|
||||
|
@ -5189,24 +5148,11 @@ public class RecoveredClassUtils {
|
|||
Function functionContainingInline = functionsContainingInlineIterator.next();
|
||||
|
||||
Address classVftableRef =
|
||||
getClassVftableRefInFunction(functionContainingInline, recoveredClass);
|
||||
//TODO: use this one if testing more progs gives same results
|
||||
Address otherWayRef =
|
||||
getClassVftableReference(recoveredClass, functionContainingInline);
|
||||
getFirstClassVftableReference(recoveredClass, functionContainingInline);
|
||||
|
||||
if (classVftableRef == null) {
|
||||
continue;
|
||||
}
|
||||
//TODO: remove after testing
|
||||
if (!classVftableRef.equals(otherWayRef)) {
|
||||
if (DEBUG) {
|
||||
Msg.debug(this,
|
||||
recoveredClass.getName() + " function " +
|
||||
functionContainingInline.getEntryPoint().toString() + " first ref: " +
|
||||
classVftableRef.toString() + " other way ref: " +
|
||||
otherWayRef.toString());
|
||||
}
|
||||
}
|
||||
|
||||
String markupString = "inlined constructor or destructor (approx location) for " +
|
||||
classNamespace.getName(true);
|
||||
|
@ -5419,22 +5365,11 @@ public class RecoveredClassUtils {
|
|||
// Type 4 inlined - inlined class c/d called from other than first function
|
||||
// either just vftable ref before operator delete or vftableref followed by parent call
|
||||
// before operator delete
|
||||
Address vftableReference = getFirstClassVftableReference(recoveredClass, virtualFunction);
|
||||
|
||||
Address vftableReference = getClassVftableReference(recoveredClass, virtualFunction);
|
||||
|
||||
//TODO remove after testing against prev method in more progs
|
||||
Address otherWayRef = getClassVftableRefInFunction(virtualFunction, recoveredClass);
|
||||
if (vftableReference == null) {
|
||||
return;
|
||||
}
|
||||
if (!vftableReference.equals(otherWayRef)) {
|
||||
if (DEBUG) {
|
||||
Msg.debug(this, recoveredClass.getName() + " function " +
|
||||
virtualFunction.getEntryPoint().toString() + " first ref: " +
|
||||
vftableReference.toString() + " other way ref (with ances): " +
|
||||
otherWayRef.toString());
|
||||
}
|
||||
}
|
||||
|
||||
List<Function> possibleParentDestructors = getPossibleParentDestructors(virtualFunction);
|
||||
|
||||
|
@ -5725,43 +5660,6 @@ public class RecoveredClassUtils {
|
|||
|
||||
}
|
||||
|
||||
private boolean isDataAtOffsetEquivalentToStructure(Structure outerStructure,
|
||||
Structure innerStructure, int offset) {
|
||||
|
||||
DataTypeComponent[] innerStructComponents = innerStructure.getDefinedComponents();
|
||||
for (DataTypeComponent innerComponent : innerStructComponents) {
|
||||
int innerOffset = innerComponent.getOffset();
|
||||
|
||||
DataTypeComponent outerComponent = outerStructure.getComponentAt(offset + innerOffset);
|
||||
if (outerComponent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (innerComponent.getFieldName().equals("vftablePtr")) {
|
||||
|
||||
// if one is vftablePtr and other isn't - return false
|
||||
if (!outerComponent.getFieldName().equals("vftablePtr")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if both are vftablePtrs they should both contain the innerStructure name (ie the class name) in
|
||||
// the vftablePtr data type name (either <some_class_name>_vftable_for_<innerStruct name> or <innerStruct name>_vftable *
|
||||
if (outerComponent.getDataType().getDisplayName().contains(
|
||||
innerStructure.getName()) &&
|
||||
!innerComponent.getDataType().getDisplayName().contains(
|
||||
innerStructure.getName())) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!innerComponent.getDataType().equals(outerComponent.getDataType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine if the given data type is the virtual parent class structure for the given class
|
||||
* @param recoveredClass the given class
|
||||
|
@ -6552,7 +6450,7 @@ public class RecoveredClassUtils {
|
|||
if (!atexitCalledFunctions.contains(calledFunction)) {
|
||||
atexitCalledFunctions.add(calledFunction);
|
||||
}
|
||||
calledFunction.setReturnType(DataType.VOID, SourceType.ANALYSIS);
|
||||
calledFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
||||
}
|
||||
else {
|
||||
if (!atexitCalledFunctions.contains(calledFunction)) {
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
# 1010 0100 ssss tttt # user_four rs rt user_four rs rt
|
||||
# 1010 0101 nnnn nnnn # user_five n user_five n
|
||||
# 1010 0110 ssss 0000 # user_six rs user_six rs
|
||||
# 1010 1000 0000 0000 # unimpl
|
||||
#
|
||||
#### RESERVED
|
||||
# 1101 1001 xxxx xxxx # RESERVED BANK
|
||||
|
@ -222,3 +223,4 @@ define pcodeop pcodeop_three;
|
|||
:user_five Rel8 is $(INSTR_PHASE) op1215=0xa & op0811=0x05 & Rel8 { lr = inst_next; call Rel8; pcodeop_three();}
|
||||
:user_six rs is $(INSTR_PHASE) op1215=0xa & op0811=0x06 & rs & op0003=0x0 { r1 = pcodeop_one(rs); call [r1];}
|
||||
|
||||
:unimpl is $(INSTR_PHASE) op1215=0xa & op0811=0x08 & op0007=0 unimpl
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue