Merge remote-tracking branch 'origin/GP-7119_ghidragon_fixing_address_evaluator--SQUASHED'

This commit is contained in:
Ryan Kurtz
2026-09-03 05:09:48 -04:00
10 changed files with 463 additions and 236 deletions

View File

@@ -106,7 +106,7 @@ public class DWARFMacroEnumCreator {
ExpressionEvaluator evaluator =
new ExpressionEvaluator(s -> macrosToValues.get(s));
long value = evaluator.parseAsLong(macroInfo.definition());
macrosToValues.put(symbolName, new LongExpressionValue(value));
macrosToValues.put(symbolName, new BigIntegerExpressionValue(value));
EnumDataType enumDT =
new EnumDataType(catPath, "define_" + symbolName, 8,
dtManager);

View File

@@ -15,11 +15,20 @@
*/
package ghidra.app.util.navigation;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.List;
import javax.swing.*;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.border.Border;
import docking.DockingWindowManager;
@@ -30,7 +39,9 @@ import docking.widgets.checkbox.GCheckBox;
import docking.widgets.combobox.GhidraComboBox;
import ghidra.GhidraOptions;
import ghidra.app.nav.Navigatable;
import ghidra.app.services.*;
import ghidra.app.services.GoToService;
import ghidra.app.services.GoToServiceListener;
import ghidra.app.services.QueryData;
import ghidra.app.util.HelpTopics;
import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState;
@@ -145,7 +156,7 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
public void gotoFailed(Exception exc) {
navigatable = null;
setDialogEnabled(true);
setStatusText("ERROR: " + exc.getMessage());
setStatusText(exc.getMessage());
initializeContents();
}
@@ -191,6 +202,12 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
inner.add(hyperlink, gbc);
comboBox = new GhidraComboBox<>();
comboBox.addEditorKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
clearStatusText();
}
});
comboBox.setEditable(true);
String comboName = "Go To Address or Label Text Field / Combobox";

View File

@@ -15,21 +15,28 @@
*/
package ghidra.app.util.navigation;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import generic.expressions.ExpressionException;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.gotoquery.GoToQueryResultsTableModel;
import ghidra.app.plugin.core.navigation.NavigationOptions;
import ghidra.app.plugin.core.table.TableComponentProvider;
import ghidra.app.services.*;
import ghidra.app.services.GoToService;
import ghidra.app.services.ProgramManager;
import ghidra.app.services.QueryData;
import ghidra.app.util.SearchConstants;
import ghidra.app.util.query.TableService;
import ghidra.framework.options.Options;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFormatException;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.util.AddressEvaluator;
@@ -79,7 +86,7 @@ public class GoToQuery {
this.monitor = monitor;
}
public boolean processQuery() {
public boolean processQuery() throws ExpressionException {
// Queries can be of several different types. Handle all the non-symbol types first since
// they are faster to try, as they don't require searching through all the program's
// symbols.
@@ -88,7 +95,7 @@ public class GoToQuery {
return true;
}
if (processAddressExpression()) {
if (processAddressExpression(false)) {
return true;
}
@@ -96,9 +103,14 @@ public class GoToQuery {
return true;
}
// none of the specialized query handlers matched, so try to process the query
// as a symbol (label, function name, variable name, etc.)
return processSymbols();
if (processSymbols()) {
return true;
}
// try processing the expression again, this time allowing it to possibly throw an
// exception if it looks like an expression, but doesn't evaluate properly.
return processAddressExpression(true);
}
private boolean processFileOffset() {
@@ -122,7 +134,7 @@ public class GoToQuery {
return false;
}
private boolean processAddressExpression() {
private boolean processAddressExpression(boolean allowExceptions) throws ExpressionException {
String queryInput = queryData.getQueryString();
if (!isAddressExpression(queryInput)) {
return false;
@@ -131,11 +143,21 @@ public class GoToQuery {
// checking for leading "+" or "-", ignoring spaces.
boolean relative = queryInput.matches("^\\s*[+-].*");
Address baseAddr = relative ? fromAddress : null;
ExpressionException exception = null;
for (Program program : getSearchPrograms()) {
Address evalAddr = AddressEvaluator.evaluate(program, baseAddr, queryInput);
if (evalAddr != null) {
Address evalAddr;
try {
evalAddr = AddressEvaluator.parseRelative(program, baseAddr, queryInput);
return goTo(program, new ProgramLocation(program, evalAddr));
}
catch (ExpressionException e) {
exception = e;
}
}
if (allowExceptions && exception != null) {
throw exception;
}
return false;
}

View File

@@ -15,9 +15,13 @@
*/
package ghidra.app.util.navigation;
import generic.expressions.ExpressionException;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.gotoquery.GoToHelper;
import ghidra.app.services.*;
import ghidra.app.services.GoToOverrideService;
import ghidra.app.services.GoToService;
import ghidra.app.services.GoToServiceListener;
import ghidra.app.services.QueryData;
import ghidra.framework.plugintool.Plugin;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
@@ -137,11 +141,22 @@ public class GoToServiceImpl implements GoToService {
GoToQuery query = new GoToQuery(navigatable, plugin, this, queryData, fromAddr,
helper.getOptions(), monitor);
boolean result = query.processQuery();
if (listener != null) {
listener.gotoCompleted(queryData.getQueryString(), result);
boolean result;
try {
result = query.processQuery();
if (listener != null) {
listener.gotoCompleted(queryData.getQueryString(), result);
}
return result;
}
return result;
catch (ExpressionException e) {
// The exception has more information about the failure. Pass that to the listener
// if the user has supplied one.
if (listener != null) {
listener.gotoFailed(e);
}
}
return false;
}
@Override

View File

@@ -15,10 +15,14 @@
*/
package ghidra.program.util;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import generic.expressions.ExpressionException;
import generic.test.AbstractGenericTest;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
@@ -52,14 +56,24 @@ public class AddressEvaluatorTest extends AbstractGenericTest {
}
@Test
public void testLongValueExpression() {
public void testLongValueExpressionAbsolute() {
assertEval(addr("0x19"), "(2+3)*5");
assertEval(addr("0x11"), "2+3*5");
assertEval(addr("0x11"), "2+(3*5)");
assertEval(addr("0x3"), "0-5+8");
assertEval(addr("0x3"), "-5+8");
assertEval(addr("0xfffffffB"), "-5");
assertEval(addr("0x11"), "3+(5+(3*2)+(3))");
assertOutOfBounds("Address out of bounds. Expression evaluated to a negative value: -1",
"-1");
}
@Test
public void testRelativeAddSubtract() {
assertEvalRelative(addr("0x50"), addr("0x20"), "+30");
assertEvalRelative(addr("0x20"), addr("0x70"), "-50");
assertOutOfBoundsRelative(addr("0xffffffff"), "+1");
assertOutOfBoundsRelative(addr("0x0"), "-1");
}
@Test
@@ -80,8 +94,6 @@ public class AddressEvaluatorTest extends AbstractGenericTest {
assertEval(addr("0xff00"), "0xffff ^ 0xff");
assertEval(addr("0x123f"), "0xffff & 0x123f");
assertEval(addr("0x1234"), "0x1200 | 0x0034");
assertEval(addr("0xffffffff"), "~ 0x0");
assertEval(addr("0x1201"), "0x1200 | ~(0xfffffffe)");
assertEval(addr("0x480"), "0x1200 >> 2");
assertEval(addr("0x1200"), "0x480 << 2");
assertEval(addr("0x103"), "0x100 | 0x1 | ~(~0x2)");
@@ -156,6 +168,30 @@ public class AddressEvaluatorTest extends AbstractGenericTest {
assertEquals(addr, AddressEvaluator.evaluate(program, input));
}
private void assertEvalRelative(Address expected, Address base, String input) {
assertEquals(expected, AddressEvaluator.evaluate(program, base, input));
}
private void assertOutOfBounds(String errMsg, String input) {
try {
AddressEvaluator.parse(program, input);
fail("Expected Expression exception");
}
catch (ExpressionException e) {
assertEquals(errMsg, e.getMessage());
}
}
private void assertOutOfBoundsRelative(Address base, String input) {
try {
AddressEvaluator.parseRelative(program, base, input);
fail("Expected Expression exception");
}
catch (ExpressionException e) {
assertEquals("Address out of bounds", e.getMessage());
}
}
private Address addr(String address) {
return program.getAddressFactory().getAddress(address);
}