Skip to content

Commit fe2ec55

Browse files
author
astrelsky
committed
Updated ghidra scripts
1 parent 4c95dea commit fe2ec55

File tree

5 files changed

+177
-219
lines changed

5 files changed

+177
-219
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ It is compatible with current builds of 9.2
7676
TODO
7777
----
7878

79-
Graphing, fix DynamicCaster script
79+
Graphing

developer_scripts/TestBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import cppclassanalyzer.data.ClassTypeInfoManager;
44
import cppclassanalyzer.data.ProgramClassTypeInfoManager;
5+
import cppclassanalyzer.utils.CppClassAnalyzerUtils;
56

67
import ghidra.app.script.GhidraScript;
78
import ghidra.app.cmd.data.rtti.gcc.builder.AbstractTypeInfoProgramBuilder;
@@ -367,7 +368,7 @@ private MemoryBlock getDataBlock() {
367368
}
368369

369370
private void populateMaps() throws Exception {
370-
ProgramClassTypeInfoManager manager = ClassTypeInfoUtils.getManager(currentProgram);
371+
ProgramClassTypeInfoManager manager = CppClassAnalyzerUtils.getManager(currentProgram);
371372
int pointerSize = currentProgram.getDefaultPointerSize();
372373
SymbolTable table = currentProgram.getSymbolTable();
373374
Listing listing = currentProgram.getListing();
Lines changed: 100 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,39 @@
1+
/**
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2019-2020 Andrew J. Strelsky
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*
24+
*/
25+
// Iterates through all vtable assignments and changes the assigned variable to
26+
// the appropriate class datatype.
127
//@category CppClassAnalyzer
2-
import static ghidra.app.cmd.data.rtti.gcc.factory.TypeInfoFactory.getTypeInfo;
3-
4-
import java.util.LinkedList;
28+
//@author Andrew J. Strelsky
29+
import java.util.Arrays;
530
import java.util.List;
31+
import java.util.Objects;
32+
import java.util.stream.Collectors;
633

7-
import ghidra.app.cmd.data.rtti.ClassTypeInfo;
8-
import ghidra.app.cmd.data.rtti.TypeInfo;
934
import ghidra.app.cmd.data.rtti.Vtable;
10-
import ghidra.app.script.GhidraScript;
1135
import ghidra.program.model.address.Address;
12-
import ghidra.program.model.data.InvalidDataTypeException;
36+
import ghidra.program.model.data.DataType;
1337
import ghidra.program.model.data.Structure;
1438
import ghidra.program.model.lang.Register;
1539
import ghidra.program.model.listing.Function;
@@ -19,90 +43,92 @@
1943
import ghidra.program.model.symbol.Reference;
2044
import ghidra.program.model.symbol.ReferenceManager;
2145
import ghidra.program.model.symbol.SourceType;
22-
import ghidra.program.model.symbol.Symbol;
23-
import ghidra.program.model.symbol.SymbolTable;
2446

25-
public class ClassReferences extends GhidraScript {
47+
import cppclassanalyzer.script.CppClassAnalyzerGhidraScript;
48+
49+
public class ClassReferences extends CppClassAnalyzerGhidraScript {
50+
51+
private int count;
2652

2753
@Override
2854
public void run() throws Exception {
2955
println("This script is currently in development and may not function properly");
30-
SymbolTable table = currentProgram.getSymbolTable();
31-
List<Vtable> vftables = new LinkedList<>();
32-
List<Symbol> symbols = new LinkedList<>();
33-
table.getSymbols(TypeInfo.SYMBOL_NAME).forEach(symbols::add);
34-
monitor.initialize(symbols.size());
35-
monitor.setMessage("Locating Vtables");
36-
for (Symbol symbol : symbols) {
56+
57+
count = 0;
58+
List<Vtable> vftables = currentManager.getVtableStream()
59+
.collect(Collectors.toList());
60+
monitor.setMessage("Setting variable datatypes");
61+
monitor.initialize(vftables.size());
62+
for (Vtable vtable : vftables) {
3763
monitor.checkCanceled();
38-
TypeInfo ti = getTypeInfo(currentProgram, symbol.getAddress());
39-
try {
40-
ti.validate();
41-
if (ti instanceof ClassTypeInfo) {
42-
Vtable vtable = ((ClassTypeInfo) ti).getVtable();
43-
vtable.validate();
44-
vftables.add(vtable);
45-
}
46-
} catch (InvalidDataTypeException e) {}
64+
processVtable(vtable);
4765
monitor.incrementProgress(1);
4866
}
49-
createClassReferences(vftables);
67+
println("Created "+Integer.toString(count)+" class variable references.");
5068
}
5169

52-
private void createClassReferences(List<Vtable> vftables) throws Exception {
53-
int count = 0;
70+
private void processVtable(Vtable vtable) throws Exception {
71+
Address vtableAddress = vtable.getTableAddresses()[0];
5472
ReferenceManager manager = currentProgram.getReferenceManager();
55-
Listing listing = currentProgram.getListing();
56-
monitor.initialize(vftables.size());
57-
monitor.setMessage("Setting variable datatypes");
58-
for (Vtable vtable : vftables) {
73+
for (Reference ref : manager.getReferencesTo(vtableAddress)) {
5974
monitor.checkCanceled();
60-
Address vtableAddress = vtable.getTableAddresses()[0];
61-
VariableSetting:
62-
for (Reference ref : manager.getReferencesTo(vtableAddress)) {
63-
monitor.checkCanceled();
64-
if (manager.getReferencedVariable(ref) != null) {
65-
Variable var = manager.getReferencedVariable(ref);
66-
if (!(var.getDataType() instanceof Structure)) {
67-
var.setDataType(vtable.getTypeInfo().getClassDataType(),
68-
true, true, SourceType.ANALYSIS);
69-
count++;
70-
continue;
71-
}
72-
}
73-
Instruction inst = listing.getInstructionAt(ref.getFromAddress());
74-
if (inst == null) {
75-
continue;
76-
}
77-
Function function = listing.getFunctionContaining(inst.getAddress());
78-
if (function == null) {
75+
if (manager.getReferencedVariable(ref) != null) {
76+
Variable var = manager.getReferencedVariable(ref);
77+
if (!(var.getDataType() instanceof Structure)) {
78+
var.setDataType(vtable.getTypeInfo().getClassDataType(),
79+
true, true, SourceType.ANALYSIS);
80+
count++;
7981
continue;
8082
}
81-
Object[] objects = inst.getInputObjects();
82-
if (!(objects[0] instanceof Register)) {
83-
continue;
83+
}
84+
ReferenceProcessor processor = new ReferenceProcessor(vtable, ref);
85+
processor.process();
86+
}
87+
}
88+
89+
private class ReferenceProcessor {
90+
91+
private final Vtable vtable;
92+
private Instruction inst;
93+
private Function function;
94+
95+
ReferenceProcessor(Vtable vtable, Reference ref) {
96+
this.vtable = vtable;
97+
Listing listing = currentProgram.getListing();
98+
this.inst = listing.getInstructionAt(ref.getFromAddress());
99+
if (inst != null) {
100+
this.function = listing.getFunctionContaining(inst.getAddress());
101+
}
102+
}
103+
104+
void process() throws Exception {
105+
if (inst == null || function == null) {
106+
return;
107+
}
108+
ReferenceManager manager = currentProgram.getReferenceManager();
109+
Reference[] refs = inst.getReferencesFrom();
110+
Variable var = Arrays.stream(refs)
111+
.map(manager::getReferencedVariable)
112+
.filter(Objects::nonNull)
113+
.findFirst()
114+
.orElse(null);
115+
if (var != null) {
116+
DataType dt = vtable.getTypeInfo().getClassDataType();
117+
DataType varDt = var.getDataType();
118+
if (varDt.isEquivalent(dt) || varDt.dependsOn(dt)) {
119+
return;
84120
}
85-
Register register = (Register) objects[0];
86-
inst = inst.getNext();
87-
while (function.getBody().contains(inst.getAddress())) {
88-
monitor.checkCanceled();
89-
if (inst.getRegister(0) != null && inst.getRegister(0).contains(register)) {
90-
Reference[] refs = inst.getReferencesFrom();
91-
if (refs.length == 1 && !refs[0].isOffsetReference() && refs[0].isStackReference()) {
92-
Variable var = manager.getReferencedVariable(refs[0]);
93-
if (var != null) {
94-
var.setDataType(vtable.getTypeInfo().getClassDataType(),
95-
true, true, SourceType.ANALYSIS);
96-
count++;
97-
continue VariableSetting;
98-
}
99-
}
100-
}
101-
inst = inst.getNext();
121+
var.setDataType(dt, true, true, SourceType.ANALYSIS);
122+
Address addr = var.getMinAddress();
123+
if (addr != null) {
124+
String msg = String.format(
125+
"Set variable %s at %s to %s",
126+
var, inst.getAddress(), dt.getDataTypePath());
127+
println(msg);
102128
}
129+
count++;
130+
return;
103131
}
104-
monitor.incrementProgress(1);
105132
}
106-
println("Created "+Integer.toString(count)+" class variabled references.");
107133
}
108134
}

0 commit comments

Comments
 (0)