mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch
'origin/GP-3195-dragonmacher-parallel-decomp-api-tweak' (Closes #5091)
This commit is contained in:
@@ -18,8 +18,7 @@ package ghidra.app.decompiler.parallel;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import generic.concurrent.QCallback;
|
import generic.concurrent.*;
|
||||||
import generic.concurrent.QResult;
|
|
||||||
import ghidra.app.util.DecompilerConcurrentQ;
|
import ghidra.app.util.DecompilerConcurrentQ;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
@@ -31,8 +30,8 @@ public class ParallelDecompiler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompile the given functions using multiple decompilers
|
* Decompile the given functions using multiple decompilers
|
||||||
*
|
*
|
||||||
* @param callback the callback to be called for each that is processed
|
* @param callback the callback to be called for each item that is processed
|
||||||
* @param program the program
|
* @param program the program
|
||||||
* @param addresses the addresses restricting which functions to decompile
|
* @param addresses the addresses restricting which functions to decompile
|
||||||
* @param monitor the task monitor
|
* @param monitor the task monitor
|
||||||
@@ -53,8 +52,8 @@ public class ParallelDecompiler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompile the given functions using multiple decompilers
|
* Decompile the given functions using multiple decompilers
|
||||||
*
|
*
|
||||||
* @param callback the callback to be called for each that is processed
|
* @param callback the callback to be called for each item that is processed
|
||||||
* @param functions the functions to decompile
|
* @param functions the functions to decompile
|
||||||
* @param monitor the task monitor
|
* @param monitor the task monitor
|
||||||
* @return the list of client results
|
* @return the list of client results
|
||||||
@@ -62,41 +61,40 @@ public class ParallelDecompiler {
|
|||||||
* @throws Exception if any other exception occurs
|
* @throws Exception if any other exception occurs
|
||||||
*/
|
*/
|
||||||
public static <R> List<R> decompileFunctions(QCallback<Function, R> callback,
|
public static <R> List<R> decompileFunctions(QCallback<Function, R> callback,
|
||||||
Collection<Function> functions,
|
Collection<Function> functions, TaskMonitor monitor)
|
||||||
TaskMonitor monitor)
|
|
||||||
throws InterruptedException, Exception {
|
throws InterruptedException, Exception {
|
||||||
|
|
||||||
List<R> results =
|
List<R> results =
|
||||||
doDecompileFunctions(callback, functions.iterator(), functions.size(),
|
doDecompileFunctions(callback, functions.iterator(), functions.size(), monitor);
|
||||||
monitor);
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompile the given functions using multiple decompilers.
|
* Decompile the given functions using multiple decompilers.
|
||||||
*
|
*
|
||||||
* <p>Results will be passed to the given consumer as they are produced. Calling this
|
* <p>Results will be passed to the given consumer as they are produced. Calling this
|
||||||
* method allows you to handle results as they are discovered.
|
* method allows you to handle results as they are discovered.
|
||||||
*
|
*
|
||||||
* <p><strong>This method will wait for all processing before returning.</strong>
|
* <p><strong>This method will wait for all processing before returning.</strong>
|
||||||
*
|
*
|
||||||
* @param callback the callback to be called for each that is processed
|
* @param callback the callback to be called for each that is processed
|
||||||
* @param program the program
|
* @param program the program
|
||||||
* @param functions the functions to decompile
|
* @param functions the functions to decompile
|
||||||
* @param resultsConsumer the consumer to which results will be passed
|
* @param resultsConsumer the consumer to which results will be passed
|
||||||
* @param monitor the task monitor
|
* @param monitor the task monitor
|
||||||
* @throws InterruptedException if interrupted
|
* @throws InterruptedException if interrupted
|
||||||
* @throws Exception if any other exception occurs
|
* @throws Exception if any other exception occurs
|
||||||
*/
|
*/
|
||||||
public static <R> void decompileFunctions(QCallback<Function, R> callback,
|
public static <R> void decompileFunctions(QCallback<Function, R> callback, Program program,
|
||||||
Program program,
|
Iterator<Function> functions, Consumer<R> resultsConsumer, TaskMonitor monitor)
|
||||||
Iterator<Function> functions, Consumer<R> resultsConsumer,
|
|
||||||
TaskMonitor monitor)
|
|
||||||
throws InterruptedException, Exception {
|
throws InterruptedException, Exception {
|
||||||
|
|
||||||
int max = program.getFunctionManager().getFunctionCount();
|
int max = program.getFunctionManager().getFunctionCount();
|
||||||
|
boolean collectResults = false; // the client will process results as they arrive
|
||||||
|
GThreadPool threadPool = GThreadPool.getSharedThreadPool(THREAD_POOL_NAME);
|
||||||
DecompilerConcurrentQ<Function, R> queue =
|
DecompilerConcurrentQ<Function, R> queue =
|
||||||
new DecompilerConcurrentQ<>(callback, THREAD_POOL_NAME, monitor);
|
new DecompilerConcurrentQ<>(callback, threadPool, collectResults, monitor);
|
||||||
|
|
||||||
monitor.initialize(max);
|
monitor.initialize(max);
|
||||||
queue.process(functions, resultsConsumer);
|
queue.process(functions, resultsConsumer);
|
||||||
queue.waitUntilDone();
|
queue.waitUntilDone();
|
||||||
@@ -130,14 +128,14 @@ public class ParallelDecompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an object that can be used to perform decompilation of a limited number of
|
* Creates an object that can be used to perform decompilation of a limited number of
|
||||||
* functions at a time, as opposed to working over an entire range of functions at once.
|
* functions at a time, as opposed to working over an entire range of functions at once.
|
||||||
* {@link #decompileFunctions(QCallback, Program, AddressSetView, TaskMonitor)} will create
|
* {@link #decompileFunctions(QCallback, Program, AddressSetView, TaskMonitor)} will create
|
||||||
* and tear down concurrent data structures on each use, making repeated calls less efficient.
|
* and tear down concurrent data structures on each use, making repeated calls less efficient.
|
||||||
* You would use this method when you wish to perform periodic work as results are returned
|
* You would use this method when you wish to perform periodic work as results are returned
|
||||||
* <b>and when using the callback mechanism is not sufficient</b> such as when ordering of
|
* <b>and when using the callback mechanism is not sufficient</b> such as when ordering of
|
||||||
* results is required.
|
* results is required.
|
||||||
*
|
*
|
||||||
* @param callback the callback required to perform work.
|
* @param callback the callback required to perform work.
|
||||||
* @param monitor the monitor used to report progress and to cancel
|
* @param monitor the monitor used to report progress and to cancel
|
||||||
* @return the parallel decompiler used for decompiling.
|
* @return the parallel decompiler used for decompiling.
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ import utility.function.Dummy;
|
|||||||
/**
|
/**
|
||||||
* A class to perform some of the boilerplate setup of the {@link ConcurrentQ} that is shared
|
* A class to perform some of the boilerplate setup of the {@link ConcurrentQ} that is shared
|
||||||
* amongst clients that perform decompilation in parallel.
|
* amongst clients that perform decompilation in parallel.
|
||||||
*
|
*
|
||||||
* <p>This class can be used in a blocking or non-blocking fashion.
|
* <p>This class can be used in a blocking or non-blocking fashion.
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>For blocking usage, call
|
* <li>For blocking usage, call
|
||||||
* one of the <u>{@code add}</u> methods to put items in the queue and then call
|
* one of the <u>{@code add}</u> methods to put items in the queue and then call
|
||||||
* {@link #waitForResults()}.</li>
|
* {@link #waitForResults()}.</li>
|
||||||
* <li>For non-blocking usage, simply call
|
* <li>For non-blocking usage, simply call
|
||||||
* {@link #process(Iterator, Consumer)}, passing the consumer of the results.</li>
|
* {@link #process(Iterator, Consumer)}, passing the consumer of the results.</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
* <p>
|
* <p>
|
||||||
@@ -50,22 +50,23 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
private Consumer<R> resultConsumer = Dummy.consumer();
|
private Consumer<R> resultConsumer = Dummy.consumer();
|
||||||
|
|
||||||
public DecompilerConcurrentQ(QCallback<I, R> callback, TaskMonitor monitor) {
|
public DecompilerConcurrentQ(QCallback<I, R> callback, TaskMonitor monitor) {
|
||||||
this(callback, AutoAnalysisManager.getSharedAnalsysThreadPool(), monitor);
|
this(callback, AutoAnalysisManager.getSharedAnalsysThreadPool(), true, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecompilerConcurrentQ(QCallback<I, R> callback, String threadPoolName,
|
public DecompilerConcurrentQ(QCallback<I, R> callback, String threadPoolName,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
this(callback, GThreadPool.getSharedThreadPool(threadPoolName), monitor);
|
this(callback, GThreadPool.getSharedThreadPool(threadPoolName), true, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecompilerConcurrentQ(QCallback<I, R> callback, GThreadPool pool, TaskMonitor monitor) {
|
public DecompilerConcurrentQ(QCallback<I, R> callback, GThreadPool pool, boolean collectResults,
|
||||||
|
TaskMonitor monitor) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
queue = new ConcurrentQBuilder<I, R>()
|
queue = new ConcurrentQBuilder<I, R>()
|
||||||
.setCollectResults(true)
|
.setCollectResults(collectResults)
|
||||||
.setThreadPool(pool)
|
.setThreadPool(pool)
|
||||||
.setMonitor(monitor)
|
.setMonitor(monitor)
|
||||||
.setListener(new InternalResultListener())
|
.setListener(new InternalResultListener())
|
||||||
.build(callback);
|
.build(callback);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
/**
|
/**
|
||||||
* Adds all items to the queue for processing. The results will be passed to the given consumer
|
* Adds all items to the queue for processing. The results will be passed to the given consumer
|
||||||
* as they are produced.
|
* as they are produced.
|
||||||
*
|
*
|
||||||
* @param functions the functions to process
|
* @param functions the functions to process
|
||||||
* @param consumer the results consumer
|
* @param consumer the results consumer
|
||||||
*/
|
*/
|
||||||
@@ -96,7 +97,7 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
/**
|
/**
|
||||||
* Waits for all results to be delivered. The client is responsible for processing the
|
* Waits for all results to be delivered. The client is responsible for processing the
|
||||||
* results and handling any exceptions that may have occurred.
|
* results and handling any exceptions that may have occurred.
|
||||||
*
|
*
|
||||||
* @return all results
|
* @return all results
|
||||||
* @throws InterruptedException if interrupted while waiting
|
* @throws InterruptedException if interrupted while waiting
|
||||||
*/
|
*/
|
||||||
@@ -110,10 +111,10 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for all work to finish. Any exception encountered will trigger all processing to
|
* Waits for all work to finish. Any exception encountered will trigger all processing to
|
||||||
* stop. If you wish for the work to continue despite exceptions, then use
|
* stop. If you wish for the work to continue despite exceptions, then use
|
||||||
* {@link #waitForResults()}.
|
* {@link #waitForResults()}.
|
||||||
*
|
*
|
||||||
* @throws InterruptedException if interrupted while waiting
|
* @throws InterruptedException if interrupted while waiting
|
||||||
* @throws Exception any exception that is encountered while processing items.
|
* @throws Exception any exception that is encountered while processing items.
|
||||||
*/
|
*/
|
||||||
@@ -131,9 +132,9 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls dispose on the queue being processed. Further, the call will block for up to
|
* Calls dispose on the queue being processed. Further, the call will block for up to
|
||||||
* <tt>timeoutSeconds</tt> while waiting for the queue to finish processing.
|
* <tt>timeoutSeconds</tt> while waiting for the queue to finish processing.
|
||||||
*
|
*
|
||||||
* @param timeoutSeconds the number of seconds to wait for the disposed queue to finish
|
* @param timeoutSeconds the number of seconds to wait for the disposed queue to finish
|
||||||
* processing
|
* processing
|
||||||
*/
|
*/
|
||||||
@@ -164,7 +165,7 @@ public class DecompilerConcurrentQ<I, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
// This code is an asynchronous callback. Handle the exception the same way as
|
// This code is an asynchronous callback. Handle the exception the same way as
|
||||||
// the waitXyz() method do, which is to shutdown the queue.
|
// the waitXyz() method do, which is to shutdown the queue.
|
||||||
Msg.error(this, "Unexpected exception getting Decompiler result", t);
|
Msg.error(this, "Unexpected exception getting Decompiler result", t);
|
||||||
queue.dispose();
|
queue.dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user