Merge remote-tracking branch 'origin/GP-2244_ghizard_developer_mode_only_place_labels_within_function_namespaces__has_problems_with_labels_becoming_primary--SQUASHED'

This commit is contained in:
Ryan Kurtz
2022-08-10 13:08:40 -04:00
2 changed files with 154 additions and 18 deletions
@@ -15,6 +15,8 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
import java.util.regex.Matcher;
import ghidra.app.util.NamespaceUtils;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractLabelMsSymbol;
@@ -22,8 +24,6 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.symbol.Namespace;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
@@ -38,7 +38,6 @@ public class LabelSymbolApplier extends MsSymbolApplier {
* Constructor
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
* @param iter the Iterator containing the symbol sequence being processed
* @throws CancelledException upon user cancellation
*/
public LabelSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
super(applicator, iter);
@@ -52,28 +51,74 @@ public class LabelSymbolApplier extends MsSymbolApplier {
@Override
void apply() throws PdbException, CancelledException {
if (!applicator.getPdbApplicatorOptions().applyInstructionLabels()) {
String label = getLabel();
if (label == null) {
return;
}
// Place compiler generated symbols (e.g., $LN9) within containing function when possible
String name = symbol.getName();
Address symbolAddress = applicator.getAddress(symbol);
if (applicator.isInvalidAddress(symbolAddress, name)) {
if (applicator.isInvalidAddress(symbolAddress, label)) {
return;
}
FunctionManager functionManager = applicator.getProgram().getFunctionManager();
// TODO: What do we do with labels such as this?... "__catch$?test_eh1@@YAHXZ$7"
if (name.startsWith("$") && !name.contains(Namespace.DELIMITER)) {
Function f = functionManager.getFunctionContaining(symbolAddress);
if (f != null && !f.getName().equals(name)) {
name = NamespaceUtils.getNamespaceQualifiedName(f, name, true);
}
}
applicator.createSymbol(symbolAddress, name, false);
applicator.createSymbol(symbolAddress, label, false);
}
@Override
void applyTo(MsSymbolApplier applyToApplier) {
// Do nothing
String label = getLabel();
if (label == null) {
return;
}
Address symbolAddress = applicator.getAddress(symbol);
if (applicator.isInvalidAddress(symbolAddress, label)) {
return;
}
if (applyToApplier instanceof FunctionSymbolApplier functionSymbolApplier) {
Function f = functionSymbolApplier.getFunction();
if (f != null && !f.getName().equals(label)) {
label = NamespaceUtils.getNamespaceQualifiedName(f, label, true);
}
}
// No longer doing this, but instead letting namespace come from GPROC sequence... that way,
// labels will pertain to functions even if landing inside other function address range.
// Keeping code here (commented out), replaced by above code, until we get other issues
// figured out.
// FunctionManager functionManager = applicator.getProgram().getFunctionManager();
// // TODO: What do we do with labels such as this?... "__catch$?test_eh1@@YAHXZ$7"
// if (!label.contains(Namespace.DELIMITER)) {
// Function f = functionManager.getFunctionContaining(symbolAddress);
// if (f != null && !f.getName().equals(label)) {
// label = NamespaceUtils.getNamespaceQualifiedName(f, label, true);
// }
// }
// TODO: Before we turn on label applications.... we probably need to change order on
// how function symbols are applied. Perhaps we need to apply all GPROC symbols before
// we apply their internals (frames, local vars, labels, blocks) because some labels (here)
// are getting applied and becoming primary (because some have addresses that are located
// outside of the the address range of their GPROC, and will prevent another GPROC at the
// same address as the label from becoming primary (e.g., $LN7 of cn3 at a750).
applicator.createSymbol(symbolAddress, label, false);
}
/**
* Returns label to apply or null if label excluded
* @return label to process or null
*/
private String getLabel() {
if (!applicator.getPdbApplicatorOptions().applyInstructionLabels()) {
return null;
}
// Place compiler generated symbols (e.g., $LN9) within containing function when possible
String label = symbol.getName();
Matcher m =
applicator.getPdbApplicatorOptions().excludeInstructionLabelsPattern().matcher(label);
if (m.find()) {
return null;
}
return label;
}
}
@@ -15,9 +15,14 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
import ghidra.framework.options.Options;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
/**
* Options used while using a {@link DefaultPdbApplicator} to apply a PDB ({@link AbstractPdb}) to a
@@ -51,6 +56,29 @@ public class PdbApplicatorOptions {
"If checked, labels associated with instructions will be applied.";
private static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = false;
private boolean applyInstructionLabels;
// If the above option is enabled, allowing instruction labels to be applied, this
// edit box provides a filter to prevent any labels matching this pattern from being
// applied to the program.
private static final String OPTION_NAME_EXCLUDE_INSTRUCTION_LABELS =
"Exclude Instruction Labels";
private static final String OPTION_DESCRIPTION_EXCLUDE_INSTRUCTION_LABELS =
"Regular expression describing instruction labels to be excluded when \"" +
OPTION_NAME_APPLY_INSTRUCTION_LABELS + "\" is enabled.";
private static final String DEFAULT_EXCLUDE_INSTRUCTION_LABELS = "$a"; // "$a" will never match
private Pattern DEFAULT_EXCLUDE_INSTRUCTION_LABELS_PATTERN;
{
try {
DEFAULT_EXCLUDE_INSTRUCTION_LABELS_PATTERN =
Pattern.compile(DEFAULT_EXCLUDE_INSTRUCTION_LABELS);
}
catch (PatternSyntaxException e) {
throw new AssertException(
"Programming error: invalid default exclude labels pattern");
}
}
private String excludeInstructionLabels;
private Pattern excludeInstructionLabelsPattern;
// Attempt to map address using existing mangled symbols.
private static final String OPTION_NAME_ADDRESS_REMAP = "Address Remap Using Existing Symbols";
@@ -169,6 +197,14 @@ public class PdbApplicatorOptions {
options.registerOption(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels,
help, OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS);
// If the above option is enabled, allowing instruction labels to be applied, this
// edit box provides a filter to prevent any labels matching this pattern from being
// applied to the program.
options.registerOption(OPTION_NAME_EXCLUDE_INSTRUCTION_LABELS, excludeInstructionLabels,
help, OPTION_DESCRIPTION_EXCLUDE_INSTRUCTION_LABELS);
validatePattern(options);
// Can we disable this one above based upon the one above it? Do it with custom editor.
// The remap capability is not completely implemented... do not turn on.
options.registerOption(OPTION_NAME_ADDRESS_REMAP,
remapAddressUsingExistingPublicMangledSymbols, help,
@@ -206,10 +242,17 @@ public class PdbApplicatorOptions {
applyCodeScopeBlockComments = options.getBoolean(
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
// Mechanism to apply instruction labels
applyInstructionLabels =
options.getBoolean(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels);
// If the above option is enabled, allowing instruction labels to be applied, this
// edit box provides a filter to prevent any labels matching this pattern from being
// applied to the program
excludeInstructionLabels =
options.getString(OPTION_NAME_EXCLUDE_INSTRUCTION_LABELS, excludeInstructionLabels);
validatePattern(options);
remapAddressUsingExistingPublicMangledSymbols = options.getBoolean(
OPTION_NAME_ADDRESS_REMAP, remapAddressUsingExistingPublicMangledSymbols);
@@ -223,12 +266,32 @@ public class PdbApplicatorOptions {
}
}
// The following code cannot remain in a final solution... The options editor does
// not get an updated String written to it. Ultimately, there is no way to validate
// this value other than have a custom options editor, which is the direction we
// already believe we need to take for purposes of appropriately grouping options
// (other than in an alphabetical order).
private void validatePattern(Options options) {
try {
excludeInstructionLabelsPattern = Pattern.compile(excludeInstructionLabels);
}
catch (PatternSyntaxException e) {
Msg.error(this, "Invalid " + OPTION_NAME_EXCLUDE_INSTRUCTION_LABELS + " value: " +
excludeInstructionLabels + "\n Resetting to default value.");
excludeInstructionLabels = DEFAULT_EXCLUDE_INSTRUCTION_LABELS;
excludeInstructionLabelsPattern = DEFAULT_EXCLUDE_INSTRUCTION_LABELS_PATTERN;
options.restoreDefaultValue(OPTION_NAME_EXCLUDE_INSTRUCTION_LABELS);
}
}
/**
* Set the options to their default values
*/
public void setDefaults() {
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
excludeInstructionLabels = DEFAULT_EXCLUDE_INSTRUCTION_LABELS;
excludeInstructionLabelsPattern = DEFAULT_EXCLUDE_INSTRUCTION_LABELS_PATTERN;
control = DEFAULT_CONTROL;
remapAddressUsingExistingPublicMangledSymbols =
DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
@@ -269,6 +332,34 @@ public class PdbApplicatorOptions {
return applyInstructionLabels;
}
// If the above option is enabled, allowing instruction labels to be applied, this
// edit box provides a filter to prevent any labels matching this pattern from being
// applied to the program
/**
* Set regular expression string describing labels to exclude from application.
* @param excludeInstructionLabels regular expression describing instruction labels to exclude
*/
public void setApplyInstructionLabels(String excludeInstructionLabels) {
this.excludeInstructionLabels = excludeInstructionLabels;
}
/**
* Returns the string containing the regular expression describing instruction labels being
* excluded from application. Applicable when {@code applyInstructionLabels} is enabled
* @return the regular expression String
*/
public String excludeInstructionLabels() {
return excludeInstructionLabels;
}
/**
* Returns the Regex Pattern for the Exclude Instruction Labels field.
* @return the Pattern.
*/
public Pattern excludeInstructionLabelsPattern() {
return excludeInstructionLabelsPattern;
}
/**
* Set processing control for PdbApplicator
* @param control the processing control