GP-972 Improvements to Gcc RTTI Class Recovery

This commit is contained in:
ghidra007 2021-06-10 14:19:33 -04:00 committed by ghidra1
parent c553971388
commit e1953ebb22
7 changed files with 652 additions and 254 deletions

View file

@ -35,18 +35,20 @@
// 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 have not been recovered yet but if the program
// has DWARF, there will be some amount of data recovered by the DWARF analyzer in the DWARF data folder.
// in early stages of development. Gcc class data types are only recovered for classes without multiple or
// 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
// done on user marked-up programs.
// NOTE: After running this script if you edit function signatures in the listing for a particular
// class and wish to update the corresponding class data (function definition data types, vftable
// class and wish to update the corresponding class data function definition data types (vftable
// structure field names, ...) then you can run the ApplyClassFunctionSignatureUpdatesScript.java
// to have it do so for you.
// to have it do so for you. See that script's description for more info.
// Conversely, if you update a particular class's function definitions in the data type manager and
// wish to have related function signatures in the listing updated, as well as other data types that
// are related, then run the ApplyClassFunctionDefinitionsUpdatesScript.java to do so. At some point,
// the Ghidra API will be updated to do this all automatically instead of needing the scripts to do so.
// are related, then run the ApplyClassFunctionDefinitionsUpdatesScript.java to do so. See that script's
// description for more info. At some point, the Ghidra API will be updated to do the updates
// automatically instead of needing the mentioned scripts to do so.
//@category C++
@ -152,6 +154,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
if (isWindows()) {
isPDBLoaded = isPDBLoadedInProgram();
nameVfunctions = !isPDBLoaded;
recoverClassesFromRTTI = new RTTIWindowsClassRecoverer(currentProgram,
@ -159,7 +162,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, isPDBLoaded, monitor);
}
else if (isGcc()) {
// for now assume gcc has named vfunctions until a way to check is developed
nameVfunctions = true;
recoverClassesFromRTTI = new RTTIGccClassRecoverer(currentProgram, currentLocation,
state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
@ -176,7 +179,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
return;
}
// possibly more picky subtype than just checking windows/gcc
if (!recoverClassesFromRTTI.isValidProgramType()) {
println("This script will not work on this program type");
return;
@ -465,9 +467,41 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
*/
private boolean isGcc() {
isGcc =
boolean isELF = currentProgram.getExecutableFormat().contains("ELF");
if (!isELF) {
return false;
}
boolean isCompilerSpecGcc =
currentProgram.getCompilerSpec().getCompilerSpecID().getIdAsString().equalsIgnoreCase(
"gcc");
if (isCompilerSpecGcc) {
return true;
}
MemoryBlock commentBlock = currentProgram.getMemory().getBlock(".comment");
if (commentBlock == null) {
return false;
}
if (!commentBlock.isLoaded()) {
return false;
}
// check memory bytes in block for GCC: bytes
byte[] gccBytes = { (byte) 0x47, (byte) 0x43, (byte) 0x43, (byte) 0x3a };
byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
Address found = currentProgram.getMemory().findBytes(commentBlock.getStart(),
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
if (found == null) {
isGcc = false;
}
else {
isGcc = true;
}
return isGcc;
}