diff --git a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/autounstrip/AutoUnstripDialog.java b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/autounstrip/AutoUnstripDialog.java index 2f99d8a..c98dd9e 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/autounstrip/AutoUnstripDialog.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/autounstrip/AutoUnstripDialog.java @@ -174,7 +174,7 @@ private void updateUI() { taskMonitorComponent.setMessage(autoUnstripResponse.progress() + "%"); // Update status - statusLabel.setText("Status: " + autoUnstripResponse.status()); + statusLabel.setText("Status: " + getFriendlyStatusMessage(autoUnstripResponse.status())); // Handle error message - dynamically add/remove error panel if (autoUnstripResponse.error_message() != null && !autoUnstripResponse.error_message().isEmpty()) { @@ -187,6 +187,24 @@ private void updateUI() { updateResultsTable(); } + /** + * Convert API status values to user-friendly messages + */ + private String getFriendlyStatusMessage(String apiStatus) { + if (apiStatus == null) { + return "Unknown"; + } + + return switch (apiStatus) { + case "STARTED" -> "started auto unstrip..."; + case "IN_PROGRESS" -> "running auto unstrip..."; + case "COMPLETED" -> "completed auto unstrip"; + case "ERROR", "NOT_FOUND" -> "auto unstrip failed"; + case "CANCELLED" -> "auto unstrip was cancelled"; + default -> apiStatus; // Fallback to original if unknown + }; + } + private void updateResultsTable() { DefaultTableModel model = new DefaultTableModel(new Object[]{"Virtual Address", "Original Name", "New Name"}, 0); for (RenameResult result : renameResults) { diff --git a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/AbstractFunctionMatchingDialog.java b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/AbstractFunctionMatchingDialog.java index 223d47b..42e7ea3 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/AbstractFunctionMatchingDialog.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/AbstractFunctionMatchingDialog.java @@ -14,6 +14,7 @@ import ghidra.util.exception.InvalidInputException; import ghidra.util.task.TaskMonitorComponent; import ghidra.util.Msg; +import resources.ResourceManager; import javax.swing.*; import javax.swing.table.DefaultTableModel; @@ -164,7 +165,7 @@ protected void updateUI() { // Update status if (functionMatchingResponse.getStatus() != null) { - statusLabel.setText("Status: " + functionMatchingResponse.getStatus()); + statusLabel.setText("Status: " + getFriendlyStatusMessage(functionMatchingResponse.getStatus())); } // Handle error message - dynamically add/remove error panel @@ -326,8 +327,26 @@ protected void configurePercentageColumnSorting(int similarityColumnIndex, int c } } + /** + * Convert API status values to user-friendly messages + */ + protected String getFriendlyStatusMessage(String apiStatus) { + if (apiStatus == null) { + return "Unknown"; + } + + return switch (apiStatus) { + case "STARTED" -> "started function matching..."; + case "IN_PROGRESS" -> "running function matching..."; + case "COMPLETED" -> "completed function matching"; + case "ERROR", "NOT_FOUND" -> "function matching failed"; + case "CANCELLED" -> "function matching was cancelled"; + default -> apiStatus; // Fallback to original if unknown + }; + } + protected void handleError(String message) { - statusLabel.setText("Error occurred"); + statusLabel.setText("An error occurred, press 'Match Functions' again to retry"); showError(message); taskMonitorComponent.setMessage("Error"); } @@ -450,9 +469,19 @@ protected JPanel createButtonAndFilterPanel() { // Match button panel JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); JButton matchButton = new JButton("Match Functions"); + + // Add magnifying glass icon to the button + try { + Icon icon = ResourceManager.loadImage("images/magnifier.png"); + matchButton.setIcon(icon); + } catch (Exception e) { + // If icon loading fails, button will just show text without icon + } + matchButton.addActionListener(e -> onMatchButtonClicked()); buttonPanel.add(matchButton); + // Function filter panel JPanel functionFilterPanel = createFunctionFilterPanel(); @@ -727,6 +756,7 @@ protected void onMatchButtonClicked() { filterResults(); } + protected void onRenameAllButtonClicked() { batchRenameFunctions(functionMatchResults); importFunctionNames(functionMatchResults); diff --git a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/BinaryLevelFunctionMatchingDialog.java b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/BinaryLevelFunctionMatchingDialog.java index 82ac095..057f189 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/BinaryLevelFunctionMatchingDialog.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/BinaryLevelFunctionMatchingDialog.java @@ -47,6 +47,17 @@ protected void pollFunctionMatchingStatus() { functionMatchingResponse = revengService.getFunctionMatchingForAnalysis(programWithBinaryID.analysisID(), request); updateUI(); + // Check if we hit an error status + if (Objects.equals(functionMatchingResponse.getStatus(), "ERROR")) { + stopPolling(); + taskMonitorComponent.setVisible(false); + String errorMsg = functionMatchingResponse.getErrorMessage() != null && !functionMatchingResponse.getErrorMessage().isEmpty() + ? functionMatchingResponse.getErrorMessage() + : "Function matching returned an error status"; + handleError(errorMsg); + return; + } + // Check if we're done if (functionMatchingResponse.getProgress() != null && (functionMatchingResponse.getProgress() >= 100 || Objects.equals(functionMatchingResponse.getStatus(), "COMPLETED"))) { diff --git a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/FunctionLevelFunctionMatchingDialog.java b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/FunctionLevelFunctionMatchingDialog.java index c10a49c..a962048 100644 --- a/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/FunctionLevelFunctionMatchingDialog.java +++ b/src/main/java/ai/reveng/toolkit/ghidra/binarysimilarity/ui/functionmatching/FunctionLevelFunctionMatchingDialog.java @@ -63,6 +63,17 @@ protected void pollFunctionMatchingStatus() { functionMatchingResponse = revengService.getFunctionMatchingForFunction(request); updateUI(); + // Check if we hit an error status + if (Objects.equals(functionMatchingResponse.getStatus(), "ERROR")) { + stopPolling(); + taskMonitorComponent.setVisible(false); + String errorMsg = functionMatchingResponse.getErrorMessage() != null && !functionMatchingResponse.getErrorMessage().isEmpty() + ? functionMatchingResponse.getErrorMessage() + : "Function matching returned an error status"; + handleError(errorMsg); + return; + } + // Check if we're done if (functionMatchingResponse.getProgress() != null && (functionMatchingResponse.getProgress() >= 100 || Objects.equals(functionMatchingResponse.getStatus(), "COMPLETED"))) {