rowObjects, TaskMonitor monitor) {
+
+ int tx = program.startTransaction("Table Chooser: " + getTitle());
+ try {
+ return doProcessRows(rowObjects, monitor);
+ }
+ finally {
+ program.endTransaction(tx, true);
+ }
+ }
+
public void addCustomColumn(ColumnDisplay> columnDisplay) {
model.addCustomColumn(columnDisplay);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/tablechooser/TableChooserExecutor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/tablechooser/TableChooserExecutor.java
index e1e7f537df..3414ea8f59 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/tablechooser/TableChooserExecutor.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/tablechooser/TableChooserExecutor.java
@@ -15,6 +15,11 @@
*/
package ghidra.app.tablechooser;
+/**
+ * The interface clients must implement to use the {@link TableChooserDialog}. This class is the
+ * callback that is used to process items from the dialog's table as users select one or more
+ * rows in the table and then press the table's "apply" button.
+ */
public interface TableChooserExecutor {
/**
@@ -29,6 +34,9 @@ public interface TableChooserExecutor {
* Applies this executors action to the given rowObject. Return true if the given object
* should be removed from the table.
*
+ * This method call will be wrapped in a transaction so the client does not have to do so.
+ * Multiple selected rows will all be processed in a single transaction.
+ *
* @param rowObject the AddressRowObject to be executed upon
* @return true if the rowObject should be removed from the table, false otherwise
*/
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java
index 8b185e485d..51b5a43572 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java
@@ -183,6 +183,9 @@ public class ElfDefaultGotPltMarkup {
monitor.checkCanceled();
Data data = createPointer(gotStart, true);
+ if (data == null) {
+ break;
+ }
try {
gotStart = data.getMaxAddress().add(1);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java
index 7745852af8..a1232215b8 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java
@@ -191,4 +191,14 @@ public class ElfSectionHeaderConstants {
public static final short SHN_XINDEX = (short) 0xffff;
/**upper bound on range of reserved indexes*/
public static final short SHN_HIRESERVE = (short) 0xffff;
+
+ /**
+ * @param symbolSectionIndex symbol section index (st_shndx)
+ * @return true if specified symbol section index corresponds to a processor
+ * specific value in the range SHN_LOPROC..SHN_HIPROC, else false
+ */
+ public static boolean isProcessorSpecificSymbolSectionIndex(short symbolSectionIndex) {
+ return symbolSectionIndex >= ElfSectionHeaderConstants.SHN_LOPROC &&
+ symbolSectionIndex <= ElfSectionHeaderConstants.SHN_HIPROC;
+ }
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java
index 1eaa428bca..1d75c2746a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java
@@ -312,6 +312,22 @@ public class ElfLoadAdapter {
return functionAddress;
}
+ /**
+ * This method allows an extension to override the default address calculation for loading
+ * a symbol. This is generally only neccessary when symbol requires handling of processor-specific
+ * flags or section index. This method should return null when default symbol processing
+ * is sufficient. {@link Address#NO_ADDRESS} should be returned if the symbol is external
+ * and is not handled by default processing.
+ * @param elfLoadHelper load helper object
+ * @param elfSymbol elf symbol
+ * @return symbol memory address or null to defer to default implementation
+ * @throws NoValueException if error logged and address calculation failed
+ */
+ public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol)
+ throws NoValueException {
+ return null;
+ }
+
/**
* During symbol processing this method will be invoked to permit an extension to
* adjust the address and/or apply context to the intended symbol location.
@@ -487,4 +503,5 @@ public class ElfLoadAdapter {
public Class extends ElfRelocation> getRelocationClass(ElfHeader elfHeader) {
return null;
}
+
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
index 4d273f4e6d..dd30101e28 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
@@ -20,7 +20,6 @@ import java.io.InputStream;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.*;
-import java.util.function.Consumer;
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
import ghidra.app.util.MemoryBlockUtils;
@@ -1232,7 +1231,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
monitor.checkCanceled();
try {
- Address address = calculateSymbolAddress(elfSymbol, msg -> log(msg));
+ Address address = calculateSymbolAddress(elfSymbol);
if (address == null) {
continue;
}
@@ -1280,11 +1279,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
/**
* Calculate the load address associated with a specified elfSymbol.
* @param elfSymbol ELF symbol
- * @param errorConsumer error consumer
* @return symbol address or null if symbol not supported and address not determined,
- * or NO_ADDRESS if symbol is external and should be allocated to the EXTERNAL block.
+ * or {@link Address#NO_ADDRESS} if symbol is external and should be allocated to the EXTERNAL block.
*/
- private Address calculateSymbolAddress(ElfSymbol elfSymbol, Consumer errorConsumer) {
+ private Address calculateSymbolAddress(ElfSymbol elfSymbol) {
if (elfSymbol.getSymbolTableIndex() == 0) {
return null; // always skip the first symbol, it is NULL
@@ -1296,13 +1294,23 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (elfSymbol.isTLS()) {
// TODO: Investigate support for TLS symbols
- errorConsumer.accept(
- "Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getNameAsString());
+ log("Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getNameAsString());
return null;
}
ElfLoadAdapter loadAdapter = elf.getLoadAdapter();
+ // Allow extension to have first shot at calculating symbol address
+ try {
+ Address address = elf.getLoadAdapter().calculateSymbolAddress(this, elfSymbol);
+ if (address != null) {
+ return address;
+ }
+ }
+ catch (NoValueException e) {
+ return null;
+ }
+
ElfSectionHeader[] elfSections = elf.getSections();
short sectionIndex = elfSymbol.getSectionHeaderIndex();
Address symSectionBase = null;
@@ -1316,7 +1324,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
ElfSectionHeader symSection = elf.getSections()[sectionIndex];
symSectionBase = findLoadAddress(symSection, 0);
if (symSectionBase == null) {
- errorConsumer.accept("Unable to place symbol due to non-loaded section: " +
+ log("Unable to place symbol due to non-loaded section: " +
elfSymbol.getNameAsString() + " - value=0x" +
Long.toHexString(elfSymbol.getValue()) + ", section=" +
symSection.getNameAsString());
@@ -1366,7 +1374,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// SHN_COMMON 0xfff2
// SHN_HIRESERVE 0xffff
- errorConsumer.accept("Unable to place symbol: " + elfSymbol.getNameAsString() +
+ log("Unable to place symbol: " + elfSymbol.getNameAsString() +
" - value=0x" + Long.toHexString(elfSymbol.getValue()) + ", section-index=0x" +
Integer.toHexString(sectionIndex & 0xffff));
return null;
@@ -1389,12 +1397,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
}
else if (elf.isRelocatable()) {
if (sectionIndex < 0 || sectionIndex >= elfSections.length) {
- errorConsumer.accept("Error creating symbol: " + elfSymbol.getNameAsString() +
+ log("Error creating symbol: " + elfSymbol.getNameAsString() +
" - 0x" + Long.toHexString(elfSymbol.getValue()));
return Address.NO_ADDRESS;
}
else if (symSectionBase == null) {
- errorConsumer.accept("No Memory for symbol: " + elfSymbol.getNameAsString() +
+ log("No Memory for symbol: " + elfSymbol.getNameAsString() +
" - 0x" + Long.toHexString(elfSymbol.getValue()));
return Address.NO_ADDRESS;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java
index 2a4e0c0711..f28bd38910 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java
@@ -27,6 +27,7 @@ import ghidra.app.util.HighlightProvider;
import ghidra.app.util.viewer.format.FieldFormatModel;
import ghidra.app.util.viewer.listingpanel.ListingModel;
import ghidra.app.util.viewer.options.OptionsGui;
+import ghidra.app.util.viewer.proxy.DataProxy;
import ghidra.app.util.viewer.proxy.ProxyObj;
import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions;
@@ -126,10 +127,10 @@ public class PlateFieldFactory extends FieldFactory {
nLinesBeforeLabels = fieldOptions.getInt(LINES_BEFORE_LABELS_OPTION, 1);
nLinesBeforePlates = fieldOptions.getInt(LINES_BEFORE_PLATES_OPTION, 0);
- showExternalFunctionPointerPlates = fieldOptions.getBoolean(
- ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true);
- showNonExternalFunctionPointerPlates = fieldOptions.getBoolean(
- ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false);
+ showExternalFunctionPointerPlates = fieldOptions
+ .getBoolean(ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true);
+ showNonExternalFunctionPointerPlates = fieldOptions
+ .getBoolean(ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false);
}
@@ -160,11 +161,32 @@ public class PlateFieldFactory extends FieldFactory {
FieldElement[] fields = new FieldElement[elementList.size()];
elementList.toArray(fields);
+ if (isNestedDataAtSameAddressAsParent(proxy)) {
+ // This is data at the same address as the parent, which happens with the first
+ // element in a structure. We do not want to the plate comment here, but only at the
+ // parent topmost address.
+ return null;
+ }
+
PlateFieldTextField textField =
new PlateFieldTextField(fields, this, proxy, startX, width, commentText, isClipped);
return new PlateListingTextField(proxy, textField);
}
+ private boolean isNestedDataAtSameAddressAsParent(ProxyObj> proxy) {
+ if (proxy instanceof DataProxy) {
+ DataProxy dp = (DataProxy) proxy;
+ Data data = dp.getObject();
+ int[] cpath = data.getComponentPath();
+ if (cpath.length > 0) {
+ if (cpath[cpath.length - 1] == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private String getCommentText(CodeUnit cu) {
String[] comments = cu.getCommentAsArray(CodeUnit.PLATE_COMMENT);
if (comments == null) {
@@ -199,8 +221,8 @@ public class PlateFieldFactory extends FieldFactory {
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
for (int i = 0; i < comments.length; i++) {
- elementList.add(
- CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i));
+ elementList
+ .add(CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i));
}
if (isWordWrap) {
@@ -499,7 +521,10 @@ public class PlateFieldFactory extends FieldFactory {
if (!CodeUnit.class.isAssignableFrom(proxyObjectClass)) {
return false;
}
- return (category == FieldFormatModel.PLATE);
+
+ // some users like the look of plate comments and would like them in many places
+ return (category == FieldFormatModel.PLATE || category == FieldFormatModel.OPEN_DATA ||
+ category == FieldFormatModel.INSTRUCTION_OR_DATA);
}
@Override
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java
index d07a2a1a1c..7f333da0b7 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java
@@ -120,16 +120,14 @@ public class PreCommentFieldFactory extends FieldFactory {
private String[] getDefinedPreComments(CodeUnit cu) {
- // If this code unit is the outside of a data
- // container, then do not display any comments.
- // If this was allowed, then the comment would appear
- // on the outside data container and on the 1st
- // internal member
- //
+ // Do not show comments for nested components that share the same address as their parent
if (cu instanceof Data) {
Data data = (Data) cu;
- if (data.getNumComponents() > 0) {
- return null;
+ int[] cpath = data.getComponentPath();
+ if (cpath.length > 0) {
+ if (cpath[cpath.length - 1] == 0) {
+ return null;
+ }
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/SymbolAnnotatedStringHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/SymbolAnnotatedStringHandler.java
index f687d68736..b3c2626908 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/SymbolAnnotatedStringHandler.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/SymbolAnnotatedStringHandler.java
@@ -22,7 +22,6 @@ import java.util.regex.Pattern;
import docking.widgets.fieldpanel.field.AttributedString;
import ghidra.app.nav.Navigatable;
import ghidra.app.services.GoToService;
-import ghidra.app.services.QueryData;
import ghidra.app.util.NamespaceUtils;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address;
@@ -142,8 +141,8 @@ public class SymbolAnnotatedStringHandler implements AnnotatedStringHandler {
// try going to the symbol first
if (!symbols.isEmpty()) {
- QueryData data = new QueryData(symbols.get(0).getName(), true);
- return goToService.goToQuery(sourceNavigatable, null, data, null, null);
+ Symbol s = symbols.get(0);
+ return goToService.goTo(s.getProgramLocation());
}
// try going to the address
diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/ShowConstantUse.java b/Ghidra/Features/Decompiler/ghidra_scripts/ShowConstantUse.java
index 24e7cea701..3123a67e19 100644
--- a/Ghidra/Features/Decompiler/ghidra_scripts/ShowConstantUse.java
+++ b/Ghidra/Features/Decompiler/ghidra_scripts/ShowConstantUse.java
@@ -40,8 +40,7 @@ import ghidra.program.model.pcode.*;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.util.*;
-import ghidra.util.SystemUtilities;
-import ghidra.util.UndefinedFunction;
+import ghidra.util.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException;
@@ -157,10 +156,9 @@ public class ShowConstantUse extends GhidraScript {
}
/**
- * Builds the configurable columns for the TableDialog. More columns could
- * be added.
+ * Builds the configurable columns for the TableDialog. More columns could be added.
*
- * @param tableChooserDialog
+ * @param tableChooserDialog the dialog
*/
private void configureTableColumns(TableChooserDialog tableChooserDialog) {
// First column added is the Constant value that is found.
@@ -254,8 +252,10 @@ public class ShowConstantUse extends GhidraScript {
@Override
public String getColumnValue(AddressableRowObject rowObject) {
ConstUseLocation entry = (ConstUseLocation) rowObject;
- Function func = entry.getProgram().getFunctionManager().getFunctionContaining(
- entry.getAddress());
+ Function func = entry.getProgram()
+ .getFunctionManager()
+ .getFunctionContaining(
+ entry.getAddress());
if (func == null) {
return "";
}
@@ -299,7 +299,7 @@ public class ShowConstantUse extends GhidraScript {
* script by creating an artificial ScriptState. This is a useful technique
* for other scripts as well.
*
- * @return
+ * @return the executor
*/
@SuppressWarnings("unused")
private TableChooserExecutor createTableExecutor() {
@@ -314,23 +314,14 @@ public class ShowConstantUse extends GhidraScript {
@Override
public boolean execute(AddressableRowObject rowObject) {
ConstUseLocation constLoc = (ConstUseLocation) rowObject;
- System.out.println("Follow Structure : " + rowObject.getAddress());
+ println("Follow Structure : " + rowObject.getAddress());
Program cp = constLoc.getProgram();
Address entry = constLoc.getAddress();
- // If we will change something in program, have to open a
- // transaction
- int trans = cp.startTransaction("Run Script" + entry);
- try {
- System.out.println("Create Structure at " + entry);
-
- runScript("CreateStructure.java", cp, entry);
- }
- finally {
- cp.endTransaction(trans, true);
- }
+ println("Create Structure at " + entry);
+ runScript("CreateStructure.java", cp, entry);
return false; // don't remove row from display table
}
@@ -347,7 +338,7 @@ public class ShowConstantUse extends GhidraScript {
}
}
catch (Exception exc) {
- exc.printStackTrace();
+ Msg.error(this, "Exception running script", exc);
}
throw new IllegalArgumentException("Script does not exist: " + name);
}
@@ -393,7 +384,7 @@ public class ShowConstantUse extends GhidraScript {
* decompiler. In the decompiler this could be a local/parameter at any
* point in the decompiler. In the listing, it must be a parameter variable.
*
- * @return
+ * @return the varnode
*/
private Varnode getVarnodeLocation() {
Varnode var = null;
@@ -559,7 +550,7 @@ public class ShowConstantUse extends GhidraScript {
* - accumulate entries. Don't like passing it, but this way the
* user gets immediate feedback as locations are found
* @return a map of Addresses->constants (constants could be NULL)
- * @throws CancelledException
+ * @throws CancelledException if cancelled
*/
private HashMap backtrackToConstant(Varnode var,
TableChooserDialog tableChooserDialog) throws CancelledException {
@@ -587,15 +578,12 @@ public class ShowConstantUse extends GhidraScript {
* Backtrack to a constant given a start position of a parameter of a given
* function Useful if you want to start from a function paramter.
*
- * @param f
- * - function to start in
- * @param paramIndex
- * - parameter index to backtrack from
- * @param tableChooserDialog
- * - accumulate entries. Don't like passing it, but this way the
- * user gets immediate feedback as locations are found
- * @return a map of Addresses->constants (constants could be NULL)
- * @throws CancelledException
+ * @param f function to start in
+ * @param paramIndex parameter index to backtrack from
+ * @param tableChooserDialog accumulate entries. Don't like passing it, but this way the
+ * user gets immediate feedback as locations are found
+ * @return a map of Addresses to constants (constants could be NULL)
+ * @throws CancelledException if cancelled
*/
private HashMap backtrackParamToConstant(Function f, int paramIndex,
TableChooserDialog tableChooserDialog) throws CancelledException {
@@ -699,14 +687,7 @@ public class ShowConstantUse extends GhidraScript {
this.addConstantProblem(tableDialog, address, problem);
}
- /**
- * Analyze a functions references
- *
- * @param constUse
- * @param funcVarUse
- * @param funcList
- */
- public void analyzeFunction(HashMap constUse, DecompInterface decompInterface,
+ private void analyzeFunction(HashMap constUse, DecompInterface decompInterface,
Program prog, Function f, Address refAddr, FunctionParamUse funcVarUse, int paramIndex,
ArrayList defUseList, ArrayList funcList) {
if (f == null) {
@@ -722,12 +703,9 @@ public class ShowConstantUse extends GhidraScript {
Iterator ops = hfunction.getPcodeOps(refAddr.getPhysicalAddress());
while (ops.hasNext() && !monitor.isCancelled()) {
PcodeOpAST pcodeOpAST = ops.next();
- // System.out.println(pcodeOpAST);
if (pcodeOpAST.getOpcode() == PcodeOp.CALL) {
// get the second parameter
- Varnode parm = pcodeOpAST.getInput(paramIndex + 1); // 1st param
- // is the
- // call dest
+ Varnode parm = pcodeOpAST.getInput(paramIndex + 1); // 1st param is the call dest
if (parm == null) {
constUse.put(instr.getAddress(), null);
String problem = " *** Warning, it appears that function '" +
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java
index 9d9cd23198..a49acf89d0 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java
@@ -42,9 +42,9 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
private static final String[] VARIADIC_SUBSTRINGS = { "printf", "scanf" };
private static final String NAME = "Variadic Function Signature Override";
private static final String DESCRIPTION =
- "Detects variadic function calls in the bodies of each function that intersect the" +
+ "Detects variadic function calls in the bodies of each function that intersect the " +
"current selection and parses their format string arguments to infer the correct " +
- "signatures. Currently, this analyzer only supports printf, scanf, and thier variants " +
+ "signatures. Currently, this analyzer only supports printf, scanf, and their variants " +
"(e.g., snprintf, fscanf). If the current selection is empty, it searches through " +
"every function. Once the correct signatures are inferred, they are overridden.";
private final static boolean OPTION_DEFAULT_CREATE_BOOKMARKS_ENABLED = false;
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
index 6578e55ffb..c845e43d91 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
@@ -58,7 +58,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
setSupportsOneTimeAnalysis();
// Set priority of RTTI analyzer to run after Demangler so can see if better
// plate comment or label already exists from Demangler.
- setPriority(AnalysisPriority.DATA_TYPE_PROPOGATION.before().before());
+ setPriority(AnalysisPriority.REFERENCE_ANALYSIS.before());
setDefaultEnablement(true);
validationOptions = new DataValidationOptions();
applyOptions = new DataApplyOptions();
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
index f07d01de59..8fb88b10c4 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java
@@ -19,7 +19,6 @@ import java.util.*;
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.cmd.function.*;
-import ghidra.app.util.SymbolPath;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
@@ -301,9 +300,6 @@ public class FunctionSymbolApplier extends MsSymbolApplier {
}
}
-
- applicator.addFunctionUse(procedureSymbol, new SymbolPath(function.getSymbol()));
-
DataType dataType = applier.getDataType();
// Since we know the applier is an AbstractionFunctionTypeApplier, then dataType is either
// FunctionDefinition or no type (typedef).
@@ -317,7 +313,6 @@ public class FunctionSymbolApplier extends MsSymbolApplier {
" due to " + sigCmd.getStatusMsg() + "; dataType: " + def.getName());
return false;
}
- // TODO: Move datatype to correct category
}
return true;
}
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java
index f726b15c89..2d10d2f3eb 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java
@@ -37,7 +37,6 @@ import ghidra.program.model.data.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
-import ghidra.util.InvalidNameException;
import ghidra.util.Msg;
import ghidra.util.exception.*;
import ghidra.util.task.CancelOnlyWrappingTaskMonitor;
@@ -65,7 +64,6 @@ import ghidra.util.task.TaskMonitor;
public class PdbApplicator {
private static final String THUNK_NAME_PREFIX = "[thunk]:";
- private static final SymbolPath DUMMY_SYMBOL_PATH = new SymbolPath("/");
//==============================================================================================
/**
@@ -145,13 +143,6 @@ public class PdbApplicator {
*/
private Map isClassByNamespace;
- /**
- * Map for tracking use of procedure type records by function symbols.
- * If a type record is used more than once it will get mapped to the
- * {@link #DUMMY_SYMBOL_PATH} to indicate non-unique use.
- */
- private Map procedureSymbolNameMap;
-
//==============================================================================================
private SymbolApplierFactory symbolApplierParser;
@@ -208,7 +199,6 @@ public class PdbApplicator {
case NONE:
processTypes();
processSymbols();
- renameAnonymousFunctions();
break;
default:
throw new PdbException("Invalid Restriction");
@@ -326,7 +316,6 @@ public class PdbApplicator {
complexApplierMapper = new ComplexTypeApplierMapper(this);
applierDependencyGraph = new JungDirectedGraph<>();
isClassByNamespace = new TreeMap<>();
- procedureSymbolNameMap = new HashMap<>();
if (program != null) {
// Currently, this must happen after symbolGroups are created.
PdbVbtManager pdbVbtManager = new PdbVbtManager(this);
@@ -1246,74 +1235,6 @@ public class PdbApplicator {
}
}
- void addFunctionUse(AbstractProcedureMsSymbol procedureSymbol, SymbolPath symbolPath) {
- RecordNumber rn = procedureSymbol.getTypeRecordNumber();
- SymbolPath n = procedureSymbolNameMap.get(rn);
- if (n == null) {
- procedureSymbolNameMap.put(rn, symbolPath);
- }
- else if (!symbolPath.equals(n)) {
- procedureSymbolNameMap.put(rn, DUMMY_SYMBOL_PATH);
- }
- }
-
- private void renameAnonymousFunctions() throws CancelledException {
-
- monitor.setMessage("Renaming function definitions...");
- monitor.setProgress(0);
- monitor.setMaximum(procedureSymbolNameMap.size());
- int cnt = 0;
- int renamedCnt = 0;
-
- for (RecordNumber rn : procedureSymbolNameMap.keySet()) {
- monitor.checkCanceled();
- monitor.setProgress(++cnt);
- SymbolPath symbolPath = procedureSymbolNameMap.get(rn);
- if (symbolPath != DUMMY_SYMBOL_PATH) {
- // unique name exists for function definition (single use)
- MsTypeApplier typeApplier = getTypeApplier(rn);
- DataType dt = typeApplier.getDataType();
- CategoryPath category = categoryUtils.getCategory(symbolPath.getParent());
- Category newCategory = dataTypeManager.createCategory(category);
- String newName = symbolPath.getName();
-
- try {
- if (newCategory.getDataType(newName) == null) {
- // fast approach should generally work
- dt.setName(newName);
- dt.setCategoryPath(category);
- }
- else {
- // use slow approach if conflict exists
- DataType newDt = dt.copy(dataTypeManager);
- newDt.setName(symbolPath.getName());
- newDt.setCategoryPath(category);
- newDt = resolve(newDt);
- dataTypeManager.replaceDataType(dt, newDt, false);
- typeApplier.resolvedDataType = newDt;
- }
- ++renamedCnt;
- }
- catch (InvalidNameException | DuplicateNameException
- | DataTypeDependencyException e) {
- // unexpected - skip
- Msg.error(this, "PDB Function definition rename failed: " + dt.getName() +
- " -> " + symbolPath);
- }
- }
- }
- if (renamedCnt != 0) {
- Msg.debug(this, "PDB Renamed " + renamedCnt + " of " + cnt + " function definitions");
- Category anonymousCategory =
- dataTypeManager.getCategory(getAnonymousFunctionsCategory());
- if (anonymousCategory != null) {
- Msg.debug(this, "PDB Remaining anonymous function definition count: " +
- anonymousCategory.getDataTypes().length);
- }
- }
-
- }
-
//==============================================================================================
//==============================================================================================
//==============================================================================================
diff --git a/Ghidra/Features/Python/src/main/java/ghidra/python/GhidraPythonInterpreter.java b/Ghidra/Features/Python/src/main/java/ghidra/python/GhidraPythonInterpreter.java
index d9261153f8..e102543058 100644
--- a/Ghidra/Features/Python/src/main/java/ghidra/python/GhidraPythonInterpreter.java
+++ b/Ghidra/Features/Python/src/main/java/ghidra/python/GhidraPythonInterpreter.java
@@ -218,8 +218,12 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
InetAddress localhost = InetAddress.getLocalHost();
new Socket(localhost, PyDevUtils.PYDEV_REMOTE_DEBUGGER_PORT).close();
Msg.info(this, "Python debugger found");
- exec("import pydevd; pydevd.settrace(host=\"" + localhost.getHostName() +
+ StringBuilder dbgCmds = new StringBuilder();
+ dbgCmds.append("import pydevd;");
+ dbgCmds.append("pydevd.threadingCurrentThread().__pydevd_main_thread = True;");
+ dbgCmds.append("pydevd.settrace(host=\"" + localhost.getHostName() +
"\", port=" + PyDevUtils.PYDEV_REMOTE_DEBUGGER_PORT + ", suspend=False);");
+ exec(dbgCmds.toString());
Msg.info(this, "Connected to a python debugger.");
}
catch (IOException e) {
diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java
index f7d4c526e6..f594fa9702 100644
--- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java
+++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java
@@ -454,7 +454,7 @@ public class GraphComponent, G e
mainStalePanel.setOpaque(false);
String tooltip = HTMLUtilities.toWrappedHTML("The block model of the function " +
- "for this graph has changed. Press the relyout button to refresh the layout." +
+ "for this graph has changed. Press the relayout button to refresh the layout." +
"\n\n") + "Note: You can edit the graph " +
"options to have the graph update automatically.";
diff --git a/Ghidra/Framework/SoftwareModeling/Sleigh.launch b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
new file mode 100644
index 0000000000..0582eb91e3
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableStorage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableStorage.java
index 4722c397cd..db51390974 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableStorage.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableStorage.java
@@ -239,7 +239,7 @@ public class VariableStorage implements Comparable {
}
if (i < (varnodes.length - 1) && !isRegister) {
throw new InvalidInputException(
- "Compound storage must use registers accept for last varnode");
+ "Compound storage must use registers except for last varnode");
}
size += varnode.getSize();
}
diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java
index 99c1a8c366..2e33262ce0 100644
--- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java
+++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java
@@ -34,7 +34,7 @@ import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class MIPS_ElfExtension extends ElfExtension {
-
+
private static final String MIPS_STUBS_SECTION_NAME = ".MIPS.stubs";
// GP value reflected by symbol address
@@ -287,9 +287,13 @@ public class MIPS_ElfExtension extends ElfExtension {
public static final byte ODK_IDENT = 10;
public static final byte ODK_PAGESIZE = 11;
+ // MIPS-specific SHN values
+ public static final short SHN_MIPS_ACOMMON = (short) 0xff00;
+ public static final short SHN_MIPS_TEXT = (short) 0xff01;
+ public static final short SHN_MIPS_DATA = (short) 0xff02;
+
@Override
public boolean canHandle(ElfHeader elf) {
- // TODO: Verify 64-bit MIPS support
return elf.e_machine() == ElfConstants.EM_MIPS;
}
@@ -328,6 +332,25 @@ public class MIPS_ElfExtension extends ElfExtension {
return functionAddress;
}
+ @Override
+ public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol)
+ throws NoValueException {
+
+ short sectionIndex = elfSymbol.getSectionHeaderIndex();
+ if (!ElfSectionHeaderConstants.isProcessorSpecificSymbolSectionIndex(sectionIndex)) {
+ return null;
+ }
+
+ if (sectionIndex == SHN_MIPS_ACOMMON || sectionIndex == SHN_MIPS_TEXT || sectionIndex == SHN_MIPS_DATA) {
+ // NOTE: logic assumes no memory conflict occured during section loading
+ AddressSpace defaultSpace = elfLoadHelper.getProgram().getAddressFactory().getDefaultAddressSpace();
+ return defaultSpace.getAddress(elfSymbol.getValue() + elfLoadHelper.getImageBaseWordAdjustmentOffset());
+ }
+
+ return null;
+ }
+
+
@Override
public Address evaluateElfSymbol(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol,
Address address, boolean isExternal) {
diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/category.xml b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/category.xml
index c97bad1bd1..7dbdf5746e 100644
--- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/category.xml
+++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/category.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml
index b014ffeb63..ead7c00822 100644
--- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml
+++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml
@@ -2,7 +2,7 @@
diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html
index d8aac87775..58f8f5e16d 100644
--- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html
+++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html
@@ -53,6 +53,8 @@ change with future releases.