From 09a58af68ddb3ba6e8e3d4b8450e6f660c98d020 Mon Sep 17 00:00:00 2001 From: James <49045138+ghidracadabra@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:51:03 -0400 Subject: [PATCH] GP-6041 bsim h2 database script improvements --- .../AddProgramToH2BSimDatabaseScript.java | 12 ++++++++++- .../CreateH2BSimDatabaseScript.java | 8 ++++++++ .../features/bsim/gui/BSimServerManager.java | 20 +++++++++---------- .../BSim/BSimTutorial_Basic_Queries.md | 2 ++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java b/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java index c31ddf723d..f472aab69c 100644 --- a/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java +++ b/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java @@ -57,7 +57,7 @@ public class AddProgramToH2BSimDatabaseScript extends GhidraScript { if (currentProgram.isChanged()) { popup(currentProgram.getName() + " has unsaved changes. Please save the program" + - " before adding it to a BSim database."); + " before adding it to a BSim database."); return; } @@ -90,6 +90,16 @@ public class AddProgramToH2BSimDatabaseScript extends GhidraScript { h2Database.initialize(); DatabaseInformation dbInfo = h2Database.getInfo(); + // check whether the executable is already in the database + // before generating signatures + QueryExeInfo exeInfo = new QueryExeInfo(); + exeInfo.filterMd5 = currentProgram.getExecutableMD5(); + ResponseExe response = exeInfo.execute(h2Database); + if (response.recordCount > 0) { + popup(currentProgram.getName() + " is already in the database."); + return; + } + LSHVectorFactory vectorFactory = h2Database.getLSHVectorFactory(); GenSignatures gensig = null; try { diff --git a/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java b/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java index ac59924ef6..de23252eaa 100644 --- a/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java +++ b/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils; import ghidra.app.script.GhidraScript; import ghidra.features.base.values.GhidraValuesMap; +import ghidra.features.bsim.gui.BSimServerManager; import ghidra.features.bsim.query.*; import ghidra.features.bsim.query.FunctionDatabase.BSimError; import ghidra.features.bsim.query.description.DatabaseInformation; @@ -37,6 +38,7 @@ public class CreateH2BSimDatabaseScript extends GhidraScript { private static final String DATABASE_TEMPLATE = "Database Template"; private static final String FUNCTION_TAGS = "Function Tags (CSV)"; private static final String EXECUTABLE_CATEGORIES = "Executable Categories (CSV)"; + private static final String ADD_TO_MANAGER = "Add New Server to Server Manager"; private static final String[] templates = { "medium_nosize", "medium_32", "medium_64", "medium_cpool" }; @@ -54,6 +56,7 @@ public class CreateH2BSimDatabaseScript extends GhidraScript { values.defineChoice(DATABASE_TEMPLATE, "medium_nosize", templates); values.defineString(FUNCTION_TAGS); values.defineString(EXECUTABLE_CATEGORIES); + values.defineBoolean(ADD_TO_MANAGER, true); values.setValidator((valueMap, status) -> { String databaseName = valueMap.getString(NAME); @@ -86,6 +89,7 @@ public class CreateH2BSimDatabaseScript extends GhidraScript { String exeCatCSV = values.getString(EXECUTABLE_CATEGORIES); List cats = parseCSV(exeCatCSV); + boolean addToManager = values.getBoolean(ADD_TO_MANAGER); File dbFile = new File(dbDir, databaseName); BSimServerInfo serverInfo = new BSimServerInfo(dbFile.getAbsolutePath()); @@ -130,6 +134,10 @@ public class CreateH2BSimDatabaseScript extends GhidraScript { throw new LSHException(lastError.message); } } + if (addToManager) { + BSimServerManager serverManager = BSimServerManager.getBSimServerManager(); + serverManager.addServer(serverInfo); + } popup("Database " + values.getString(NAME) + " created successfully!"); } finally { diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java index 387c682b88..ad6161dc8f 100644 --- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java +++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java @@ -18,6 +18,7 @@ package ghidra.features.bsim.gui; import java.io.File; import java.io.IOException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import ghidra.features.bsim.gui.search.dialog.BSimServerManagerListener; @@ -30,7 +31,6 @@ import ghidra.framework.Application; import ghidra.framework.options.GProperties; import ghidra.framework.options.JSonProperties; import ghidra.util.Msg; -import ghidra.util.Swing; /** * Managers BSim database server definitions and connections @@ -43,14 +43,14 @@ public class BSimServerManager { * Get static singleton instance for BSimServerManager * @return BSimServerManager instance */ - static synchronized BSimServerManager getBSimServerManager() { + public static synchronized BSimServerManager getBSimServerManager() { if (instance == null) { instance = new BSimServerManager(); } return instance; } - private Set serverInfos = new HashSet<>(); + private Set serverInfos = ConcurrentHashMap.newKeySet(); private List listeners = new CopyOnWriteArrayList<>(); private BSimServerManager() { @@ -64,7 +64,7 @@ public class BSimServerManager { } /** - * Get list of defined servers. Method must be invoked from swing thread only. + * Get list of defined servers. * @return list of defined servers */ public Set getServerInfos() { @@ -130,7 +130,7 @@ public class BSimServerManager { } /** - * Add server to list. Method must be invoked from swing thread only. + * Add server to list. * @param newServerInfo new BSim DB server */ public void addServer(BSimServerInfo newServerInfo) { @@ -166,7 +166,7 @@ public class BSimServerManager { } /** - * Remove BSim DB server from list. Method must be invoked from swing thread only. + * Remove BSim DB server from list. * Specified server datasource will be dispose unless it is active or force is true. * @param info BSim DB server to be removed * @param force true if server datasource should be disposed even when active. @@ -192,11 +192,9 @@ public class BSimServerManager { } private void notifyServerListChanged() { - Swing.runLater(() -> { - for (BSimServerManagerListener listener : listeners) { - listener.serverListChanged(); - } - }); + for (BSimServerManagerListener listener : listeners) { + listener.serverListChanged(); + } } /** diff --git a/GhidraDocs/GhidraClass/BSim/BSimTutorial_Basic_Queries.md b/GhidraDocs/GhidraClass/BSim/BSimTutorial_Basic_Queries.md index 2652ebdc54..3e6d4c0000 100644 --- a/GhidraDocs/GhidraClass/BSim/BSimTutorial_Basic_Queries.md +++ b/GhidraDocs/GhidraClass/BSim/BSimTutorial_Basic_Queries.md @@ -4,6 +4,8 @@ In this section, we demonstrate some applications of our BSim database. ## Registering a BSim Database +**Note**: This step is not necessary if the **Add New Server to Server Manager** option was checked in ``CreateH2BSimDatabaseScript.java``. + In order to query the database, you must register it with Ghidra: 1. From The Code Browser, Select **BSim -> Manage Servers**.