mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch 'origin/GP-7119_ghidragon_fixing_address_evaluator--SQUASHED'
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user