mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
template stripping in FID
This commit is contained in:
parent
956e8ef342
commit
062b6769f8
3 changed files with 76 additions and 56 deletions
|
@ -405,11 +405,6 @@ public class FidStatistics extends GhidraScript {
|
|||
}
|
||||
String funcName = chooseFunctionName(result);
|
||||
NameVersions nameVersions = NameVersions.generate(funcName, program);
|
||||
String strippedTemplateName = null;
|
||||
if (nameVersions.demangledBaseName != null) {
|
||||
strippedTemplateName =
|
||||
MatchNameAnalysis.removeTemplateParams(nameVersions.demangledBaseName);
|
||||
}
|
||||
boolean exactNameMatch = false;
|
||||
Iterator<String> iter = matchAnalysis.getRawNameIterator();
|
||||
while(iter.hasNext()) {
|
||||
|
@ -450,17 +445,15 @@ public class FidStatistics extends GhidraScript {
|
|||
exactNameMatch = true;
|
||||
break;
|
||||
}
|
||||
if (matchNames.demangledBaseName != null && strippedTemplateName != null) {
|
||||
String strippedName =
|
||||
MatchNameAnalysis.removeTemplateParams(matchNames.demangledBaseName);
|
||||
if (strippedName != null) {
|
||||
if (checkNames(strippedName, strippedTemplateName)) {
|
||||
if (nameVersions.demangledNoTemplate != null &&
|
||||
matchNames.demangledNoTemplate != null) {
|
||||
if (checkNames(nameVersions.demangledNoTemplate,
|
||||
matchNames.demangledNoTemplate)) {
|
||||
exactNameMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exactNameMatch) {
|
||||
record.nameMatched += 1;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,10 @@ public class MatchNameAnalysis {
|
|||
private Set<String> finalNameList = null;
|
||||
private TreeSet<String> rawNames = null;
|
||||
private TreeSet<String> similarBaseNames = null;
|
||||
private TreeSet<String> demangledNameNoTemplate = null;
|
||||
private TreeSet<String> exactDemangledBaseNames = null;
|
||||
private TreeSet<String> libraries = null;
|
||||
private boolean demangleSelect = false; // True if either deamngledNameNoTemplate or exactDemangledBaseNames is unique
|
||||
|
||||
private int mostOptimisticCount; // What is most optimistic (smallest) number of matches
|
||||
// Once duplicates and similar base names are taken into account
|
||||
|
@ -43,6 +45,10 @@ public class MatchNameAnalysis {
|
|||
return finalNameList.size();
|
||||
}
|
||||
|
||||
public boolean isDemangled() {
|
||||
return demangleSelect;
|
||||
}
|
||||
|
||||
public Iterator<String> getRawNameIterator() {
|
||||
return rawNames.iterator();
|
||||
}
|
||||
|
@ -80,7 +86,9 @@ public class MatchNameAnalysis {
|
|||
|
||||
rawNames = new TreeSet<String>();
|
||||
similarBaseNames = new TreeSet<String>();
|
||||
demangledNameNoTemplate = new TreeSet<String>();
|
||||
exactDemangledBaseNames = new TreeSet<String>();
|
||||
int cannotDetemplate = 0;
|
||||
int cannotDemangle = 0;
|
||||
|
||||
for (FidMatch match : matches) {
|
||||
|
@ -93,6 +101,12 @@ public class MatchNameAnalysis {
|
|||
if (nameVersions.rawName != null) {
|
||||
rawNames.add(nameVersions.rawName); // Dedup the raw names
|
||||
similarBaseNames.add(nameVersions.similarName); // Dedup names with underscores removed
|
||||
if (nameVersions.demangledNoTemplate != null) {
|
||||
demangledNameNoTemplate.add(nameVersions.demangledNoTemplate);
|
||||
}
|
||||
else {
|
||||
cannotDetemplate += 1;
|
||||
}
|
||||
if (nameVersions.demangledBaseName != null) {
|
||||
exactDemangledBaseNames.add(nameVersions.demangledBaseName); // Dedup demangled base name
|
||||
}
|
||||
|
@ -111,8 +125,21 @@ public class MatchNameAnalysis {
|
|||
else {
|
||||
singleName = findCommonBaseName();
|
||||
mostOptimisticCount = similarBaseNames.size();
|
||||
if (singleName == null) {
|
||||
singleName = findCommonNoTemplate(cannotDetemplate);
|
||||
if (singleName != null) {
|
||||
demangleSelect = true;
|
||||
}
|
||||
if (demangledNameNoTemplate.size() > 0 &&
|
||||
demangledNameNoTemplate.size() < mostOptimisticCount) {
|
||||
mostOptimisticCount = demangledNameNoTemplate.size();
|
||||
}
|
||||
}
|
||||
if (singleName == null) {
|
||||
singleName = findCommonDemangledBaseName(cannotDemangle);
|
||||
if (singleName != null) {
|
||||
demangleSelect = true;
|
||||
}
|
||||
if (exactDemangledBaseNames.size() > 0 &&
|
||||
exactDemangledBaseNames.size() < mostOptimisticCount) {
|
||||
mostOptimisticCount = exactDemangledBaseNames.size();
|
||||
|
@ -183,58 +210,23 @@ public class MatchNameAnalysis {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there exists an initial set of template parameters bracketed by '<' and '>'
|
||||
* in this name, strip them from the name.
|
||||
* @param name is the function name to strip
|
||||
* @return the stripped name or null if no parameters present
|
||||
*/
|
||||
public static String removeTemplateParams(String name) {
|
||||
int pos1 = name.indexOf('<');
|
||||
if (pos1 < 0) {
|
||||
private String findCommonNoTemplate(int cannotDetemplate) {
|
||||
if (cannotDetemplate > 0) {
|
||||
return null; // Couldn't remove a parameters from everything, so we can't have a common template
|
||||
}
|
||||
if (demangledNameNoTemplate.size() == 1) {
|
||||
return demangledNameNoTemplate.first();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
int nesting = 1;
|
||||
int pos2;
|
||||
for (pos2 = pos1 + 1; pos2 < name.length(); ++pos2) {
|
||||
char c = name.charAt(pos2);
|
||||
if (c == '<') {
|
||||
nesting += 1;
|
||||
}
|
||||
else if (c == '>') {
|
||||
nesting -= 1;
|
||||
if (nesting == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nesting != 0) {
|
||||
return null;
|
||||
}
|
||||
return name.substring(0, pos1 + 1) + name.substring(pos2);
|
||||
}
|
||||
|
||||
private String findCommonDemangledBaseName(int cannotDemangle) {
|
||||
if (cannotDemangle > 0) {
|
||||
return null; // Couldn't demangle everything, so no way we can have a common base
|
||||
}
|
||||
if (exactDemangledBaseNames.size() == 1) {
|
||||
return exactDemangledBaseNames.iterator().next();
|
||||
return exactDemangledBaseNames.first();
|
||||
}
|
||||
// If we don't have a unique demangled name, try excising template parameters
|
||||
String finalName = null;
|
||||
for (String name : exactDemangledBaseNames) {
|
||||
String templateFree = removeTemplateParams(name);
|
||||
if (templateFree == null) {
|
||||
return null; // At least one name has no template parameters
|
||||
}
|
||||
if (finalName == null) {
|
||||
finalName = templateFree;
|
||||
}
|
||||
else if (!finalName.equals(templateFree)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return finalName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,13 @@ import ghidra.program.model.listing.Program;
|
|||
public class NameVersions {
|
||||
public String rawName; // Original name
|
||||
public String similarName; // Name with underscores removed
|
||||
public String demangledNoTemplate; // Demangled string with (first) template removed
|
||||
public String demangledBaseName; // Base name of the demangled string
|
||||
|
||||
public NameVersions(String raw) {
|
||||
rawName = raw;
|
||||
similarName = null;
|
||||
demangledNoTemplate = null;
|
||||
demangledBaseName = null;
|
||||
}
|
||||
|
||||
|
@ -55,6 +57,38 @@ public class NameVersions {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there exists an initial set of template parameters bracketed by '<' and '>'
|
||||
* in the given demangled name, strip them.
|
||||
* @param demangledObj is the object holding the demangled name
|
||||
* @return the stripped name or null if no parameters present
|
||||
*/
|
||||
private static String removeTemplateParams(DemangledObject demangledObj) {
|
||||
String name = demangledObj.getDemangledName();
|
||||
int pos1 = name.indexOf('<');
|
||||
if (pos1 < 0) {
|
||||
return null;
|
||||
}
|
||||
int nesting = 1;
|
||||
int pos2;
|
||||
for (pos2 = pos1 + 1; pos2 < name.length(); ++pos2) {
|
||||
char c = name.charAt(pos2);
|
||||
if (c == '<') {
|
||||
nesting += 1;
|
||||
}
|
||||
else if (c == '>') {
|
||||
nesting -= 1;
|
||||
if (nesting == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nesting != 0) {
|
||||
return null;
|
||||
}
|
||||
return name.substring(0, pos1 + 1) + name.substring(pos2);
|
||||
}
|
||||
|
||||
private static String constructBaseName(DemangledObject demangledObj) {
|
||||
String origName = demangledObj.getName();
|
||||
String name = origName.replaceFirst("_*", "");
|
||||
|
@ -87,6 +121,7 @@ public class NameVersions {
|
|||
if (rawName != null) {
|
||||
DemangledObject demangledObj = demangle(program, rawName);
|
||||
if (demangledObj != null) {
|
||||
result.demangledNoTemplate = removeTemplateParams(demangledObj);
|
||||
result.demangledBaseName = constructBaseName(demangledObj);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue