Skip to content

Commit

Permalink
GP-4376 Updated gcc class recovery to allow for special typeinfos that
Browse files Browse the repository at this point in the history
are not in program memory or external block. Also updated to add a check
for unhandled relocations. Also updated to allow for non-mangled
typeinfo-name strings.
  • Loading branch information
ghidra007 committed Apr 4, 2024
1 parent 3e35b4d commit b04d533
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.reloc.Relocation;
import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationTable;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.GhidraProgramUtilities;
Expand Down Expand Up @@ -210,8 +211,7 @@ else if (isPE() && isGcc()) {
if (!runGcc) {
return;
}
//run fixup old elf relocations script
runScript("FixElfExternalOffsetDataRelocationScript.java");

recoverClassesFromRTTI = new RTTIGccClassRecoverer(currentProgram, state.getTool(),
this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
nameVfunctions, hasDebugSymbols, monitor);
Expand All @@ -232,9 +232,6 @@ else if (isGcc()) {
return;
}

//run fixup old elf relocations script
runScript("FixElfExternalOffsetDataRelocationScript.java");

hasDebugSymbols = isDwarfLoadedInProgram();
if (hasDwarf() && !hasDebugSymbols) {
println(
Expand Down Expand Up @@ -379,7 +376,7 @@ private boolean isDwarfLoadedInProgram() {
DWARFProgram.DWARF_ROOT_NAME) || options.getBoolean("DWARF Loaded", false));
}

public String validate() throws CancelledException {
public String validate() throws Exception {

if (currentProgram == null) {
return ("There is no open program");
Expand Down Expand Up @@ -417,6 +414,8 @@ public String validate() throws CancelledException {
// check that gcc loader or mingw analyzer has fixed the relocations correctly
if (isGcc()) {

runScript("FixElfExternalOffsetDataRelocationScript.java");

// first check that there is even rtti by searching the special string in memory
if (!isStringInProgramMemory("class_type_info")) {
return ("This program does not contain RTTI.");
Expand All @@ -432,7 +431,7 @@ public String validate() throws CancelledException {
"contact the Ghidra team so this issue can be fixed.");
}

if (hasUnhandledRelocations()) {
if (hasRelocationIssue()) {
return ("This program has unhandled elf relocations so cannot continue. Please " +
"contact the Ghidra team for assistance.");
}
Expand All @@ -442,7 +441,13 @@ public String validate() throws CancelledException {

}

private boolean hasUnhandledRelocations() throws CancelledException {
/**
* Method to determine if the gcc relocations needed to find the special typeinfos/vtables
* have any issues that would keep script from running correctly.
* @return true if there are any issues with the relocations, false otherwise
* @throws CancelledException if cancelled
*/
private boolean hasRelocationIssue() throws CancelledException {

RelocationTable relocationTable = currentProgram.getRelocationTable();

Expand All @@ -452,17 +457,39 @@ private boolean hasUnhandledRelocations() throws CancelledException {
monitor.checkCancelled();
Relocation r = relocations.next();

if (r.getSymbolName().contains("class_type_info") &&
(r.getStatus() != Relocation.Status.APPLIED &&
r.getStatus() != Relocation.Status.APPLIED_OTHER &&
r.getStatus() != Relocation.Status.SKIPPED)) {
return true;
}
String symbolName = r.getSymbolName();

if (symbolName != null && symbolName.contains("class_type_info")) {

Status status = r.getStatus();

// if any relocations for special typeinfo class symbols have failed then there
// is an issue
if (status == Status.FAILURE) {
return true;
}

// if any relocations for special typeinfo class symbols are unsupported then
// determine where the symbol is located before determining if it is an issue
if(status == Status.UNSUPPORTED) {

//if relocation symbol is the same as the symbol at the relcation address
//then this situation is not an issue - it indicates a copy relocation at the
//location of the special typeinfo vtable which is a use case that can be handled
Address address = r.getAddress();
Symbol symbolAtAddress = currentProgram.getSymbolTable().getSymbol(symbolName, address, currentProgram.getGlobalNamespace());
if(symbolAtAddress != null) {
continue;
}
return true;
}

}
}
return false;
}


private void analyzeProgramChanges(AddressSetView beforeChanges) throws Exception {

AddressSetView addressSet = currentProgram.getChanges().getAddressSet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
*/
package classrecovery;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

import ghidra.program.model.address.Address;
import ghidra.program.model.symbol.Namespace;
Expand All @@ -30,7 +27,7 @@ public class GccTypeinfo extends Typeinfo {
private static final String VMI_CLASS_TYPEINFO_NAMESPACE = "__vmi_class_type_info";

boolean isSpecialTypeinfo;
GccTypeinfo inheritedSpecialTypeinfo = null;
Namespace inheritedSpecialTypeinfoNamespace = null;
Address vtableAddress;
boolean inProgramMemory;
String mangledNamespaceString = null;
Expand All @@ -53,13 +50,13 @@ public boolean isInProgramMemory() {
return inProgramMemory;
}

public void setInheritedSpecialTypeinfo(GccTypeinfo specialTypeinfo) {
inheritedSpecialTypeinfo = specialTypeinfo;
public void setInheritedSpecialTypeinfoNamespace(Namespace specialTypeinfoNamespace) {
inheritedSpecialTypeinfoNamespace = specialTypeinfoNamespace;
}


public GccTypeinfo getInheritedSpecialTypeinfo() {
return inheritedSpecialTypeinfo;
public Namespace getInheritedSpecialTypeinfoNamespace() {
return inheritedSpecialTypeinfoNamespace;
}


Expand Down Expand Up @@ -156,21 +153,21 @@ public long getInheritanceFlagValue() {
}

public boolean isClassTypeinfo() {
if(inheritedSpecialTypeinfo.getNamespace().getName().equals(CLASS_TYPEINFO_NAMESPACE)) {
if (inheritedSpecialTypeinfoNamespace.getName().equals(CLASS_TYPEINFO_NAMESPACE)) {
return true;
}
return false;
}

public boolean isSiClassTypeinfo() {
if(inheritedSpecialTypeinfo.getNamespace().getName().equals(SI_CLASS_TYPEINFO_NAMESPACE)) {
if (inheritedSpecialTypeinfoNamespace.getName().equals(SI_CLASS_TYPEINFO_NAMESPACE)) {
return true;
}
return false;
}

public boolean isVmiClassTypeinfo() {
if(inheritedSpecialTypeinfo.getNamespace().getName().equals(VMI_CLASS_TYPEINFO_NAMESPACE)) {
if (inheritedSpecialTypeinfoNamespace.getName().equals(VMI_CLASS_TYPEINFO_NAMESPACE)) {
return true;
}
return false;
Expand Down

0 comments on commit b04d533

Please sign in to comment.