-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCreateTypeInfoStructs.java
More file actions
170 lines (150 loc) · 6.31 KB
/
CreateTypeInfoStructs.java
File metadata and controls
170 lines (150 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// CreateTypeInfoStructs.java
// Ghidra Script: Creates __cxxabiv1 RTTI structs if they do not already exist.
//
// Creates the following in /abi/__cxxabiv1:
// - __base_class_type_info (used inside __vmi_class_type_info arrays)
// - __class_type_info (leaf classes, no bases)
// - __si_class_type_info (single, public, non-virtual inheritance)
// - __vmi_class_type_info (1 base)
// - __vmi_class_type_info (2 bases)
// - __vmi_class_type_info (3 bases)
//
// These match the Itanium C++ ABI as used by ARMCC 4.1.
// All pointer fields use the program's default pointer size.
//
// @category RTTI
// @author Claude (for AlgebraManiacABC)
import ghidra.app.script.GhidraScript;
import ghidra.program.model.data.*;
public class CreateTypeInfoStructs extends GhidraScript {
private DataTypeManager dtm;
@Override
public void run() throws Exception {
dtm = currentProgram.getDataTypeManager();
int txId = dtm.startTransaction("Create __cxxabiv1 typeinfo structs");
try {
createBaseClassTypeInfo();
createClassTypeInfo();
createSiClassTypeInfo();
createVmiClassTypeInfo(1);
createVmiClassTypeInfo(2);
createVmiClassTypeInfo(3);
println("Done. All __cxxabiv1 typeinfo structs created or already present.");
} finally {
dtm.endTransaction(txId, true);
}
}
/**
* Returns the category path /type_info.
*/
private CategoryPath getCategoryPath() {
return new CategoryPath("/type_info");
}
/**
* Checks whether a struct with the given name already exists under the category.
* If it does, prints a message and returns true.
*/
private boolean alreadyExists(String name) {
DataType existing = dtm.getDataType(getCategoryPath(), name);
if (existing != null) {
println(" SKIP: " + name + " already exists.");
return true;
}
return false;
}
/**
* Resolves a struct into the DTM (adds or returns existing equivalent).
*/
private DataType resolve(StructureDataType s) {
DataType resolved = dtm.resolve(s, DataTypeConflictHandler.REPLACE_HANDLER);
println(" OK: " + s.getName());
return resolved;
}
/**
* Returns a pointer type using the program's default pointer size.
*/
private PointerDataType ptr(DataType dt) {
return new PointerDataType(dt, currentProgram.getDefaultPointerSize());
}
// -----------------------------------------------------------------
// __base_class_type_info
//
// struct __base_class_type_info {
// const __class_type_info *__base_type;
// long __offset_flags;
// };
// -----------------------------------------------------------------
private void createBaseClassTypeInfo() {
String name = "__base_class_type_info";
if (alreadyExists(name)) return;
// Forward-reference: __class_type_info may not exist yet.
// Use a void* for the pointer target; user can refine later.
StructureDataType s = new StructureDataType(getCategoryPath(), name, 0);
s.add(ptr(DataType.VOID), "__base_type", "const __class_type_info *");
s.add(LongDataType.dataType, "__offset_flags", "offset and info bitfield");
resolve(s);
}
// -----------------------------------------------------------------
// __class_type_info (no bases)
//
// struct __class_type_info {
// void *__vtable_ptr;
// const char *__name;
// };
// -----------------------------------------------------------------
private void createClassTypeInfo() {
String name = "__class_type_info";
if (alreadyExists(name)) return;
StructureDataType s = new StructureDataType(getCategoryPath(), name, 0);
s.add(ptr(DataType.VOID), "__vtable_ptr", "typeinfo vtable pointer");
s.add(ptr(CharDataType.dataType), "__name", "mangled name");
resolve(s);
}
// -----------------------------------------------------------------
// __si_class_type_info (single non-virtual public base)
//
// struct __si_class_type_info {
// void *__vtable_ptr;
// const char *__name;
// const __class_type_info *__base_type;
// };
// -----------------------------------------------------------------
private void createSiClassTypeInfo() {
String name = "__si_class_type_info";
if (alreadyExists(name)) return;
StructureDataType s = new StructureDataType(getCategoryPath(), name, 0);
s.add(ptr(DataType.VOID), "__vtable_ptr", "typeinfo vtable pointer");
s.add(ptr(CharDataType.dataType), "__name", "mangled name");
s.add(ptr(DataType.VOID), "__base_type", "const __class_type_info *");
resolve(s);
}
// -----------------------------------------------------------------
// __vmi_class_type_info (N bases)
//
// struct __vmi_class_type_info {
// void *__vtable_ptr;
// const char *__name;
// unsigned int __flags;
// unsigned int __base_count;
// __base_class_type_info __base_info[N];
// };
// -----------------------------------------------------------------
private void createVmiClassTypeInfo(int baseCount) {
String name = "__vmi_class_type_info_" + baseCount;
if (alreadyExists(name)) return;
// Look up __base_class_type_info (should exist by now)
DataType baseClassTI = dtm.getDataType(getCategoryPath(), "__base_class_type_info");
if (baseClassTI == null) {
printerr("ERROR: __base_class_type_info not found. Cannot create " + name);
return;
}
StructureDataType s = new StructureDataType(getCategoryPath(), name, 0);
s.add(ptr(DataType.VOID), "__vtable_ptr", "typeinfo vtable pointer");
s.add(ptr(CharDataType.dataType), "__name", "mangled name");
s.add(UnsignedIntegerDataType.dataType, "__flags", "diamond / non-diamond flags");
s.add(UnsignedIntegerDataType.dataType, "__base_count", "number of direct bases");
ArrayDataType baseArray = new ArrayDataType(baseClassTI, baseCount, baseClassTI.getLength());
s.add(baseArray, "__base_info", "__base_class_type_info[" + baseCount + "]");
resolve(s);
}
}