mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 08:55:33 +08:00
template stripping in FID
This commit is contained in:
@@ -405,11 +405,6 @@ public class FidStatistics extends GhidraScript {
|
|||||||
}
|
}
|
||||||
String funcName = chooseFunctionName(result);
|
String funcName = chooseFunctionName(result);
|
||||||
NameVersions nameVersions = NameVersions.generate(funcName, program);
|
NameVersions nameVersions = NameVersions.generate(funcName, program);
|
||||||
String strippedTemplateName = null;
|
|
||||||
if (nameVersions.demangledBaseName != null) {
|
|
||||||
strippedTemplateName =
|
|
||||||
MatchNameAnalysis.removeTemplateParams(nameVersions.demangledBaseName);
|
|
||||||
}
|
|
||||||
boolean exactNameMatch = false;
|
boolean exactNameMatch = false;
|
||||||
Iterator<String> iter = matchAnalysis.getRawNameIterator();
|
Iterator<String> iter = matchAnalysis.getRawNameIterator();
|
||||||
while(iter.hasNext()) {
|
while(iter.hasNext()) {
|
||||||
@@ -450,14 +445,12 @@ public class FidStatistics extends GhidraScript {
|
|||||||
exactNameMatch = true;
|
exactNameMatch = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (matchNames.demangledBaseName != null && strippedTemplateName != null) {
|
if (nameVersions.demangledNoTemplate != null &&
|
||||||
String strippedName =
|
matchNames.demangledNoTemplate != null) {
|
||||||
MatchNameAnalysis.removeTemplateParams(matchNames.demangledBaseName);
|
if (checkNames(nameVersions.demangledNoTemplate,
|
||||||
if (strippedName != null) {
|
matchNames.demangledNoTemplate)) {
|
||||||
if (checkNames(strippedName, strippedTemplateName)) {
|
exactNameMatch = true;
|
||||||
exactNameMatch = true;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-43
@@ -32,8 +32,10 @@ public class MatchNameAnalysis {
|
|||||||
private Set<String> finalNameList = null;
|
private Set<String> finalNameList = null;
|
||||||
private TreeSet<String> rawNames = null;
|
private TreeSet<String> rawNames = null;
|
||||||
private TreeSet<String> similarBaseNames = null;
|
private TreeSet<String> similarBaseNames = null;
|
||||||
|
private TreeSet<String> demangledNameNoTemplate = null;
|
||||||
private TreeSet<String> exactDemangledBaseNames = null;
|
private TreeSet<String> exactDemangledBaseNames = null;
|
||||||
private TreeSet<String> libraries = 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
|
private int mostOptimisticCount; // What is most optimistic (smallest) number of matches
|
||||||
// Once duplicates and similar base names are taken into account
|
// Once duplicates and similar base names are taken into account
|
||||||
@@ -43,6 +45,10 @@ public class MatchNameAnalysis {
|
|||||||
return finalNameList.size();
|
return finalNameList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDemangled() {
|
||||||
|
return demangleSelect;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator<String> getRawNameIterator() {
|
public Iterator<String> getRawNameIterator() {
|
||||||
return rawNames.iterator();
|
return rawNames.iterator();
|
||||||
}
|
}
|
||||||
@@ -80,7 +86,9 @@ public class MatchNameAnalysis {
|
|||||||
|
|
||||||
rawNames = new TreeSet<String>();
|
rawNames = new TreeSet<String>();
|
||||||
similarBaseNames = new TreeSet<String>();
|
similarBaseNames = new TreeSet<String>();
|
||||||
|
demangledNameNoTemplate = new TreeSet<String>();
|
||||||
exactDemangledBaseNames = new TreeSet<String>();
|
exactDemangledBaseNames = new TreeSet<String>();
|
||||||
|
int cannotDetemplate = 0;
|
||||||
int cannotDemangle = 0;
|
int cannotDemangle = 0;
|
||||||
|
|
||||||
for (FidMatch match : matches) {
|
for (FidMatch match : matches) {
|
||||||
@@ -93,6 +101,12 @@ public class MatchNameAnalysis {
|
|||||||
if (nameVersions.rawName != null) {
|
if (nameVersions.rawName != null) {
|
||||||
rawNames.add(nameVersions.rawName); // Dedup the raw names
|
rawNames.add(nameVersions.rawName); // Dedup the raw names
|
||||||
similarBaseNames.add(nameVersions.similarName); // Dedup names with underscores removed
|
similarBaseNames.add(nameVersions.similarName); // Dedup names with underscores removed
|
||||||
|
if (nameVersions.demangledNoTemplate != null) {
|
||||||
|
demangledNameNoTemplate.add(nameVersions.demangledNoTemplate);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cannotDetemplate += 1;
|
||||||
|
}
|
||||||
if (nameVersions.demangledBaseName != null) {
|
if (nameVersions.demangledBaseName != null) {
|
||||||
exactDemangledBaseNames.add(nameVersions.demangledBaseName); // Dedup demangled base name
|
exactDemangledBaseNames.add(nameVersions.demangledBaseName); // Dedup demangled base name
|
||||||
}
|
}
|
||||||
@@ -111,8 +125,21 @@ public class MatchNameAnalysis {
|
|||||||
else {
|
else {
|
||||||
singleName = findCommonBaseName();
|
singleName = findCommonBaseName();
|
||||||
mostOptimisticCount = similarBaseNames.size();
|
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) {
|
if (singleName == null) {
|
||||||
singleName = findCommonDemangledBaseName(cannotDemangle);
|
singleName = findCommonDemangledBaseName(cannotDemangle);
|
||||||
|
if (singleName != null) {
|
||||||
|
demangleSelect = true;
|
||||||
|
}
|
||||||
if (exactDemangledBaseNames.size() > 0 &&
|
if (exactDemangledBaseNames.size() > 0 &&
|
||||||
exactDemangledBaseNames.size() < mostOptimisticCount) {
|
exactDemangledBaseNames.size() < mostOptimisticCount) {
|
||||||
mostOptimisticCount = exactDemangledBaseNames.size();
|
mostOptimisticCount = exactDemangledBaseNames.size();
|
||||||
@@ -183,35 +210,14 @@ public class MatchNameAnalysis {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private String findCommonNoTemplate(int cannotDetemplate) {
|
||||||
* If there exists an initial set of template parameters bracketed by '<' and '>'
|
if (cannotDetemplate > 0) {
|
||||||
* in this name, strip them from the name.
|
return null; // Couldn't remove a parameters from everything, so we can't have a common template
|
||||||
* @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) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
int nesting = 1;
|
if (demangledNameNoTemplate.size() == 1) {
|
||||||
int pos2;
|
return demangledNameNoTemplate.first();
|
||||||
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 null;
|
|
||||||
}
|
|
||||||
return name.substring(0, pos1 + 1) + name.substring(pos2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String findCommonDemangledBaseName(int cannotDemangle) {
|
private String findCommonDemangledBaseName(int cannotDemangle) {
|
||||||
@@ -219,22 +225,8 @@ public class MatchNameAnalysis {
|
|||||||
return null; // Couldn't demangle everything, so no way we can have a common base
|
return null; // Couldn't demangle everything, so no way we can have a common base
|
||||||
}
|
}
|
||||||
if (exactDemangledBaseNames.size() == 1) {
|
if (exactDemangledBaseNames.size() == 1) {
|
||||||
return exactDemangledBaseNames.iterator().next();
|
return exactDemangledBaseNames.first();
|
||||||
}
|
}
|
||||||
// If we don't have a unique demangled name, try excising template parameters
|
return null;
|
||||||
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 class NameVersions {
|
||||||
public String rawName; // Original name
|
public String rawName; // Original name
|
||||||
public String similarName; // Name with underscores removed
|
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 String demangledBaseName; // Base name of the demangled string
|
||||||
|
|
||||||
public NameVersions(String raw) {
|
public NameVersions(String raw) {
|
||||||
rawName = raw;
|
rawName = raw;
|
||||||
similarName = null;
|
similarName = null;
|
||||||
|
demangledNoTemplate = null;
|
||||||
demangledBaseName = null;
|
demangledBaseName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +57,38 @@ public class NameVersions {
|
|||||||
return name;
|
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) {
|
private static String constructBaseName(DemangledObject demangledObj) {
|
||||||
String origName = demangledObj.getName();
|
String origName = demangledObj.getName();
|
||||||
String name = origName.replaceFirst("_*", "");
|
String name = origName.replaceFirst("_*", "");
|
||||||
@@ -87,6 +121,7 @@ public class NameVersions {
|
|||||||
if (rawName != null) {
|
if (rawName != null) {
|
||||||
DemangledObject demangledObj = demangle(program, rawName);
|
DemangledObject demangledObj = demangle(program, rawName);
|
||||||
if (demangledObj != null) {
|
if (demangledObj != null) {
|
||||||
|
result.demangledNoTemplate = removeTemplateParams(demangledObj);
|
||||||
result.demangledBaseName = constructBaseName(demangledObj);
|
result.demangledBaseName = constructBaseName(demangledObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user