mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch
'origin/GT-0_ghidravore_fixing_missing_invalide_cache_method_in_FunctionTagManager' Conflicts: Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagsComponentProvider.java
This commit is contained in:
commit
6648cbb8cb
30 changed files with 695 additions and 613 deletions
|
@ -283,8 +283,9 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
manager.lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
return manager.getCodeManager().getComment(CodeUnit.REPEATABLE_COMMENT,
|
||||
getEntryPoint());
|
||||
return manager.getCodeManager()
|
||||
.getComment(CodeUnit.REPEATABLE_COMMENT,
|
||||
getEntryPoint());
|
||||
}
|
||||
finally {
|
||||
manager.lock.release();
|
||||
|
@ -301,8 +302,9 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
manager.lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
manager.getCodeManager().setComment(getEntryPoint(), CodeUnit.REPEATABLE_COMMENT,
|
||||
comment);
|
||||
manager.getCodeManager()
|
||||
.setComment(getEntryPoint(), CodeUnit.REPEATABLE_COMMENT,
|
||||
comment);
|
||||
}
|
||||
finally {
|
||||
manager.lock.release();
|
||||
|
@ -885,8 +887,9 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
}
|
||||
}
|
||||
}
|
||||
program.getBookmarkManager().setBookmark(getEntryPoint(), BookmarkType.ERROR,
|
||||
"Bad Variables Removed", "Removed " + badSymbols.size() + " bad variables");
|
||||
program.getBookmarkManager()
|
||||
.setBookmark(getEntryPoint(), BookmarkType.ERROR,
|
||||
"Bad Variables Removed", "Removed " + badSymbols.size() + " bad variables");
|
||||
for (Symbol s : badSymbols) {
|
||||
s.delete();
|
||||
}
|
||||
|
@ -2703,8 +2706,10 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
callFixupMap.remove(entryPoint);
|
||||
}
|
||||
else {
|
||||
if (program.getCompilerSpec().getPcodeInjectLibrary().getPayload(
|
||||
InjectPayload.CALLFIXUP_TYPE, name, null, null) == null) {
|
||||
if (program.getCompilerSpec()
|
||||
.getPcodeInjectLibrary()
|
||||
.getPayload(
|
||||
InjectPayload.CALLFIXUP_TYPE, name, null, null) == null) {
|
||||
Msg.warn(this, "Undefined CallFixup set at " + entryPoint + ": " + name);
|
||||
}
|
||||
callFixupMap.add(entryPoint, name);
|
||||
|
@ -2815,13 +2820,12 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
tag = tagManager.createFunctionTag(name, "");
|
||||
}
|
||||
|
||||
FunctionTagMappingAdapter mappingAdapter = tagManager.getFunctionTagMappingAdapter();
|
||||
if (mappingAdapter.getRecord(getID(), tag.getId()) == null) {
|
||||
mappingAdapter.createFunctionTagRecord(getID(), tag.getId());
|
||||
if (!tagManager.isTagApplied(getID(), tag.getId())) {
|
||||
tagManager.applyFunctionTag(getID(), tag.getId());
|
||||
|
||||
Address addr = getEntryPoint();
|
||||
program.setChanged(ChangeManager.DOCR_TAG_ADDED_TO_FUNCTION, addr, addr, null,
|
||||
null);
|
||||
program.setChanged(ChangeManager.DOCR_TAG_ADDED_TO_FUNCTION, addr, addr, tag,
|
||||
tag);
|
||||
}
|
||||
|
||||
// Add to local cache
|
||||
|
@ -2829,9 +2833,6 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
manager.dbError(e);
|
||||
}
|
||||
finally {
|
||||
endUpdate();
|
||||
manager.lock.release();
|
||||
|
@ -2853,13 +2854,12 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
|
||||
FunctionTagManagerDB tagManager =
|
||||
(FunctionTagManagerDB) manager.getFunctionTagManager();
|
||||
FunctionTagMappingAdapter mappingAdapter = tagManager.getFunctionTagMappingAdapter();
|
||||
boolean removed = mappingAdapter.removeFunctionTagRecord(getID(), tag.getId());
|
||||
boolean removed = tagManager.removeFunctionTag(getID(), tag.getId());
|
||||
|
||||
if (removed) {
|
||||
Address addr = getEntryPoint();
|
||||
program.setChanged(ChangeManager.DOCR_TAG_REMOVED_FROM_FUNCTION, addr, addr, null,
|
||||
null);
|
||||
program.setChanged(ChangeManager.DOCR_TAG_REMOVED_FROM_FUNCTION, addr, addr, tag,
|
||||
tag);
|
||||
|
||||
// Remove from the local cache.
|
||||
if (tags != null) {
|
||||
|
@ -2867,9 +2867,6 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
manager.dbError(e);
|
||||
}
|
||||
finally {
|
||||
endUpdate();
|
||||
manager.lock.release();
|
||||
|
|
|
@ -21,7 +21,8 @@ import java.util.function.Predicate;
|
|||
|
||||
import db.*;
|
||||
import generic.FilteredIterator;
|
||||
import ghidra.program.database.*;
|
||||
import ghidra.program.database.DBObjectCache;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.code.CodeManager;
|
||||
import ghidra.program.database.external.ExternalLocationDB;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
|
@ -48,7 +49,7 @@ import ghidra.util.task.TaskMonitor;
|
|||
* all function related calls are routed to this class.
|
||||
*
|
||||
*/
|
||||
public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
||||
public class FunctionManagerDB implements FunctionManager {
|
||||
|
||||
private final String CALLFIXUP_MAP = "CallFixup"; // string map used to store call-fixup name
|
||||
|
||||
|
@ -64,7 +65,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
private NamespaceManager namespaceMgr;
|
||||
private SymbolManager symbolMgr;
|
||||
private CodeManager codeMgr;
|
||||
private FunctionTagManager functionTagManager;
|
||||
private FunctionTagManagerDB functionTagManager;
|
||||
private Namespace globalNamespace;
|
||||
|
||||
private Predicate<Function> functionFilter = f -> {
|
||||
|
@ -352,7 +353,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
throw new IllegalArgumentException(
|
||||
"Function entryPoint may not be created on defined data");
|
||||
}
|
||||
|
||||
|
||||
if (namespaceMgr.overlapsNamespace(body) != null) {
|
||||
throw new OverlappingFunctionException(entryPoint);
|
||||
}
|
||||
|
@ -552,7 +553,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
|
||||
// Remove all tag mappings associated with this function
|
||||
for (FunctionTag tag : function.getTags()) {
|
||||
tag.delete();
|
||||
function.removeTag(tag.getName());
|
||||
}
|
||||
|
||||
long functionID = function.getID();
|
||||
|
@ -930,6 +931,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
public void invalidateCache(boolean all) {
|
||||
lock.acquire();
|
||||
try {
|
||||
functionTagManager.invalidateCache();
|
||||
callFixupMap = null;
|
||||
lastFuncID = -1;
|
||||
cache.invalidate();
|
||||
|
@ -996,14 +998,16 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
*/
|
||||
FunctionIteratorDB(boolean external, boolean forward) {
|
||||
if (external) {
|
||||
it = program.getSymbolTable().getSymbols(
|
||||
new AddressSet(AddressSpace.EXTERNAL_SPACE.getMinAddress(),
|
||||
AddressSpace.EXTERNAL_SPACE.getMaxAddress()),
|
||||
SymbolType.FUNCTION, forward);
|
||||
it = program.getSymbolTable()
|
||||
.getSymbols(
|
||||
new AddressSet(AddressSpace.EXTERNAL_SPACE.getMinAddress(),
|
||||
AddressSpace.EXTERNAL_SPACE.getMaxAddress()),
|
||||
SymbolType.FUNCTION, forward);
|
||||
}
|
||||
else {
|
||||
it = program.getSymbolTable().getSymbols(program.getMemory(), SymbolType.FUNCTION,
|
||||
forward);
|
||||
it = program.getSymbolTable()
|
||||
.getSymbols(program.getMemory(), SymbolType.FUNCTION,
|
||||
forward);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1144,8 +1148,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
list.add(symbol);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Symbol symbol = list.get(i);
|
||||
for (Symbol symbol : list) {
|
||||
symbol.delete();
|
||||
}
|
||||
}
|
||||
|
@ -1477,6 +1480,7 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionTagManager getFunctionTagManager() {
|
||||
return functionTagManager;
|
||||
}
|
||||
|
|
|
@ -53,9 +53,10 @@ public class FunctionTagDB extends DatabaseObject implements FunctionTag {
|
|||
comment = "";
|
||||
}
|
||||
|
||||
if (!comment.equals(record.getString(FunctionTagAdapter.COMMENT_COL))) {
|
||||
String oldValue = record.getString(FunctionTagAdapter.COMMENT_COL);
|
||||
if (!comment.equals(oldValue)) {
|
||||
record.setString(FunctionTagAdapter.COMMENT_COL, comment);
|
||||
mgr.updateFunctionTag(this);
|
||||
mgr.updateFunctionTag(this, oldValue, comment);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -77,9 +78,10 @@ public class FunctionTagDB extends DatabaseObject implements FunctionTag {
|
|||
name = "";
|
||||
}
|
||||
|
||||
if (!name.equals(record.getString(FunctionTagAdapter.NAME_COL))) {
|
||||
String oldValue = record.getString(FunctionTagAdapter.NAME_COL);
|
||||
if (!name.equals(oldValue)) {
|
||||
record.setString(FunctionTagAdapter.NAME_COL, name);
|
||||
mgr.updateFunctionTag(this);
|
||||
mgr.updateFunctionTag(this, oldValue, name);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
@ -137,7 +139,7 @@ public class FunctionTagDB extends DatabaseObject implements FunctionTag {
|
|||
// is null, use whatever is in the database.
|
||||
if (rec == null) {
|
||||
try {
|
||||
rec = mgr.getFunctionTagAdapter().getRecord(key);
|
||||
rec = mgr.getTagRecord(key);
|
||||
}
|
||||
catch (IOException e) {
|
||||
mgr.dbError(e);
|
||||
|
|
|
@ -18,6 +18,8 @@ package ghidra.program.database.function;
|
|||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.collections4.map.LazyMap;
|
||||
|
||||
import db.*;
|
||||
import db.util.ErrorHandler;
|
||||
import ghidra.program.database.DBObjectCache;
|
||||
|
@ -25,6 +27,7 @@ import ghidra.program.database.ProgramDB;
|
|||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.util.ChangeManager;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.datastruct.Counter;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -41,6 +44,8 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
|
||||
private DBObjectCache<FunctionTagDB> cache;
|
||||
|
||||
private Map<FunctionTag, Counter> tagCountCache;
|
||||
|
||||
protected final Lock lock;
|
||||
|
||||
/**
|
||||
|
@ -53,7 +58,7 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
* @throws VersionException if the database is incompatible with the current
|
||||
* schema
|
||||
* @throws IOException if there is a problem accessing the database.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if the program loading is cancelled
|
||||
*/
|
||||
FunctionTagManagerDB(DBHandle handle, int openMode, Lock lock, TaskMonitor monitor)
|
||||
throws VersionException, IOException, CancelledException {
|
||||
|
@ -62,10 +67,9 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
functionTagAdapter = FunctionTagAdapter.getAdapter(handle, openMode, monitor);
|
||||
functionTagMappingAdapter = FunctionTagMappingAdapter.getAdapter(handle, openMode, monitor);
|
||||
|
||||
cache = new DBObjectCache<FunctionTagDB>(100);
|
||||
cache = new DBObjectCache<>(100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgram(Program program) {
|
||||
this.program = (ProgramDB) program;
|
||||
}
|
||||
|
@ -172,21 +176,89 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
void updateFunctionTag(FunctionTagDB tag) throws IOException {
|
||||
boolean isTagApplied(long functionId, long tagId) {
|
||||
|
||||
lock.acquire();
|
||||
|
||||
try {
|
||||
return functionTagMappingAdapter.getRecord(functionId, tagId) != null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void applyFunctionTag(long functionId, long tagId) {
|
||||
lock.acquire();
|
||||
|
||||
try {
|
||||
FunctionTag tag = getFunctionTag(tagId);
|
||||
if (tag == null) {
|
||||
return; // shouldn't happen
|
||||
}
|
||||
|
||||
functionTagMappingAdapter.createFunctionTagRecord(functionId, tagId);
|
||||
incrementCountCache(tag);
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void incrementCountCache(FunctionTag tag) {
|
||||
if (tagCountCache != null) {
|
||||
tagCountCache.get(tag).count++;
|
||||
}
|
||||
}
|
||||
|
||||
private void decrementCountCache(FunctionTag tag) {
|
||||
if (tagCountCache != null) {
|
||||
tagCountCache.get(tag).count--;
|
||||
}
|
||||
}
|
||||
|
||||
boolean removeFunctionTag(long functionId, long tagId) {
|
||||
|
||||
lock.acquire();
|
||||
|
||||
try {
|
||||
FunctionTag tag = getFunctionTag(tagId);
|
||||
if (tag == null) {
|
||||
return false; // shouldn't happen
|
||||
}
|
||||
|
||||
if (functionTagMappingAdapter.removeFunctionTagRecord(functionId, tagId)) {
|
||||
decrementCountCache(tag);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateFunctionTag(FunctionTagDB tag, String oldValue, String newValue) throws IOException {
|
||||
|
||||
// Update the tag attributes.
|
||||
functionTagAdapter.updateRecord(tag.getRecord());
|
||||
|
||||
// Notify subscribers of the change.
|
||||
fireTagChangedNotification(ChangeManager.DOCR_FUNCTION_TAG_CHANGED, tag);
|
||||
fireTagChangedNotification(ChangeManager.DOCR_FUNCTION_TAG_CHANGED, tag, oldValue,
|
||||
newValue);
|
||||
invalidateFunctions();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* TODO: Be a bit smarter about this - if the cache contains all the tags in
|
||||
* the db we can just return the cache itself. If not, then go to the
|
||||
* db to get the remainder.
|
||||
*/
|
||||
@Override
|
||||
public List<? extends FunctionTag> getAllFunctionTags() {
|
||||
|
||||
|
@ -211,27 +283,25 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public FunctionTagAdapter getFunctionTagAdapter() {
|
||||
return functionTagAdapter;
|
||||
public Record getTagRecord(long id) throws IOException {
|
||||
return functionTagAdapter.getRecord(id);
|
||||
}
|
||||
|
||||
public FunctionTagMappingAdapter getFunctionTagMappingAdapter() {
|
||||
return functionTagMappingAdapter;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* PRIVATE METHODS
|
||||
*****************************************************************************/
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Sends a notification when a tag has been changed (edited or deleted).
|
||||
*
|
||||
* @param type {@link ChangeManager} change type
|
||||
* @param tag the tag that was changed
|
||||
* @throws IOException
|
||||
* @param oldValue the old value
|
||||
* @param newValue the new value
|
||||
*/
|
||||
private void fireTagChangedNotification(int type, FunctionTag tag) throws IOException {
|
||||
program.tagChanged(tag, type, null, null);
|
||||
private void fireTagChangedNotification(int type, FunctionTag tag, String oldValue,
|
||||
String newValue) {
|
||||
program.tagChanged(tag, type, oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,9 +309,8 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
*
|
||||
* @param type {@link ChangeManager} change type
|
||||
* @param tag the tag that was created
|
||||
* @throws IOException
|
||||
*/
|
||||
private void fireTagCreatedNotification(int type, FunctionTag tag) throws IOException {
|
||||
private void fireTagCreatedNotification(int type, FunctionTag tag) {
|
||||
program.tagCreated(tag, type);
|
||||
}
|
||||
|
||||
|
@ -250,10 +319,9 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
*
|
||||
* @param type the type of change
|
||||
* @param tag the tag that was deleted
|
||||
* @throws IOException
|
||||
*/
|
||||
private void fireTagDeletedNotification(int type, FunctionTag tag) throws IOException {
|
||||
program.tagChanged(tag, type, null, null);
|
||||
private void fireTagDeletedNotification(int type, FunctionTag tag) {
|
||||
program.tagChanged(tag, type, tag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,6 +343,7 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
* Deletes the given function tag.
|
||||
*
|
||||
* @param tag the tag to delete
|
||||
* @throws IOException if there is an issue reading from the db
|
||||
*/
|
||||
void doDeleteTag(FunctionTag tag) throws IOException {
|
||||
|
||||
|
@ -304,20 +373,56 @@ public class FunctionTagManagerDB implements FunctionTagManager, ErrorHandler {
|
|||
* Returns all function tags associated with the given function id.
|
||||
*
|
||||
* @param functionId the function id
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @return the tags
|
||||
* @throws IOException if there is an issue reading from the db
|
||||
*/
|
||||
Set<FunctionTag> getFunctionTagsByFunctionID(long functionId) throws IOException {
|
||||
Set<FunctionTag> tags = new HashSet<>();
|
||||
RecordIterator functionTagMappingRecords =
|
||||
RecordIterator functionRecords =
|
||||
functionTagMappingAdapter.getRecordsByFunctionID(functionId);
|
||||
|
||||
while (functionTagMappingRecords.hasNext()) {
|
||||
Record mappingRecord = functionTagMappingRecords.next();
|
||||
while (functionRecords.hasNext()) {
|
||||
Record mappingRecord = functionRecords.next();
|
||||
Record tagRecord = functionTagAdapter.getRecord(
|
||||
mappingRecord.getLongValue(FunctionTagMappingAdapter.TAG_ID_COL));
|
||||
tags.add(getFunctionTagFromCache(tagRecord));
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
void invalidateCache() {
|
||||
cache.invalidate();
|
||||
tagCountCache = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUseCount(FunctionTag tag) {
|
||||
lock.acquire();
|
||||
try {
|
||||
if (tagCountCache == null) {
|
||||
buildTagCountCache();
|
||||
}
|
||||
Counter counter = tagCountCache.get(tag);
|
||||
return counter.count;
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
return 0;
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildTagCountCache() throws IOException {
|
||||
Map<FunctionTag, Counter> map = LazyMap.lazyMap(new HashMap<>(), () -> new Counter());
|
||||
RecordIterator records = functionTagMappingAdapter.getRecords();
|
||||
while (records.hasNext()) {
|
||||
Record mappingRecord = records.next();
|
||||
long tagId = mappingRecord.getLongValue(FunctionTagMappingAdapter.TAG_ID_COL);
|
||||
FunctionTag tag = getFunctionTag(tagId);
|
||||
map.get(tag).count++;
|
||||
}
|
||||
tagCountCache = map;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ abstract class FunctionTagMappingAdapter {
|
|||
static final String TABLE_NAME = "Function Tag Map";
|
||||
|
||||
static final int CURRENT_VERSION = 0;
|
||||
|
||||
|
||||
static final int FUNCTION_ID_COL = 0;
|
||||
static final int TAG_ID_COL = 1;
|
||||
|
||||
|
@ -74,7 +74,7 @@ abstract class FunctionTagMappingAdapter {
|
|||
*
|
||||
* @param functionID index into the {@link SymbolTable} table
|
||||
* @return iterator of database records
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract RecordIterator getRecordsByFunctionID(long functionID) throws IOException;
|
||||
|
||||
|
@ -84,17 +84,17 @@ abstract class FunctionTagMappingAdapter {
|
|||
* @param functionID index into the {@link SymbolTable} table
|
||||
* @param tagID index into the {@link FunctionTagAdapter} table
|
||||
* @return null if not found
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract Record getRecord(long functionID, long tagID) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a new record with the given function and tag ID's.
|
||||
*
|
||||
* @param functionID
|
||||
* @param tagID
|
||||
* @param functionID the function's database id
|
||||
* @param tagID the FunctionTags database id
|
||||
* @return newly-created database record
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract Record createFunctionTagRecord(long functionID, long tagID)
|
||||
throws IOException;
|
||||
|
@ -106,7 +106,7 @@ abstract class FunctionTagMappingAdapter {
|
|||
* @param functionID index into the {@link SymbolTable} table
|
||||
* @param tagID index into the {@link FunctionTagAdapter} table
|
||||
* @return true if the remove was performed
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract boolean removeFunctionTagRecord(long functionID, long tagID)
|
||||
throws IOException;
|
||||
|
@ -116,16 +116,22 @@ abstract class FunctionTagMappingAdapter {
|
|||
* whenever a tag is being deleted from the system.
|
||||
*
|
||||
* @param tagID index into the {@link FunctionTagAdapter} table
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract void removeFunctionTagRecord(long tagID) throws IOException;
|
||||
|
||||
/**
|
||||
* Determine if the specified tag ID has been applied to a function
|
||||
* @param tagId tag ID
|
||||
* @param id tag ID
|
||||
* @return true if tag applied to one or more functions
|
||||
* @throws IOException
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
abstract boolean isTagAssigned(long id) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a RecordIterator over all the records in this table
|
||||
* @return a RecordIterator over all the records in this table
|
||||
* @throws IOException if database error occurs
|
||||
*/
|
||||
protected abstract RecordIterator getRecords() throws IOException;
|
||||
}
|
||||
|
|
|
@ -65,4 +65,9 @@ class FunctionTagMappingAdapterNoTable extends FunctionTagMappingAdapter {
|
|||
boolean isTagAssigned(long id) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecordIterator getRecords() throws IOException {
|
||||
return new EmptyRecordIterator();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ class FunctionTagMappingAdapterV0 extends FunctionTagMappingAdapter implements D
|
|||
return table.indexIterator(V0_FUNCTION_ID_COL, value, value, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecordIterator getRecords() throws IOException {
|
||||
if (table == null) {
|
||||
return new EmptyRecordIterator();
|
||||
}
|
||||
return table.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTagAssigned(long tagID) throws IOException {
|
||||
if (table == null) {
|
||||
|
|
|
@ -29,10 +29,7 @@ import ghidra.util.exception.InvalidInputException;
|
|||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Interface to define methods available on a function. Functions
|
||||
* have a single entry point.
|
||||
*
|
||||
*
|
||||
* Interface to define methods available on a function. Functions have a single entry point.
|
||||
*/
|
||||
public interface Function extends Namespace {
|
||||
|
||||
|
@ -110,8 +107,8 @@ public interface Function extends Namespace {
|
|||
public void setCallFixup(String name);
|
||||
|
||||
/**
|
||||
* Returns the current call-fixup name set on this instruction or null
|
||||
* if one has not been set.
|
||||
* Returns the current call-fixup name set on this instruction or null if one has not been set
|
||||
* @return the name
|
||||
*/
|
||||
public String getCallFixup();
|
||||
|
||||
|
@ -131,6 +128,7 @@ public interface Function extends Namespace {
|
|||
/**
|
||||
* Returns the function (same as plate) comment as an array of strings where
|
||||
* each item in the array is a line of text in the comment.
|
||||
* @return the comments
|
||||
*/
|
||||
public String[] getCommentAsArray();
|
||||
|
||||
|
@ -194,11 +192,15 @@ public interface Function extends Namespace {
|
|||
|
||||
/**
|
||||
* Set the return data-type and storage.
|
||||
* <p>NOTE: The storage and source are ignored if the function does not have custom storage enabled.
|
||||
* @param type
|
||||
* @param storage
|
||||
*
|
||||
* <p>NOTE: The storage and source are ignored if the function does not have custom storage
|
||||
* enabled.
|
||||
*
|
||||
* @param type the data type
|
||||
* @param storage the storage
|
||||
* @param source source to be combined with the overall signature source.
|
||||
* @throws InvalidInputException if data type is not a fixed length or storage is improperly sized
|
||||
* @throws InvalidInputException if data type is not a fixed length or storage is improperly
|
||||
* sized
|
||||
*/
|
||||
public void setReturn(DataType type, VariableStorage storage, SourceType source)
|
||||
throws InvalidInputException;
|
||||
|
@ -216,21 +218,22 @@ public interface Function extends Namespace {
|
|||
|
||||
/**
|
||||
* Get the function's signature.
|
||||
* <br><br>WARNING! It is important to note that the calling convention may not be properly retained
|
||||
* by the returned signature object if a non-generic calling convention is used by this function as
|
||||
* defined by the program's compiler specification.
|
||||
* <br><br>WARNING! It is important to note that the calling convention may not be properly
|
||||
* retained by the returned signature object if a non-generic calling convention is used by
|
||||
* this function as defined by the program's compiler specification.
|
||||
*
|
||||
* @param formalSignature if true only original raw types will be retained and
|
||||
* auto-params discarded (e.g., this, __return_storage_ptr__, etc.) within the returned
|
||||
* signature. If false, the effective signature will be returned where forced indirect
|
||||
* and auto-params are reflected in the signature. This option has no affect if the specified
|
||||
* function has custom storage enabled.
|
||||
*
|
||||
* @return the function's signature
|
||||
*/
|
||||
public FunctionSignature getSignature(boolean formalSignature);
|
||||
|
||||
/**
|
||||
* Return a string representation of the function signature
|
||||
*
|
||||
* @param formalSignature if true only original raw return/parameter types will be retained and
|
||||
* auto-params discarded (e.g., this, __return_storage_ptr__, etc.) within the returned
|
||||
* signature. If false, the effective signature will be returned where forced indirect
|
||||
|
@ -238,6 +241,7 @@ public interface Function extends Namespace {
|
|||
* function has custom storage enabled.
|
||||
* @param includeCallingConvention if true prototype will include call convention
|
||||
* declaration if known.
|
||||
* @return the prototype
|
||||
*/
|
||||
public String getPrototypeString(boolean formalSignature, boolean includeCallingConvention);
|
||||
|
||||
|
@ -464,6 +468,7 @@ public interface Function extends Namespace {
|
|||
* @param fromOrdinal from ordinal position using the current numbering
|
||||
* @param toOrdinal the final position of the specified parameter
|
||||
* @return parameter which was moved
|
||||
* @throws InvalidInputException if either ordinal is invalid
|
||||
* @deprecated The use of this method is discouraged. The function signature should generally be
|
||||
* adjusted with a single call to {@link #updateFunction(String, Variable, List, FunctionUpdateType, boolean, SourceType)}
|
||||
*/
|
||||
|
@ -520,7 +525,7 @@ public interface Function extends Namespace {
|
|||
|
||||
/**
|
||||
* Returns an array of all local and parameter variables
|
||||
* @return
|
||||
* @return the variables
|
||||
*/
|
||||
public Variable[] getAllVariables();
|
||||
|
||||
|
@ -533,6 +538,7 @@ public interface Function extends Namespace {
|
|||
* @return the Variable added to the program.
|
||||
* @throws DuplicateNameException if another local variable or parameter already
|
||||
* has that name.
|
||||
* @throws InvalidInputException if there is an error or conflict when resolving the variable
|
||||
*/
|
||||
public Variable addLocalVariable(Variable var, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException;
|
||||
|
@ -553,14 +559,16 @@ public interface Function extends Namespace {
|
|||
public void setBody(AddressSetView newBody) throws OverlappingFunctionException;
|
||||
|
||||
/**
|
||||
* Returns true if this function has a variable argument list (VarArgs).
|
||||
* Returns true if this function has a variable argument list (VarArgs)
|
||||
* @return true if this function has a variable argument list (VarArgs)
|
||||
*/
|
||||
public boolean hasVarArgs();
|
||||
|
||||
/**
|
||||
* Set whether parameters can be passed as a VarArg (variable argument list).
|
||||
* Set whether parameters can be passed as a VarArg (variable argument list)
|
||||
*
|
||||
* @param hasVarArgs true if this function has a variable argument list (ie printf(fmt, ...)).
|
||||
* @param hasVarArgs true if this function has a variable argument list
|
||||
* (e.g., printf(fmt, ...)).
|
||||
*/
|
||||
public void setVarArgs(boolean hasVarArgs);
|
||||
|
||||
|
@ -595,7 +603,7 @@ public interface Function extends Namespace {
|
|||
|
||||
/**
|
||||
* Set whether or not this function uses custom variable storage
|
||||
* @param hasCustomVariableStorage
|
||||
* @param hasCustomVariableStorage true if this function uses custom storage
|
||||
*/
|
||||
public void setCustomVariableStorage(boolean hasCustomVariableStorage);
|
||||
|
||||
|
|
|
@ -15,22 +15,29 @@
|
|||
*/
|
||||
package ghidra.program.model.listing;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.ManagerDB;
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.lang.PrototypeModel;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public interface FunctionManager {
|
||||
/**
|
||||
* The manager for functions
|
||||
*/
|
||||
public interface FunctionManager extends ManagerDB {
|
||||
|
||||
/**
|
||||
* Returns this manager's program
|
||||
* @return the program
|
||||
*/
|
||||
public Program getProgram();
|
||||
|
||||
/**
|
||||
|
@ -50,8 +57,8 @@ public interface FunctionManager {
|
|||
public PrototypeModel getDefaultCallingConvention();
|
||||
|
||||
/**
|
||||
* Gets the prototype model of the calling convention with the specified name in this program.
|
||||
*
|
||||
* Gets the prototype model of the calling convention with the specified name in this program
|
||||
* @param name the calling convention name
|
||||
* @return the named function calling convention prototype model or null.
|
||||
*/
|
||||
public PrototypeModel getCallingConvention(String name);
|
||||
|
@ -113,25 +120,28 @@ public interface FunctionManager {
|
|||
throws OverlappingFunctionException;
|
||||
|
||||
/**
|
||||
* Returns the total number of functions in the program including external functions.
|
||||
* Returns the total number of functions in the program including external functions
|
||||
* @return the count
|
||||
*/
|
||||
public int getFunctionCount();
|
||||
|
||||
/**
|
||||
* Remove a function defined at entryPoint.
|
||||
* Remove a function defined at entryPoint
|
||||
* @param entryPoint the entry point
|
||||
* @return true if the function was removed
|
||||
*/
|
||||
public boolean removeFunction(Address entryPoint);
|
||||
|
||||
/**
|
||||
* Get the function at entryPoint.
|
||||
*
|
||||
* @return null if there is no function at entryPoint.
|
||||
* Get the function at entryPoint
|
||||
* @param entryPoint the entry point
|
||||
* @return null if there is no function at entryPoint
|
||||
*/
|
||||
public Function getFunctionAt(Address entryPoint);
|
||||
|
||||
/**
|
||||
* Get the function which resides at the specified address or is referenced from the specified
|
||||
* address.
|
||||
* Get the function which resides at the specified address or is referenced from the specified
|
||||
* address
|
||||
*
|
||||
* @param address function address or address of pointer to a function.
|
||||
* @return referenced function or null
|
||||
|
@ -147,19 +157,18 @@ public interface FunctionManager {
|
|||
public Function getFunctionContaining(Address addr);
|
||||
|
||||
/**
|
||||
* Returns an iterator over all non-external functions in address (entry point) order.
|
||||
*
|
||||
* Returns an iterator over all non-external functions in address (entry point) order
|
||||
* @param forward true means to iterate in ascending address order
|
||||
* @return the iterator
|
||||
*/
|
||||
public FunctionIterator getFunctions(boolean forward);
|
||||
|
||||
/**
|
||||
* Get an iterator over non-external functions starting at an address and ordered by entry
|
||||
* address.
|
||||
* address
|
||||
*
|
||||
* @param start starting address
|
||||
* @param forward true means to iterate in ascending address order
|
||||
*
|
||||
* @return an iterator over functions.
|
||||
*/
|
||||
public FunctionIterator getFunctions(Address start, boolean forward);
|
||||
|
@ -176,9 +185,10 @@ public interface FunctionManager {
|
|||
|
||||
/**
|
||||
* Returns an iterator over all REAL functions in address (entry point) order (real functions
|
||||
* have instructions, and aren't stubs).
|
||||
* have instructions, and aren't stubs)
|
||||
*
|
||||
* @param forward true means to iterate in ascending address order
|
||||
* @return the iterator
|
||||
*/
|
||||
public FunctionIterator getFunctionsNoStubs(boolean forward);
|
||||
|
||||
|
@ -220,39 +230,6 @@ public interface FunctionManager {
|
|||
*/
|
||||
public boolean isInFunction(Address addr);
|
||||
|
||||
/**
|
||||
* @see ghidra.program.database.ManagerDB#moveAddressRange(ghidra.program.model.address.Address,
|
||||
* ghidra.program.model.address.Address, long, ghidra.util.task.TaskMonitor)
|
||||
*/
|
||||
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
||||
throws CancelledException;
|
||||
|
||||
/**
|
||||
* @see ghidra.program.database.ManagerDB#deleteAddressRange(ghidra.program.model.address.Address,
|
||||
* ghidra.program.model.address.Address, ghidra.util.task.TaskMonitor)
|
||||
*/
|
||||
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
|
||||
throws CancelledException;
|
||||
|
||||
/**
|
||||
* @see ghidra.program.database.ManagerDB#setProgram(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
public void setProgram(ProgramDB program);
|
||||
|
||||
/**
|
||||
* @param currentRevision TODO
|
||||
* @see ghidra.program.database.ManagerDB#programReady(int, int, ghidra.util.task.TaskMonitor)
|
||||
*/
|
||||
public void programReady(int openMode, int currentRevision, TaskMonitor monitor)
|
||||
throws IOException, CancelledException;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ghidra.program.database.ManagerDB#invalidateCache(boolean)
|
||||
*/
|
||||
public void invalidateCache(boolean all);
|
||||
|
||||
/**
|
||||
* Return an iterator over functions that overlap the given address set.
|
||||
*
|
||||
|
@ -268,10 +245,10 @@ public interface FunctionManager {
|
|||
* function. While this does not account for the actual instruction flow, it is hopefully
|
||||
* accurate enough for most situations.
|
||||
*
|
||||
* @param instrAddr
|
||||
* @param storageAddr
|
||||
* @param instrAddr the instruction address
|
||||
* @param storageAddr the storage address
|
||||
* @param size varnode size in bytes (1 is assumed if value <= 0)
|
||||
* @param isRead
|
||||
* @param isRead true if the reference is a read reference
|
||||
* @return referenced variable or null if one not found
|
||||
*/
|
||||
public Variable getReferencedVariable(Address instrAddr, Address storageAddr, int size,
|
||||
|
@ -284,4 +261,30 @@ public interface FunctionManager {
|
|||
*/
|
||||
public Function getFunction(long key);
|
||||
|
||||
/**
|
||||
* Returns the function tag manager
|
||||
* @return the function tag manager
|
||||
*/
|
||||
public FunctionTagManager getFunctionTagManager();
|
||||
|
||||
/**
|
||||
* Clears all data caches
|
||||
* @param all if false, some managers may not need to update their cache if they can
|
||||
* tell that its not necessary. If this flag is true, then all managers should clear
|
||||
* their cache no matter what.
|
||||
*/
|
||||
@Override
|
||||
public void invalidateCache(boolean all); // note: redeclared to not throw an exception
|
||||
|
||||
/**
|
||||
* Move all objects within an address range to a new location
|
||||
* @param fromAddr the first address of the range to be moved
|
||||
* @param toAddr the address where to the range is to be moved
|
||||
* @param length the number of addresses to move
|
||||
* @param monitor the task monitor to use in any upgrade operations
|
||||
* @throws CancelledException if the user cancelled the operation via the task monitor
|
||||
*/
|
||||
@Override
|
||||
void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
||||
throws CancelledException; // note: redeclared to not throw an AddressOverflowException
|
||||
}
|
||||
|
|
|
@ -18,39 +18,39 @@ package ghidra.program.model.listing;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface for managing function tags. Tags are simple objects consisting of
|
||||
* a name and an optional comment, which can be applied to functions in Ghidra.
|
||||
* Interface for managing function tags. Tags are simple objects consisting of a name and an
|
||||
* optional comment, which can be applied to functions.
|
||||
*
|
||||
* @see ghidra.program.database.function.FunctionTagAdapter FunctionTagAdapter
|
||||
* @see ghidra.program.database.function.FunctionTagMappingAdapter FunctionTagMappingAdapter
|
||||
* See ghidra.program.database.function.FunctionTagAdapter
|
||||
* See ghidra.program.database.function.FunctionTagMappingAdapter
|
||||
*/
|
||||
public interface FunctionTagManager {
|
||||
|
||||
/**
|
||||
* Returns the function tag with the given name.
|
||||
* Returns the function tag with the given name
|
||||
*
|
||||
* @param name the tag name
|
||||
* @return the function tag, or null if not found
|
||||
*/
|
||||
FunctionTag getFunctionTag(String name);
|
||||
public FunctionTag getFunctionTag(String name);
|
||||
|
||||
/**
|
||||
* Returns the function tag with the given database id.
|
||||
* Returns the function tag with the given database id
|
||||
*
|
||||
* @param id the tags database id
|
||||
* @return the function tag, or null if not found
|
||||
*/
|
||||
FunctionTag getFunctionTag(long id);
|
||||
public FunctionTag getFunctionTag(long id);
|
||||
|
||||
/**
|
||||
* Returns all function tags in the database.
|
||||
* Returns all function tags in the database
|
||||
*
|
||||
* @return list of function tags
|
||||
*/
|
||||
List<? extends FunctionTag> getAllFunctionTags();
|
||||
public List<? extends FunctionTag> getAllFunctionTags();
|
||||
|
||||
/**
|
||||
* Returns true if the given tag is assigned to a function.
|
||||
* Returns true if the given tag is assigned to a function
|
||||
*
|
||||
* @param name the tag name
|
||||
* @return true if assigned to a function
|
||||
|
@ -65,13 +65,12 @@ public interface FunctionTagManager {
|
|||
* @param comment the comment associated with the tag (optional)
|
||||
* @return the new function tag
|
||||
*/
|
||||
FunctionTag createFunctionTag(String name, String comment);
|
||||
public FunctionTag createFunctionTag(String name, String comment);
|
||||
|
||||
/**
|
||||
* Sets the program on this manager to allow the manager to persist changes
|
||||
* and notify subscribers.
|
||||
*
|
||||
* @param program the program
|
||||
* Returns the number of times the given tag has been applied to a function
|
||||
* @param tag the tag
|
||||
* @return the count
|
||||
*/
|
||||
void setProgram(Program program);
|
||||
public int getUseCount(FunctionTag tag);
|
||||
}
|
||||
|
|
|
@ -187,4 +187,8 @@ public class FunctionManagerTestDouble implements FunctionManager {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionTagManager getFunctionTagManager() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue