mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-812 corrected improper exposure of DatabaseObject methods
This commit is contained in:
parent
6a8788acbc
commit
d688f580dc
25 changed files with 209 additions and 195 deletions
|
@ -986,7 +986,7 @@ public class FunctionEditorModel {
|
||||||
if (!paramInfo.isAutoParameter() && paramInfo.isNameModified()) {
|
if (!paramInfo.isAutoParameter() && paramInfo.isNameModified()) {
|
||||||
Parameter param = paramInfo.getOriginalParameter();
|
Parameter param = paramInfo.getOriginalParameter();
|
||||||
if (param != null) {
|
if (param != null) {
|
||||||
if (!param.getSymbol().checkIsValid()) {
|
if (param.getSymbol().isDeleted()) {
|
||||||
// concurrent removal of param - must do full update
|
// concurrent removal of param - must do full update
|
||||||
paramsOrReturnModified = true;
|
paramsOrReturnModified = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,7 +38,6 @@ import ghidra.app.plugin.core.compositeeditor.CompositeEditorModel;
|
||||||
import ghidra.app.plugin.core.compositeeditor.DataTypeHelper;
|
import ghidra.app.plugin.core.compositeeditor.DataTypeHelper;
|
||||||
import ghidra.app.util.datatype.EmptyCompositeException;
|
import ghidra.app.util.datatype.EmptyCompositeException;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
import ghidra.program.database.DatabaseObject;
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
@ -1271,11 +1270,8 @@ class StackEditorModel extends CompositeEditorModel {
|
||||||
for (int i = comps.length - 1; i >= 0; i--) {
|
for (int i = comps.length - 1; i >= 0; i--) {
|
||||||
DataTypeComponent component = comps[i];
|
DataTypeComponent component = comps[i];
|
||||||
DataType compDt = component.getDataType();
|
DataType compDt = component.getDataType();
|
||||||
if (compDt instanceof DatabaseObject) {
|
if (compDt.isDeleted()) {
|
||||||
DatabaseObject dbObj = (DatabaseObject) compDt;
|
clearComponent(component.getOrdinal());
|
||||||
if (!dbObj.checkIsValid()) {
|
|
||||||
clearComponent(component.getOrdinal());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.stackeditor;
|
package ghidra.app.plugin.core.stackeditor;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.compositeeditor.CompositeEditorPanel;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
|
||||||
import ghidra.program.database.DatabaseObject;
|
|
||||||
import ghidra.program.model.data.*;
|
|
||||||
import ghidra.program.model.listing.*;
|
|
||||||
import ghidra.util.exception.UsrException;
|
|
||||||
|
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
|
import ghidra.app.plugin.core.compositeeditor.CompositeEditorPanel;
|
||||||
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.util.exception.UsrException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel for editing a function stack.
|
* Panel for editing a function stack.
|
||||||
|
@ -274,14 +271,12 @@ public class StackEditorPanel extends CompositeEditorPanel {
|
||||||
if (originalDt instanceof StackFrameDataType) {
|
if (originalDt instanceof StackFrameDataType) {
|
||||||
StackFrameDataType sfdt = (StackFrameDataType) originalDt;
|
StackFrameDataType sfdt = (StackFrameDataType) originalDt;
|
||||||
Function function = sfdt.getFunction();
|
Function function = sfdt.getFunction();
|
||||||
if (function instanceof DatabaseObject) {
|
if (function.isDeleted()) {
|
||||||
if (!((DatabaseObject) function).checkIsValid()) {
|
// Cancel Editor.
|
||||||
// Cancel Editor.
|
provider.dispose();
|
||||||
provider.dispose();
|
PluginTool tool = ((StackEditorProvider) provider).getPlugin().getTool();
|
||||||
PluginTool tool = ((StackEditorProvider) provider).getPlugin().getTool();
|
tool.setStatusInfo("Stack Editor was closed for " + provider.getName());
|
||||||
tool.setStatusInfo("Stack Editor was closed for " + provider.getName());
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
StackFrame stack = function.getStackFrame();
|
StackFrame stack = function.getStackFrame();
|
||||||
StackFrameDataType newSfdt = new StackFrameDataType(stack, dtm);
|
StackFrameDataType newSfdt = new StackFrameDataType(stack, dtm);
|
||||||
|
@ -329,13 +324,10 @@ public class StackEditorPanel extends CompositeEditorPanel {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param localSizeField
|
|
||||||
*/
|
|
||||||
private void removeFocusListeners(JTextField textField) {
|
private void removeFocusListeners(JTextField textField) {
|
||||||
FocusListener[] fl = textField.getFocusListeners();
|
FocusListener[] fl = textField.getFocusListeners();
|
||||||
for (int i = 0; i < fl.length; i++) {
|
for (FocusListener element : fl) {
|
||||||
textField.removeFocusListener(fl[i]);
|
textField.removeFocusListener(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -568,7 +568,7 @@ public class SymbolTreeProvider extends ComponentProviderAdapter {
|
||||||
SymbolTreeRootNode rootNode = (SymbolTreeRootNode) tree.getModelRoot();
|
SymbolTreeRootNode rootNode = (SymbolTreeRootNode) tree.getModelRoot();
|
||||||
|
|
||||||
// the symbol may have been deleted while we are processing bulk changes
|
// the symbol may have been deleted while we are processing bulk changes
|
||||||
if (symbol.checkIsValid()) {
|
if (!symbol.isDeleted()) {
|
||||||
GTreeNode newNode = rootNode.symbolAdded(symbol);
|
GTreeNode newNode = rootNode.symbolAdded(symbol);
|
||||||
tree.refilterLater(newNode);
|
tree.refilterLater(newNode);
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,7 @@ public class SymbolTreeProvider extends ComponentProviderAdapter {
|
||||||
root.symbolRemoved(symbol, monitor);
|
root.symbolRemoved(symbol, monitor);
|
||||||
|
|
||||||
// the symbol may have been deleted while we are processing bulk changes
|
// the symbol may have been deleted while we are processing bulk changes
|
||||||
if (symbol.checkIsValid()) {
|
if (!symbol.isDeleted()) {
|
||||||
root.symbolAdded(symbol);
|
root.symbolAdded(symbol);
|
||||||
}
|
}
|
||||||
tree.refilterLater();
|
tree.refilterLater();
|
||||||
|
|
|
@ -379,7 +379,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public Symbol getValue(Symbol symbol, Settings settings, Program p,
|
public Symbol getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
|
@ -400,7 +400,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public Boolean getValue(Symbol symbol, Settings settings, Program p,
|
public Boolean getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return symbol.isPinned();
|
return symbol.isPinned();
|
||||||
|
@ -435,7 +435,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public ProgramLocation getProgramLocation(Symbol symbol, Settings settings, Program p,
|
public ProgramLocation getProgramLocation(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) {
|
ServiceProvider svcProvider) {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return symbol.getProgramLocation();
|
return symbol.getProgramLocation();
|
||||||
|
@ -454,7 +454,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public String getValue(Symbol symbol, Settings settings, Program p,
|
public String getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public String getValue(Symbol symbol, Settings settings, Program p,
|
public String getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public String getValue(Symbol symbol, Settings settings, Program p,
|
public String getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return symbol.getParentNamespace().getName(true);
|
return symbol.getParentNamespace().getName(true);
|
||||||
|
@ -580,7 +580,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
@Override
|
@Override
|
||||||
public Integer getValue(Symbol symbol, Settings settings, Program p,
|
public Integer getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Integer.valueOf(symbol.getReferenceCount());
|
return Integer.valueOf(symbol.getReferenceCount());
|
||||||
|
@ -612,7 +612,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
@Override
|
@Override
|
||||||
public Integer getValue(Symbol symbol, Settings settings, Program p,
|
public Integer getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public String getValue(Symbol symbol, Settings settings, Program p,
|
public String getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +702,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||||
public String getValue(Symbol symbol, Settings settings, Program p,
|
public String getValue(Symbol symbol, Settings settings, Program p,
|
||||||
ServiceProvider svcProvider) throws IllegalArgumentException {
|
ServiceProvider svcProvider) throws IllegalArgumentException {
|
||||||
|
|
||||||
if (!symbol.checkIsValid()) {
|
if (symbol.isDeleted()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
|
||||||
case ChangeManager.DOCR_SYMBOL_SCOPE_CHANGED:
|
case ChangeManager.DOCR_SYMBOL_SCOPE_CHANGED:
|
||||||
case ChangeManager.DOCR_SYMBOL_DATA_CHANGED:
|
case ChangeManager.DOCR_SYMBOL_DATA_CHANGED:
|
||||||
symbol = (Symbol) rec.getObject();
|
symbol = (Symbol) rec.getObject();
|
||||||
if (symbol.checkIsValid()) { // symbol may have been removed (e.g., parameter)
|
if (!symbol.isDeleted()) { // symbol may have been removed (e.g., parameter)
|
||||||
symProvider.symbolChanged(symbol);
|
symProvider.symbolChanged(symbol);
|
||||||
refProvider.symbolChanged(symbol);
|
refProvider.symbolChanged(symbol);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,22 +54,28 @@ public class UndefinedFunction implements Function {
|
||||||
frame = new StackFrameImpl(this);
|
frame = new StackFrameImpl(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* locates the function based on the location given at construction time.
|
* Identifies a <code>UndefinedFunction</code> based on the location given based upon the current
|
||||||
|
* listing disassembly at time of construction using a block model.
|
||||||
|
* @param program program to be searched
|
||||||
|
* @param address address within body of function
|
||||||
|
* @param monitor task monitor
|
||||||
|
* @return function or null if invalid parameters, not found, or cancelled
|
||||||
*/
|
*/
|
||||||
public static UndefinedFunction findFunction(Program program, Address address,
|
public static UndefinedFunction findFunction(Program program, Address address,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
if (program == null || address == null) {
|
if (program == null || address == null || monitor.isCancelled()) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor.isCancelled()) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first try to walk back up to the top of the function
|
// first try to walk back up to the top of the function
|
||||||
UndefinedFunction function = findFunctionUsingSimpleBlockModel(program, address, monitor);
|
UndefinedFunction function = findFunctionUsingSimpleBlockModel(program, address, monitor);
|
||||||
if (function != null) {
|
if (function != null || monitor.isCancelled()) {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package ghidra.program.database.util;
|
package ghidra.program.database;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
|
@ -17,14 +17,12 @@ package ghidra.program.database.symbol;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.ConcurrentModificationException;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.database.function.FunctionDB;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
@ -52,8 +50,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
program = createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
program = createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
||||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
namespaceManager = program.getNamespaceManager();
|
namespaceManager = program.getNamespaceManager();
|
||||||
|
@ -65,14 +63,14 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
addBlock("BlockTwo", addr(0x2000), 0x4000);
|
addBlock("BlockTwo", addr(0x2000), 0x4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
program.endTransaction(transactionID, true);
|
program.endTransaction(transactionID, true);
|
||||||
program.release(this);
|
program.release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateSubNamespace() throws Exception {
|
public void testCreateSubNamespace() throws Exception {
|
||||||
GhidraClass gc =
|
GhidraClass gc =
|
||||||
symbolMgr.createClass(globalNamespace, "classNamespace", SourceType.USER_DEFINED);
|
symbolMgr.createClass(globalNamespace, "classNamespace", SourceType.USER_DEFINED);
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
|
@ -85,9 +83,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
AddressSet set2 = new AddressSet();
|
AddressSet set2 = new AddressSet();
|
||||||
set2.addRange(addr(0x100), addr(0x130));
|
set2.addRange(addr(0x100), addr(0x130));
|
||||||
Function f2 =
|
Function f2 = functionMgr.createFunction("TextFunctionNamespace", addr(0x100), set2,
|
||||||
functionMgr.createFunction("TextFunctionNamespace", addr(0x100), set2,
|
SourceType.USER_DEFINED);
|
||||||
SourceType.USER_DEFINED);
|
|
||||||
f2.setParentNamespace(gc);
|
f2.setParentNamespace(gc);
|
||||||
|
|
||||||
assertTrue(gc.getBody().hasSameAddresses(set.union(set2)));
|
assertTrue(gc.getBody().hasSameAddresses(set.union(set2)));
|
||||||
|
@ -99,8 +96,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(f2, namespaceManager.getNamespaceContaining(addr(0x110)));
|
assertEquals(f2, namespaceManager.getNamespaceContaining(addr(0x110)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetBody() throws Exception {
|
public void testGetBody() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
|
@ -139,8 +136,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(gcSet.hasSameAddresses(newSet));
|
assertTrue(gcSet.hasSameAddresses(newSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFullName() throws Exception {
|
public void testFullName() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
|
@ -168,8 +165,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals("TestNamespaceClass::F3", f3.getName(true));
|
assertEquals("TestNamespaceClass::F3", f3.getName(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveNamespace() throws Exception {
|
public void testRemoveNamespace() throws Exception {
|
||||||
|
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
@ -206,22 +203,12 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0x100)));
|
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0x100)));
|
||||||
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0x255)));
|
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0x255)));
|
||||||
|
|
||||||
try {
|
Assert.assertTrue("Function 2 should be marked as deleted!", f2.isDeleted());
|
||||||
((FunctionDB) f2).checkDeleted();
|
Assert.assertTrue("Function 3 should be marked as deleted!", f3.isDeleted());
|
||||||
Assert.fail("Function 2 should be marked as deleted!");
|
|
||||||
}
|
|
||||||
catch (ConcurrentModificationException e) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
((FunctionDB) f3).checkDeleted();
|
|
||||||
Assert.fail("Function 3 should be marked as deleted!");
|
|
||||||
}
|
|
||||||
catch (ConcurrentModificationException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveNamespace() throws Exception {
|
public void testMoveNamespace() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
GhidraClass classNamespace2 =
|
GhidraClass classNamespace2 =
|
||||||
|
@ -252,8 +239,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(classNamespace3, f2.getParentNamespace());
|
assertEquals(classNamespace3, f2.getParentNamespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveAddressRange() throws Exception {
|
public void testMoveAddressRange() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -287,8 +274,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(f2.getBody().hasSameAddresses(set2));
|
assertTrue(f2.getBody().hasSameAddresses(set2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveAddressRange2() throws Exception {
|
public void testMoveAddressRange2() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -319,8 +306,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(f2.getBody().hasSameAddresses(set2));
|
assertTrue(f2.getBody().hasSameAddresses(set2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteAddressRange() throws Exception {
|
public void testDeleteAddressRange() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -344,8 +331,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0)));
|
assertEquals(globalNamespace, namespaceManager.getNamespaceContaining(addr(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsOverlappedNamespace() throws Exception {
|
public void testIsOverlappedNamespace() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -376,7 +363,6 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Assert.fail("Should overlap!");
|
Assert.fail("Should overlap!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
set2 = new AddressSet();
|
set2 = new AddressSet();
|
||||||
set.addRange(addr(0x200), addr(0x210));
|
set.addRange(addr(0x200), addr(0x210));
|
||||||
set.addRange(addr(0x55), addr(0xff));
|
set.addRange(addr(0x55), addr(0xff));
|
||||||
|
@ -386,8 +372,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNamespaceIteratorForOverlaps() throws Exception {
|
public void testNamespaceIteratorForOverlaps() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -438,8 +424,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNamespaceIteratorForOverlaps2() throws Exception {
|
public void testNamespaceIteratorForOverlaps2() throws Exception {
|
||||||
GhidraClass classNamespace =
|
GhidraClass classNamespace =
|
||||||
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
symbolMgr.createClass(null, "TestNamespaceClass", SourceType.USER_DEFINED);
|
||||||
|
|
||||||
|
@ -497,7 +483,8 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBlock(String name, Address addr, int length) throws Exception {
|
private void addBlock(String name, Address addr, int length) throws Exception {
|
||||||
program.getMemory().createInitializedBlock(name, addr, length, (byte) 0,
|
program.getMemory()
|
||||||
TaskMonitorAdapter.DUMMY_MONITOR, false);
|
.createInitializedBlock(name, addr, length, (byte) 0,
|
||||||
|
TaskMonitorAdapter.DUMMY_MONITOR, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1389,7 +1389,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
Symbol s = createSymbol(addr(100), "fred");
|
Symbol s = createSymbol(addr(100), "fred");
|
||||||
assertTrue(s.checkIsValid());
|
assertFalse(s.isDeleted());
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
set.addRange(addr(100), addr(150));
|
set.addRange(addr(100), addr(150));
|
||||||
|
@ -1400,11 +1400,11 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Parameter p = f.addParameter(new ParameterImpl(null, ByteDataType.dataType, program),
|
Parameter p = f.addParameter(new ParameterImpl(null, ByteDataType.dataType, program),
|
||||||
SourceType.DEFAULT);
|
SourceType.DEFAULT);
|
||||||
Symbol paramSym = p.getSymbol();
|
Symbol paramSym = p.getSymbol();
|
||||||
assertTrue(paramSym.checkIsValid());
|
assertFalse(paramSym.isDeleted());
|
||||||
|
|
||||||
listing.removeFunction(addr(100));
|
listing.removeFunction(addr(100));
|
||||||
|
|
||||||
assertTrue(!paramSym.checkIsValid());
|
assertTrue(paramSym.isDeleted());
|
||||||
|
|
||||||
Symbol s1 = st.getPrimarySymbol(addr(100));
|
Symbol s1 = st.getPrimarySymbol(addr(100));
|
||||||
assertNotNull(s1);
|
assertNotNull(s1);
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.database.code;
|
package ghidra.program.database.code;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
@ -80,12 +79,12 @@ public class DefaultDataCacheTest extends AbstractGenericTest {
|
||||||
assertTrue(cu instanceof Data);
|
assertTrue(cu instanceof Data);
|
||||||
DataDB data = (DataDB) cu;
|
DataDB data = (DataDB) cu;
|
||||||
assertTrue(!data.isDefined());
|
assertTrue(!data.isDefined());
|
||||||
assertTrue(!data.isInvalid());
|
assertTrue(!((Boolean) invokeInstanceMethod("isInvalid", data)));
|
||||||
AddressSet restrictedSet = new AddressSet(addr(0x1000), addr(0x1003));
|
AddressSet restrictedSet = new AddressSet(addr(0x1000), addr(0x1003));
|
||||||
Disassembler disassembler = Disassembler.getDisassembler(program, TaskMonitor.DUMMY, null);
|
Disassembler disassembler = Disassembler.getDisassembler(program, TaskMonitor.DUMMY, null);
|
||||||
AddressSetView disAddrs = disassembler.disassemble(addr(0x1000), restrictedSet);
|
AddressSetView disAddrs = disassembler.disassemble(addr(0x1000), restrictedSet);
|
||||||
assertTrue(!disAddrs.isEmpty());
|
assertTrue(!disAddrs.isEmpty());
|
||||||
assertTrue(!data.checkIsValid());
|
assertTrue(!((Boolean) invokeInstanceMethod("checkIsValid", data)));
|
||||||
assertNull(listing.getCodeUnitAt(addr(0x1001)));
|
assertNull(listing.getCodeUnitAt(addr(0x1001)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.model.util.AddressSetPropertyMap;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -615,7 +614,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
||||||
if (nsSymbol == null) {
|
if (nsSymbol == null) {
|
||||||
return false; // global namespace.
|
return false; // global namespace.
|
||||||
}
|
}
|
||||||
return !nsSymbol.checkIsValid();
|
return nsSymbol.isDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.util.Lock;
|
||||||
* been deleted. Instantiating an object will cause it to be added immediately to the associated
|
* been deleted. Instantiating an object will cause it to be added immediately to the associated
|
||||||
* cache.
|
* cache.
|
||||||
*/
|
*/
|
||||||
abstract public class DatabaseObject {
|
public abstract class DatabaseObject {
|
||||||
|
|
||||||
protected long key;
|
protected long key;
|
||||||
private volatile boolean deleted;
|
private volatile boolean deleted;
|
||||||
|
@ -41,7 +41,7 @@ abstract public class DatabaseObject {
|
||||||
* @param key database key to uniquely identify this object
|
* @param key database key to uniquely identify this object
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public DatabaseObject(@SuppressWarnings("rawtypes") DBObjectCache cache, long key) {
|
protected DatabaseObject(@SuppressWarnings("rawtypes") DBObjectCache cache, long key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
if (cache != null) {
|
if (cache != null) {
|
||||||
|
@ -64,17 +64,6 @@ abstract public class DatabaseObject {
|
||||||
deleted = true;
|
deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this object has been deleted. Note: once an object has been deleted, it will
|
|
||||||
* never be "refreshed". For example, if an object is ever deleted and is resurrected via an
|
|
||||||
* "undo", you will have get a fresh instance of the object.
|
|
||||||
*
|
|
||||||
* @return true if this object has been deleted.
|
|
||||||
*/
|
|
||||||
public boolean isDeleted() {
|
|
||||||
return deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Invalidate this object. This does not necessarily mean that this object can never be used
|
* Invalidate this object. This does not necessarily mean that this object can never be used
|
||||||
|
@ -101,21 +90,28 @@ abstract public class DatabaseObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if object is currently invalid. Calling checkIsValid may successfully refresh
|
* Returns true if object is currently invalid and must be validated prior to further use.
|
||||||
* object making it valid.
|
* An invalid object may result from a cache invalidation which corresponds to wide-spread
|
||||||
|
* record changes. A common situation where this can occur is an undo/redo operation
|
||||||
|
* against the underlying database. The methods {@link #checkIsValid()}, {@link #checkDeleted()},
|
||||||
|
* {@link #validate(Lock)} and {@link #isDeleted(Lock)} are methods which will force
|
||||||
|
* a re-validation if required.
|
||||||
*
|
*
|
||||||
* @see #checkIsValid()
|
* @return true if this object is invalid and must be re-validated, else false if object state
|
||||||
|
* is currently valid which may include a deleted state.
|
||||||
*/
|
*/
|
||||||
public boolean isInvalid() {
|
protected boolean isInvalid() {
|
||||||
return invalidateCount != getCurrentValidationCount();
|
return !deleted && invalidateCount != getCurrentValidationCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this object has been deleted, in which case any use of the object is not allowed.
|
* Checks if this object has been deleted, in which case any use of the object is not allowed.
|
||||||
|
* This method should be invoked before any modifications to the object are performed to
|
||||||
|
* ensure it still exists and is in a valid state.
|
||||||
*
|
*
|
||||||
* @throws ConcurrentModificationException if the object has been deleted from the database.
|
* @throws ConcurrentModificationException if the object has been deleted from the database.
|
||||||
*/
|
*/
|
||||||
public void checkDeleted() {
|
protected void checkDeleted() {
|
||||||
if (!checkIsValid()) {
|
if (!checkIsValid()) {
|
||||||
throw new ConcurrentModificationException("Object has been deleted.");
|
throw new ConcurrentModificationException("Object has been deleted.");
|
||||||
}
|
}
|
||||||
|
@ -125,9 +121,9 @@ abstract public class DatabaseObject {
|
||||||
* Check whether this object is still valid. If the object is invalid, the object will attempt
|
* Check whether this object is still valid. If the object is invalid, the object will attempt
|
||||||
* to refresh itself. If the refresh fails, the object will be marked as deleted.
|
* to refresh itself. If the refresh fails, the object will be marked as deleted.
|
||||||
*
|
*
|
||||||
* @return true if the object is valid.
|
* @return true if the object is valid, else false if deleted
|
||||||
*/
|
*/
|
||||||
public boolean checkIsValid() {
|
protected boolean checkIsValid() {
|
||||||
return checkIsValid(null);
|
return checkIsValid(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +136,7 @@ abstract public class DatabaseObject {
|
||||||
* @param record optional record which may be used to refresh invalid object
|
* @param record optional record which may be used to refresh invalid object
|
||||||
* @return true if the object is valid.
|
* @return true if the object is valid.
|
||||||
*/
|
*/
|
||||||
public boolean checkIsValid(DBRecord record) {
|
protected boolean checkIsValid(DBRecord record) {
|
||||||
if (deleted) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (isInvalid()) {
|
if (isInvalid()) {
|
||||||
setValid();// prevent checkIsValid recursion during refresh
|
setValid();// prevent checkIsValid recursion during refresh
|
||||||
if (!refresh(record)) {
|
if (!refresh(record)) {
|
||||||
|
@ -162,10 +155,10 @@ abstract public class DatabaseObject {
|
||||||
* invalid, then the lock will be used to refresh as needed.
|
* invalid, then the lock will be used to refresh as needed.
|
||||||
*
|
*
|
||||||
* @param lock the lock that will be used if the object needs to be refreshed.
|
* @param lock the lock that will be used if the object needs to be refreshed.
|
||||||
* @return true if object is valid, else false
|
* @return true if object is valid, else false if deleted
|
||||||
*/
|
*/
|
||||||
public boolean validate(Lock lock) {
|
protected boolean validate(Lock lock) {
|
||||||
if (!deleted && !isInvalid()) {
|
if (!isInvalid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
|
@ -177,6 +170,18 @@ abstract public class DatabaseObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this object has been deleted. Note: once an object has been deleted, it will
|
||||||
|
* never be "refreshed". For example, if an object is ever deleted and is resurrected via an
|
||||||
|
* "undo", you will have get a fresh instance of the object.
|
||||||
|
*
|
||||||
|
* @param lock object cache lock object
|
||||||
|
* @return true if this object has been deleted.
|
||||||
|
*/
|
||||||
|
public boolean isDeleted(Lock lock) {
|
||||||
|
return deleted || !validate(lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the object to refresh its state from the database.
|
* Tells the object to refresh its state from the database.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,8 +19,8 @@ import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import db.Field;
|
|
||||||
import db.DBRecord;
|
import db.DBRecord;
|
||||||
|
import db.Field;
|
||||||
import ghidra.program.database.DBObjectCache;
|
import ghidra.program.database.DBObjectCache;
|
||||||
import ghidra.program.database.DatabaseObject;
|
import ghidra.program.database.DatabaseObject;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
@ -92,8 +92,7 @@ class CategoryDB extends DatabaseObject implements Category {
|
||||||
}
|
}
|
||||||
mgr.lock.acquire();
|
mgr.lock.acquire();
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
if (!checkIsValid() || isRoot()) {
|
||||||
if (isRoot() || isDeleted()) {
|
|
||||||
categoryPath = CategoryPath.ROOT;
|
categoryPath = CategoryPath.ROOT;
|
||||||
}
|
}
|
||||||
if (categoryPath == null) {
|
if (categoryPath == null) {
|
||||||
|
|
|
@ -216,7 +216,7 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isDeleted() {
|
public boolean isDeleted() {
|
||||||
return !checkIsValid();
|
return isDeleted(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,6 +95,11 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
frame = new FunctionStackFrame(this);
|
frame = new FunctionStackFrame(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return isDeleted(manager.lock);
|
||||||
|
}
|
||||||
|
|
||||||
public void setValidationEnabled(boolean state) {
|
public void setValidationEnabled(boolean state) {
|
||||||
validateEnabled = state;
|
validateEnabled = state;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +110,12 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
entryPoint = functionSymbol.getAddress();
|
entryPoint = functionSymbol.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkDeleted() {
|
||||||
|
// expose method to function package
|
||||||
|
super.checkDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isThunk() {
|
public boolean isThunk() {
|
||||||
manager.lock.acquire();
|
manager.lock.acquire();
|
||||||
|
@ -853,8 +864,7 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
|
|
||||||
private void renumberParameterOrdinals() {
|
private void renumberParameterOrdinals() {
|
||||||
int ordinal = autoParams != null ? autoParams.size() : 0;
|
int ordinal = autoParams != null ? autoParams.size() : 0;
|
||||||
for (int i = 0; i < params.size(); i++) {
|
for (ParameterDB param : params) {
|
||||||
ParameterDB param = params.get(i);
|
|
||||||
param.setOrdinal(ordinal++);
|
param.setOrdinal(ordinal++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1096,21 +1106,18 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
loadVariables();
|
loadVariables();
|
||||||
ArrayList<Variable> list = new ArrayList<>();
|
ArrayList<Variable> list = new ArrayList<>();
|
||||||
if (autoParams != null) {
|
if (autoParams != null) {
|
||||||
for (int i = 0; i < autoParams.size(); i++) {
|
for (AutoParameterImpl p : autoParams) {
|
||||||
Parameter p = autoParams.get(i);
|
|
||||||
if (filter == null || filter.matches(p)) {
|
if (filter == null || filter.matches(p)) {
|
||||||
list.add(p);
|
list.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < params.size(); i++) {
|
for (ParameterDB p : params) {
|
||||||
Parameter p = params.get(i);
|
|
||||||
if (filter == null || filter.matches(p)) {
|
if (filter == null || filter.matches(p)) {
|
||||||
list.add(p);
|
list.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < locals.size(); i++) {
|
for (VariableDB var : locals) {
|
||||||
Variable var = locals.get(i);
|
|
||||||
if (filter == null || filter.matches(var)) {
|
if (filter == null || filter.matches(var)) {
|
||||||
list.add(var);
|
list.add(var);
|
||||||
}
|
}
|
||||||
|
@ -1140,15 +1147,13 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
loadVariables();
|
loadVariables();
|
||||||
ArrayList<Parameter> list = new ArrayList<>();
|
ArrayList<Parameter> list = new ArrayList<>();
|
||||||
if (autoParams != null) {
|
if (autoParams != null) {
|
||||||
for (int i = 0; i < autoParams.size(); i++) {
|
for (AutoParameterImpl p : autoParams) {
|
||||||
Parameter p = autoParams.get(i);
|
|
||||||
if (filter == null || filter.matches(p)) {
|
if (filter == null || filter.matches(p)) {
|
||||||
list.add(p);
|
list.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < params.size(); i++) {
|
for (ParameterDB p : params) {
|
||||||
Parameter p = params.get(i);
|
|
||||||
if (filter == null || filter.matches(p)) {
|
if (filter == null || filter.matches(p)) {
|
||||||
list.add(p);
|
list.add(p);
|
||||||
}
|
}
|
||||||
|
@ -1176,8 +1181,7 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
}
|
}
|
||||||
loadVariables();
|
loadVariables();
|
||||||
ArrayList<Variable> list = new ArrayList<>();
|
ArrayList<Variable> list = new ArrayList<>();
|
||||||
for (int i = 0; i < locals.size(); i++) {
|
for (VariableDB var : locals) {
|
||||||
Variable var = locals.get(i);
|
|
||||||
if (filter == null || filter.matches(var)) {
|
if (filter == null || filter.matches(var)) {
|
||||||
list.add(var);
|
list.add(var);
|
||||||
}
|
}
|
||||||
|
@ -1657,8 +1661,7 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
}
|
}
|
||||||
if (ordinal != params.size()) {
|
if (ordinal != params.size()) {
|
||||||
// shift params to make room for inserted param
|
// shift params to make room for inserted param
|
||||||
for (int i = 0; i < params.size(); i++) {
|
for (ParameterDB param : params) {
|
||||||
ParameterDB param = params.get(i);
|
|
||||||
int paramOrdinal = param.getOrdinal();
|
int paramOrdinal = param.getOrdinal();
|
||||||
if (paramOrdinal >= ordinal) {
|
if (paramOrdinal >= ordinal) {
|
||||||
param.setOrdinal(paramOrdinal + 1);
|
param.setOrdinal(paramOrdinal + 1);
|
||||||
|
|
|
@ -505,7 +505,7 @@ public class FunctionManagerDB implements FunctionManager {
|
||||||
try {
|
try {
|
||||||
FunctionDB func = cache.get(key);
|
FunctionDB func = cache.get(key);
|
||||||
if (func != null) {
|
if (func != null) {
|
||||||
func.checkIsValid();
|
func.checkDeleted();
|
||||||
func.createClassStructIfNeeded();
|
func.createClassStructIfNeeded();
|
||||||
func.updateParametersAndReturn();
|
func.updateParametersAndReturn();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.database.function;
|
package ghidra.program.database.function;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
@ -23,8 +24,6 @@ import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
class FunctionStackFrame implements StackFrame {
|
class FunctionStackFrame implements StackFrame {
|
||||||
|
|
||||||
// NOTE: Program stack frame may contain compound variables which have a stack component
|
// NOTE: Program stack frame may contain compound variables which have a stack component
|
||||||
|
@ -46,17 +45,17 @@ class FunctionStackFrame implements StackFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkIsValid() {
|
boolean checkIsValid() {
|
||||||
if (function.checkIsValid()) {
|
if (function.isDeleted()) {
|
||||||
if (invalid) {
|
return false;
|
||||||
stackGrowsNegative =
|
|
||||||
function.getFunctionManager().getProgram().getCompilerSpec().stackGrowsNegative();
|
|
||||||
variables = function.getVariables(VariableFilter.COMPOUND_STACK_VARIABLE_FILTER);
|
|
||||||
Arrays.sort(variables, StackVariableComparator.get());
|
|
||||||
invalid = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
if (invalid) {
|
||||||
|
stackGrowsNegative =
|
||||||
|
function.getFunctionManager().getProgram().getCompilerSpec().stackGrowsNegative();
|
||||||
|
variables = function.getVariables(VariableFilter.COMPOUND_STACK_VARIABLE_FILTER);
|
||||||
|
Arrays.sort(variables, StackVariableComparator.get());
|
||||||
|
invalid = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkDeleted() {
|
void checkDeleted() {
|
||||||
|
@ -101,9 +100,9 @@ class FunctionStackFrame implements StackFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (Parameter param : params) {
|
||||||
if (offset >= params[i].getLastStorageVarnode().getOffset()) {
|
if (offset >= param.getLastStorageVarnode().getOffset()) {
|
||||||
ordinal = params[i].getOrdinal();
|
ordinal = param.getOrdinal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,9 +158,9 @@ class FunctionStackFrame implements StackFrame {
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
ArrayList<Variable> list = new ArrayList<Variable>();
|
ArrayList<Variable> list = new ArrayList<Variable>();
|
||||||
for (int i = 0; i < variables.length; i++) {
|
for (Variable variable : variables) {
|
||||||
if (!(variables[i] instanceof Parameter)) {
|
if (!(variable instanceof Parameter)) {
|
||||||
list.add(variables[i]);
|
list.add(variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Variable[] vars = new Variable[list.size()];
|
Variable[] vars = new Variable[list.size()];
|
||||||
|
@ -182,9 +181,9 @@ class FunctionStackFrame implements StackFrame {
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
ArrayList<Parameter> list = new ArrayList<Parameter>();
|
ArrayList<Parameter> list = new ArrayList<Parameter>();
|
||||||
for (int i = 0; i < variables.length; i++) {
|
for (Variable variable : variables) {
|
||||||
if (variables[i] instanceof Parameter) {
|
if (variable instanceof Parameter) {
|
||||||
list.add((Parameter) variables[i]);
|
list.add((Parameter) variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Parameter[] vars = new Parameter[list.size()];
|
Parameter[] vars = new Parameter[list.size()];
|
||||||
|
@ -329,8 +328,8 @@ class FunctionStackFrame implements StackFrame {
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int i = 0; i < variables.length; i++) {
|
for (Variable variable : variables) {
|
||||||
if (variables[i] instanceof Parameter) {
|
if (variable instanceof Parameter) {
|
||||||
++cnt;
|
++cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import db.*;
|
||||||
import db.util.ErrorHandler;
|
import db.util.ErrorHandler;
|
||||||
import ghidra.program.database.*;
|
import ghidra.program.database.*;
|
||||||
import ghidra.program.database.external.ExternalManagerDB;
|
import ghidra.program.database.external.ExternalManagerDB;
|
||||||
import ghidra.program.database.function.FunctionDB;
|
|
||||||
import ghidra.program.database.map.AddressMap;
|
import ghidra.program.database.map.AddressMap;
|
||||||
import ghidra.program.database.symbol.*;
|
import ghidra.program.database.symbol.*;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
@ -638,13 +637,12 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
Function function = var.getFunction();
|
Function function = var.getFunction();
|
||||||
if (!(function instanceof FunctionDB) || function.getProgram() != program ||
|
if (function.getProgram() != program || function.isDeleted()) {
|
||||||
!((FunctionDB) function).checkIsValid()) {
|
|
||||||
return NO_REFS;
|
return NO_REFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolDB varSymbol = (SymbolDB) var.getSymbol();
|
SymbolDB varSymbol = (SymbolDB) var.getSymbol();
|
||||||
if (varSymbol != null && !varSymbol.checkIsValid()) {
|
if (varSymbol != null && varSymbol.isDeleted()) {
|
||||||
return NO_REFS;
|
return NO_REFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,17 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
||||||
lock = symbolMgr.getLock();
|
lock = symbolMgr.getLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return isDeleted(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkDeleted() {
|
||||||
|
// expose method to symbol package
|
||||||
|
super.checkDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName();
|
return getName();
|
||||||
|
|
|
@ -34,8 +34,8 @@ public class GlobalSymbol implements Symbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkIsValid() {
|
public boolean isDeleted() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -711,4 +711,11 @@ public interface Function extends Namespace {
|
||||||
* symbol will be removed.
|
* symbol will be removed.
|
||||||
*/
|
*/
|
||||||
public void promoteLocalUserLabelsToGlobal();
|
public void promoteLocalUserLabelsToGlobal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if this function object has been deleted. NOTE: the function could be
|
||||||
|
* deleted at anytime due to asynchronous activity.
|
||||||
|
* @return true if function has been deleted, false if not.
|
||||||
|
*/
|
||||||
|
public boolean isDeleted();
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ public interface Variable extends Comparable<Variable> {
|
||||||
/**
|
/**
|
||||||
* Returns the function that contains this Variable. May be null if the variable is not in
|
* Returns the function that contains this Variable. May be null if the variable is not in
|
||||||
* a function.
|
* a function.
|
||||||
|
* @return containing function or null
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public Function getFunction();
|
public Function getFunction();
|
||||||
|
@ -190,7 +191,7 @@ public interface Variable extends Comparable<Variable> {
|
||||||
/**
|
/**
|
||||||
* @return true if this is a simple variable consisting of a single register varnode
|
* @return true if this is a simple variable consisting of a single register varnode
|
||||||
* which will be returned by either the {@link #getFirstStorageVarnode()} or
|
* which will be returned by either the {@link #getFirstStorageVarnode()} or
|
||||||
* {@link getLastStorageVarnode()} methods. The register can be obtained using the
|
* {@link #getLastStorageVarnode()} methods. The register can be obtained using the
|
||||||
* {@link #getRegister()} method.
|
* {@link #getRegister()} method.
|
||||||
*/
|
*/
|
||||||
public boolean isRegisterVariable();
|
public boolean isRegisterVariable();
|
||||||
|
@ -262,11 +263,13 @@ public interface Variable extends Comparable<Variable> {
|
||||||
/**
|
/**
|
||||||
* @return the symbol associated with this variable or null if no symbol
|
* @return the symbol associated with this variable or null if no symbol
|
||||||
* associated. Certain dynamic variables such as auto-parameters do not
|
* associated. Certain dynamic variables such as auto-parameters do not
|
||||||
* have a symbol.
|
* have a symbol and will return null.
|
||||||
*/
|
*/
|
||||||
public Symbol getSymbol();
|
public Symbol getSymbol();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Determine is another variable is equivalent to this variable.
|
||||||
|
* @param variable other variable
|
||||||
* @return true if the specified variable is equivalent to this variable
|
* @return true if the specified variable is equivalent to this variable
|
||||||
*/
|
*/
|
||||||
public boolean isEquivalent(Variable variable);
|
public boolean isEquivalent(Variable variable);
|
||||||
|
|
|
@ -40,12 +40,6 @@ public interface Symbol {
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether this symbol is still valid (i.e., deleted).
|
|
||||||
* @return true if valid or false if deleted.
|
|
||||||
*/
|
|
||||||
public boolean checkIsValid();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the full path name for this symbol as an ordered array of strings ending
|
* Gets the full path name for this symbol as an ordered array of strings ending
|
||||||
* with the symbol name. The global symbol will return an empty array.
|
* with the symbol name. The global symbol will return an empty array.
|
||||||
|
@ -67,12 +61,14 @@ public interface Symbol {
|
||||||
public String getName(boolean includeNamespace);
|
public String getName(boolean includeNamespace);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the namespace that contains this symbol
|
* Return the parent namespace for this symbol.
|
||||||
|
* @return the namespace that contains this symbol.
|
||||||
*/
|
*/
|
||||||
public Namespace getParentNamespace();
|
public Namespace getParentNamespace();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns namespace symbol of the namespace containing this symbol
|
* Returns namespace symbol of the namespace containing this symbol
|
||||||
|
* @return parent namespace symbol
|
||||||
*/
|
*/
|
||||||
public Symbol getParentSymbol();
|
public Symbol getParentSymbol();
|
||||||
|
|
||||||
|
@ -84,14 +80,16 @@ public interface Symbol {
|
||||||
public boolean isDescendant(Namespace namespace);
|
public boolean isDescendant(Namespace namespace);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given parent is valid for this Symbol.
|
* Determines if the given parent is valid for this Symbol. Specified namespace
|
||||||
* @param parent
|
* must belong to the same symbol table as this symbol.
|
||||||
|
* @param parent prospective parent namespace for this symbol
|
||||||
* @return true if parent is valid
|
* @return true if parent is valid
|
||||||
*/
|
*/
|
||||||
public boolean isValidParent(Namespace parent);
|
public boolean isValidParent(Namespace parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the symbol type
|
* Returns this symbol's type
|
||||||
|
* @return symbol type
|
||||||
*/
|
*/
|
||||||
public SymbolType getSymbolType();
|
public SymbolType getSymbolType();
|
||||||
|
|
||||||
|
@ -273,4 +271,11 @@ public interface Symbol {
|
||||||
* @return the source of this symbol
|
* @return the source of this symbol
|
||||||
*/
|
*/
|
||||||
public SourceType getSource();
|
public SourceType getSource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if this symbol object has been deleted. NOTE: the symbol could be
|
||||||
|
* deleted at anytime due to asynchronous activity.
|
||||||
|
* @return true if symbol has been deleted, false if not.
|
||||||
|
*/
|
||||||
|
public boolean isDeleted();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,11 @@ public class FunctionTestDouble implements Function {
|
||||||
functionSignature = signature;
|
functionSignature = signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue