mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-5891: Include Debugger javadocs in the build.
This commit is contained in:
parent
483cd9a799
commit
ce96f8551d
51 changed files with 223 additions and 222 deletions
|
@ -18,6 +18,7 @@ apply from: "${rootProject.projectDir}/gradle/javaProject.gradle"
|
|||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-api'
|
||||
|
|
|
@ -38,8 +38,8 @@ public interface DebuggerPlatformService {
|
|||
* <p>
|
||||
* If the trace's current mapper is applicable to the object, it will be returned. Otherwise,
|
||||
* the service will query the opinions for a new mapper, as in
|
||||
* {@link #getNewMapper(TraceObject)} and set it as the current mapper before returning. If a
|
||||
* new mapper is set, the trace is also initialized for that mapper.
|
||||
* {@link #getNewMapper(Trace, TraceObject, long)} and set it as the current mapper before
|
||||
* returning. If a new mapper is set, the trace is also initialized for that mapper.
|
||||
*
|
||||
* @param trace the trace
|
||||
* @param object the object for which a mapper is desired
|
||||
|
|
|
@ -22,10 +22,6 @@ import ghidra.util.classfinder.ExtensionPoint;
|
|||
|
||||
/**
|
||||
* A factory for configuring and creating a Debugger-integrated emulator
|
||||
*
|
||||
* <p>
|
||||
* See {@link BytesDebuggerPcodeEmulatorFactory} for the default implementation. See the Taint
|
||||
* Analyzer for the archetype of alternative implementations.
|
||||
*/
|
||||
public interface DebuggerPcodeEmulatorFactory extends ExtensionPoint {
|
||||
// TODO: Config options, use ModelFactory as a model
|
||||
|
|
|
@ -20,10 +20,6 @@ import ghidra.pcode.exec.trace.TracePcodeMachine;
|
|||
/**
|
||||
* A Debugger-integrated emulator (or p-code machine)
|
||||
*
|
||||
* <p>
|
||||
* A common implementation is an emulator with concrete plus some auxiliary state. To realize such a
|
||||
* machine, please see {@link AuxDebuggerPcodeEmulator} and {@link AuxDebuggerEmulatorPartsFactory}.
|
||||
*
|
||||
* @param <T> the type of values in the machine's memory and registers
|
||||
*/
|
||||
public interface DebuggerPcodeMachine<T> extends TracePcodeMachine<T> {
|
||||
|
|
|
@ -26,8 +26,7 @@ import ghidra.trace.model.thread.TraceThread;
|
|||
* In addition to the trace "coordinates" encapsulated by {@link PcodeTraceAccess}, this
|
||||
* encapsulates the tool controlling a session and the session's target. This permits p-code
|
||||
* executor/emulator states to access target data and to access session data, e.g., data from mapped
|
||||
* static images. It supports the same method chain pattern as {@link PcodeTraceAccess}, but
|
||||
* starting with {@link DefaultPcodeDebuggerAccess}.
|
||||
* static images. It supports the same method chain pattern as {@link PcodeTraceAccess}.
|
||||
*/
|
||||
public interface PcodeDebuggerAccess extends PcodeTraceAccess {
|
||||
@Override
|
||||
|
|
|
@ -519,8 +519,10 @@ public interface Target {
|
|||
* be recorded into the trace <em>before</em> this method returns. If the request is
|
||||
* unsuccessful, this method throw an exception.
|
||||
*
|
||||
* @param address the starting address
|
||||
* @param data the bytes to write
|
||||
* @param platform the platform whose language defines the registers
|
||||
* @param thread the thread whose register to write
|
||||
* @param frame the frame level, usually 0.
|
||||
* @param value the register and value to write
|
||||
*/
|
||||
void writeRegister(TracePlatform platform, TraceThread thread, int frame, RegisterValue value);
|
||||
|
||||
|
@ -548,7 +550,7 @@ public interface Target {
|
|||
* @param thread if a register, the thread whose registers to examine
|
||||
* @param frame the frame level, usually 0.
|
||||
* @param address the address of the variable
|
||||
* @param size the size of the variable. Ignored for memory
|
||||
* @param length the size of the variable. Ignored for memory
|
||||
* @return true if the variable can be mapped to the target
|
||||
*/
|
||||
boolean isVariableExists(TracePlatform platform, TraceThread thread, int frame, Address address,
|
||||
|
@ -558,8 +560,7 @@ public interface Target {
|
|||
* @see #writeVariable(TracePlatform, TraceThread, int, Address, byte[])
|
||||
*/
|
||||
CompletableFuture<Void> writeVariableAsync(TracePlatform platform, TraceThread thread,
|
||||
int frame,
|
||||
Address address, byte[] data);
|
||||
int frame, Address address, byte[] data);
|
||||
|
||||
/**
|
||||
* Write a variable (memory or register) of the given thread or the process
|
||||
|
@ -571,7 +572,7 @@ public interface Target {
|
|||
* {@link #writeMemory(Address, byte[])}.
|
||||
*
|
||||
* @param thread the thread. Ignored (may be null) if address is in memory
|
||||
* @param frameLevel the frame, usually 0. Ignored if address is in memory
|
||||
* @param frame the frame, usually 0. Ignored if address is in memory
|
||||
* @param address the starting address
|
||||
* @param data the value to write
|
||||
*/
|
||||
|
@ -665,7 +666,8 @@ public interface Target {
|
|||
* This will first attempt to kill the target gracefully. In addition, and whether or not the
|
||||
* target is successfully terminated, the target will be dissociated from its trace, and the
|
||||
* target will be invalidated. To attempt only a graceful termination, check
|
||||
* {@link #collectActions(ActionName, ActionContext)} with {@link ActionName#KILL}.
|
||||
* {@link #collectActions(ActionName, ActionContext, ObjectArgumentPolicy)} with
|
||||
* {@link ActionName#KILL}.
|
||||
*/
|
||||
void forceTerminate();
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ public interface RemoteMethod {
|
|||
* Check the type of an argument.
|
||||
*
|
||||
* <p>
|
||||
* This is a hack, because {@link TraceObjectSchema} expects {@link TargetObject}, or a
|
||||
* This is a hack, because {@link TraceObjectSchema} expects {@link TraceObject}, or a
|
||||
* primitive. We instead need {@link TraceObject}. I'd add the method to the schema, except that
|
||||
* trace stuff is not in its dependencies.
|
||||
*
|
||||
|
|
|
@ -34,6 +34,7 @@ public interface TraceRmiAcceptor {
|
|||
*
|
||||
* @return the connection, if successful
|
||||
* @throws IOException if there was an error
|
||||
* @throws CancelledException if {@link #cancel()} is called, usually from the user canceling
|
||||
*/
|
||||
TraceRmiConnection accept() throws IOException, CancelledException;
|
||||
|
||||
|
@ -64,8 +65,8 @@ public interface TraceRmiAcceptor {
|
|||
*
|
||||
* <p>
|
||||
* If a different thread has called {@link #accept()}, it will fail. In this case, both
|
||||
* {@linkplain TraceRmiServiceListener#acceptCancelled(TraceRmiAcceptor)} and
|
||||
* {@linkplain TraceRmiServiceListener#acceptFailed(Exception)} may be invoked.
|
||||
* {@link TraceRmiServiceListener#acceptCancelled(TraceRmiAcceptor)} and
|
||||
* {@link TraceRmiServiceListener#acceptFailed(TraceRmiAcceptor, Exception)} may be invoked.
|
||||
*/
|
||||
void cancel();
|
||||
}
|
||||
|
|
|
@ -86,8 +86,9 @@ public interface TraceRmiServiceListener {
|
|||
*
|
||||
* <p>
|
||||
* The acceptor remains valid until one of three events occurs:
|
||||
* {@linkplain} #connected(TraceRmiConnection, ConnectMode, TraceRmiAcceptor)},
|
||||
* {@linkplain} #acceptCancelled(TraceRmiAcceptor)}, or {@linkplain} #acceptFailed(Exception)}.
|
||||
* {@link #connected(TraceRmiConnection, ConnectMode, TraceRmiAcceptor)},
|
||||
* {@link #acceptCancelled(TraceRmiAcceptor)}, or
|
||||
* {@link #acceptFailed(TraceRmiAcceptor, Exception)}.
|
||||
*
|
||||
* @param acceptor the acceptor waiting
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@ apply from: "${rootProject.projectDir}/gradle/helpProject.gradle"
|
|||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/hasProtobuf.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiHandler;
|
|||
import ghidra.app.services.InternalTraceRmiService;
|
||||
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
|
||||
|
@ -30,15 +29,14 @@ import ghidra.util.classfinder.ExtensionPoint;
|
|||
* A factory of launch offers
|
||||
*
|
||||
* <p>
|
||||
* Each factory is instantiated only once for the entire application, even when multiple tools are
|
||||
* open. Thus, {@link #init(PluginTool)} and {@link #dispose(PluginTool)} will be invoked for each
|
||||
* tool.
|
||||
* Each opinion is instantiated only once for the entire application, even when multiple tools are
|
||||
* open.
|
||||
*/
|
||||
public interface TraceRmiLaunchOpinion extends ExtensionPoint {
|
||||
/**
|
||||
* Register any options
|
||||
*
|
||||
* @param tool the tool
|
||||
* @param options the tool options
|
||||
*/
|
||||
default void registerOptions(Options options) {
|
||||
}
|
||||
|
@ -75,7 +73,7 @@ public interface TraceRmiLaunchOpinion extends ExtensionPoint {
|
|||
* @param plugin the Trace RMI launcher service plugin. <b>NOTE:</b> to get access to the Trace
|
||||
* RMI (connection) service, use the {@link InternalTraceRmiService}, so that the
|
||||
* offers can register the connection's resources. See
|
||||
* {@link TraceRmiHandler#registerResources(Collection)}. Resource registration is
|
||||
* {@link TraceRmiHandler#registerTerminals(Collection)}. Terminal registration is
|
||||
* required for the Disconnect button to completely terminate the back end.
|
||||
* @param program the current program. While this is not <em>always</em> used by the launcher,
|
||||
* it is implied that the user expects the debugger to do something with the current
|
||||
|
|
|
@ -18,6 +18,7 @@ apply from: "${rootProject.projectDir}/gradle/helpProject.gradle"
|
|||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger'
|
||||
|
|
|
@ -58,12 +58,12 @@ import ghidra.util.task.TaskMonitor;
|
|||
* <p>
|
||||
* The usage pattern is typically:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* StackUnwinder unwinder = new StackUnwinder(tool, coordinates.getPlatform());
|
||||
* for (AnalysisUnwoundFrame<WatchValue> frame : unwinder.frames(coordinates.frame(0), monitor)) {
|
||||
* // check and/or cache the frame
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Typically, a frame is sought either by its level or by its function. Once found, several
|
||||
|
|
|
@ -214,8 +214,8 @@ public class SymPcodeExecutorState implements PcodeExecutorState<Sym> {
|
|||
* <p>
|
||||
* There are two cases:
|
||||
* <ul>
|
||||
* <li>PC:Register => location is PC.reg.address
|
||||
* <li>PC:Deref => location is [Stack]:PC.offset
|
||||
* <li>{@code PC:Register => location is PC.reg.address}</li>
|
||||
* <li>{@code PC:Deref => location is [Stack]:PC.offset}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the address (stack offset or register) of the return address
|
||||
|
|
|
@ -419,16 +419,16 @@ public class UnwindAnalysis {
|
|||
* function return.</li>
|
||||
* <li>Examine the symbol in the program counter register. This gives the location (register
|
||||
* or stack offset) of the return address. This strategy should work whether or not a link
|
||||
* register is involved. See {@link SymPcodeExecutorState#computeAddressOfReturn()}.
|
||||
* register is involved. See {@link SymPcodeExecutorState#computeAddressOfReturn()}.</li>
|
||||
* <li>Examine the symbol in the stack pointer register, again. It should be a stack offset.
|
||||
* That offset is the "stack adjustment." See {@link UnwindInfo#adjust()},
|
||||
* {@link UnwindInfo#computeNextSp(Address)}, and
|
||||
* {@link SymPcodeExecutorState#computeStackDepth()}.
|
||||
* {@link SymPcodeExecutorState#computeStackDepth()}.</li>
|
||||
* <li>Search the registers for stack dereference symbols, creating an offset-register map.
|
||||
* This intersected with the same from entry to program counter is the saved registers map.
|
||||
* See {@link UnwindInfo#saved()},
|
||||
* {@link UnwindInfo#mapSavedRegisters(Address, SavedRegisterMap)}, and
|
||||
* {@link SymPcodeExecutorState#computeMapUsingRegisters()}.
|
||||
* {@link SymPcodeExecutorState#computeMapUsingRegisters()}.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
|
|
|
@ -115,7 +115,7 @@ public interface UnwoundFrame<T> {
|
|||
* assuming the callee has not saved that register to the stack.</li>
|
||||
* <li>The return address cannot be recovered. This happens when the function appears to be non
|
||||
* returning, or the analysis otherwise fails to recover the return address. In this case, this
|
||||
* method will throw an exception.
|
||||
* method will throw an exception.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @return the return address
|
||||
|
|
|
@ -93,7 +93,8 @@ public enum MiscellaneousUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses a value from 1 to 1<<64. Any value outside the range is "clipped" into the range.
|
||||
* Parses a value from 1 to {@code 1<<64}. Any value outside the range is "clipped" into the
|
||||
* range.
|
||||
*
|
||||
* <p>
|
||||
* Note that a returned value of 0 indicates 2 to the power 64, which is just 1 too high to fit
|
||||
|
|
|
@ -64,8 +64,7 @@ public enum DebuggerPcodeUtils {
|
|||
* A p-code parser that can resolve labels from a trace or its mapped programs.
|
||||
*/
|
||||
public static class LabelBoundPcodeParser extends ErrorCollectingPcodeParser {
|
||||
record ProgSym(String sourceName, String nm, Address address) {
|
||||
}
|
||||
record ProgSym(String sourceName, String nm, Address address) {}
|
||||
|
||||
private final DebuggerStaticMappingService mappings;
|
||||
private final DebuggerCoordinates coordinates;
|
||||
|
@ -447,8 +446,8 @@ public enum DebuggerPcodeUtils {
|
|||
* A p-code arithmetic on watch values
|
||||
*
|
||||
* <p>
|
||||
* This is just a composition of four arithmetics. Using Pair<A,Pair<B,Pair<C,D>> would be
|
||||
* unwieldy.
|
||||
* This is just a composition of four arithmetics. Using {@code Pair<A,Pair<B,Pair<C,D>>} would
|
||||
* be unwieldy.
|
||||
*/
|
||||
public enum WatchValuePcodeArithmetic implements PcodeArithmetic<WatchValue> {
|
||||
BIG_ENDIAN(BytesPcodeArithmetic.BIG_ENDIAN, LocationPcodeArithmetic.BIG_ENDIAN),
|
||||
|
|
|
@ -17,6 +17,7 @@ apply from: "${rootProject.projectDir}/gradle/javaProject.gradle"
|
|||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Framework-TraceModeling'
|
||||
|
|
|
@ -111,7 +111,6 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiec
|
|||
* @param size the size of the requested read
|
||||
* @param uninitialized the portion of the read that is uninitialized
|
||||
* @return the adjusted size of the read
|
||||
* @throws Exception to interrupt the emulator
|
||||
*/
|
||||
protected abstract int checkUninitialized(PcodeTraceDataAccess backing, Address start,
|
||||
int size, AddressSet uninitialized);
|
||||
|
|
|
@ -54,23 +54,28 @@ import ghidra.trace.model.thread.TraceThread;
|
|||
* new DefaultPcodeTraceAccess(trace.getPlatformManager().getHostPlatform(), 0, 0);
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>Typically invoked by a factory method for an emulator's shared executor state
|
||||
*
|
||||
* <pre>
|
||||
* PcodeTraceMemoryAccess sharedData = access.getDataForSharedState();
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>Typically invoked by a factory method for an emulator thread's local executor state
|
||||
*
|
||||
* <pre>
|
||||
* PcodeTraceRegisterAccess localData = access.getDataForLocalState(thread, 0);
|
||||
* </pre>
|
||||
*
|
||||
* </li>
|
||||
* <li>Typically invoked by an auxiliary emulator state piece
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* PcodeTracePropertyAccess<String> property = data.getPropertyAccess("MyProperty", String.class);
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public interface PcodeTraceAccess {
|
||||
|
|
|
@ -19,7 +19,6 @@ import generic.NestedIterator;
|
|||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a {@link TraceBaseCodeUnitsView} for a specific address space
|
||||
|
@ -64,20 +63,6 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
|
|||
return space.manager.getTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getThread()
|
||||
*/
|
||||
public TraceThread getThread() {
|
||||
return space.getThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getFrameLevel()
|
||||
*/
|
||||
public int getFrameLevel() {
|
||||
return space.getFrameLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#size()
|
||||
*/
|
||||
|
|
|
@ -115,30 +115,36 @@ import ghidra.util.task.TaskMonitor;
|
|||
* Here is the type hierarchy presented with notes regarding structural interface implementations:
|
||||
* <ul>
|
||||
* <li>{@link AbstractBaseDBTraceCodeUnitsView} structurally implements
|
||||
* {@link TraceBaseCodeUnitsView}</li>
|
||||
* {@link TraceBaseCodeUnitsView}
|
||||
* <ul>
|
||||
* <li>{@link AbstractComposedDBTraceCodeUnitsView}</li>
|
||||
* <li>{@link AbstractComposedDBTraceCodeUnitsView}
|
||||
* <ul>
|
||||
* <li>{@link DBTraceCodeUnitsView} nominally implements {@link TraceCodeUnitsView}</li>
|
||||
* <li>{@link DBTraceDataView} nominally implements {@link TraceDataView}</li>
|
||||
* <li>{@link DBTraceDefinedUnitsView} nominally implements {@link TraceDefinedUnitsView}</li>
|
||||
* </ul>
|
||||
* <li>{@link AbstractSingleDBTraceCodeUnitsView}</li>
|
||||
* </li>
|
||||
* <li>{@link AbstractSingleDBTraceCodeUnitsView}
|
||||
* <ul>
|
||||
* <li>{@link AbstractBaseDBTraceDefinedUnitsView} structurally implements
|
||||
* {@link TraceBaseDefinedUnitsView}</li>
|
||||
* {@link TraceBaseDefinedUnitsView}
|
||||
* <ul>
|
||||
* <li>{@link DBTraceDefinedDataView} nominally implements {@link TraceDefinedDataView}</li>
|
||||
* <li>{@link DBTraceInstructionsView} nominally implements {@link TraceInstructionsView}</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>{@link DBTraceUndefinedDataView} nominally implements {@link TraceUndefinedDataView}</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The view composition is not hierarchical, as each may represent a different combination, and one
|
||||
* type may appear in several compositions. The single-type views are named first, then the composed
|
||||
* views:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Instructions - single-type view</li>
|
||||
* <li>Defined Data - single-type view</li>
|
||||
|
|
|
@ -119,7 +119,7 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
|||
* Set the fields of this record
|
||||
*
|
||||
* @param platform the platform
|
||||
* @param dataType the data type
|
||||
* @param dataTypeID the data type id
|
||||
*/
|
||||
protected void set(InternalTracePlatform platform, long dataTypeID) {
|
||||
this.platformKey = platform.getIntKey();
|
||||
|
|
|
@ -240,7 +240,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
|||
* {@inheritDoc}
|
||||
*
|
||||
* This implementation differs in that the path is relative to this unit, even if it is not the
|
||||
* root. In {@link DataDB}, it appears the behavior is undefined if you call this on a non-root
|
||||
* root. In {@code DataDB}, it appears the behavior is undefined if you call this on a non-root
|
||||
* component.
|
||||
*/
|
||||
@Override
|
||||
|
|
|
@ -149,8 +149,8 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
|||
* Check the preceding unit and see if it can be extended to "create" the desired one
|
||||
*
|
||||
* <p>
|
||||
* For overwrite, the caller should first use
|
||||
* {@link #doAdjustExisting(Address, InstructionPrototype, Instruction)}.
|
||||
* For overwrite, the caller should first use *
|
||||
* {@link #doAdjustExisting(Address, Instruction)}.
|
||||
*
|
||||
* @param address the starting address of the instruction
|
||||
* @param protoInstr the prototype instruction
|
||||
|
@ -228,7 +228,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
|||
* If it encounters a delay-slotted instruction, it will recurse on the group, iterating in
|
||||
* reverse order.
|
||||
*
|
||||
* @param instructions the instructions to add
|
||||
* @param it the iterator of instructions to add
|
||||
* @param areDelaySlots true if the instructions are already reversed from being
|
||||
* delay-slotted
|
||||
* @return the last instruction added
|
||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.trace.model;
|
|||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* NOTE: This is used to mark <trace,snap>; regardless of whether that snapshot is actually in the
|
||||
* NOTE: This is used to mark (trace,snap) regardless of whether that snapshot is actually in the
|
||||
* database.... Cannot just use TraceSnapshot here.
|
||||
*/
|
||||
public class DefaultTraceSpan implements TraceSpan {
|
||||
|
|
|
@ -239,8 +239,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
|||
* This checks if any (snap, address) point within the given box is contained within some code
|
||||
* unit in this view.
|
||||
*
|
||||
* @param span the span of snaps
|
||||
* @param range the address range
|
||||
* @param range the address-snap range
|
||||
* @return true if intersecting, false otherwise
|
||||
*/
|
||||
boolean intersectsRange(TraceAddressSnapRange range);
|
||||
|
|
|
@ -216,7 +216,6 @@ public interface TraceSymbolWithLocationView<T extends TraceSymbol> extends Trac
|
|||
* Check if this view contains any symbols at the given point.
|
||||
*
|
||||
* @param snap the snapshot key
|
||||
* @param thread the thread, if in register space
|
||||
* @param address the address of the symbols
|
||||
* @param includeDynamicSymbols true to include dynamically-generated symbols
|
||||
* @return true if any symbols in this view satisfy the query
|
||||
|
|
|
@ -72,9 +72,9 @@ import ghidra.trace.model.thread.TraceThread;
|
|||
* <ol>
|
||||
* <li><b>The object itself:</b> Test if the context target object supports the desired interface.
|
||||
* If it does, take it.</li>
|
||||
* <li><b>Aggregate objects:</b> If the object is marked with {@link TraceAggregate}, collect
|
||||
* all attributes supporting the desired interface. If there are any, take them. This step is
|
||||
* applied recursively if any child attribute is also marked with {@link TraceAggregate}.</li>
|
||||
* <li><b>Aggregate objects:</b> If the object is marked with {@link TraceAggregate}, collect all
|
||||
* attributes supporting the desired interface. If there are any, take them. This step is applied
|
||||
* recursively if any child attribute is also marked with {@link TraceAggregate}.</li>
|
||||
* <li><b>Ancestry:</b> Apply these same steps to the object's (canonical) parent, recursively.</li>
|
||||
* </ol>
|
||||
*
|
||||
|
@ -92,44 +92,52 @@ import ghidra.trace.model.thread.TraceThread;
|
|||
* may be presented by a user-space debugger for a desktop operating system:
|
||||
*
|
||||
* <ul>
|
||||
* <li>"Session" : {@link TraceObject}</li>
|
||||
* <li>"Session" : {@link TraceObject}
|
||||
* <ul>
|
||||
* <li>"Process 789" : {@link TraceProcess}, {@link TraceAggregate}</li>
|
||||
* <li>"Process 789" : {@link TraceProcess}, {@link TraceAggregate}
|
||||
* <ul>
|
||||
* <li>"Threads" : {@link TraceObject}</li>
|
||||
* <li>"Threads" : {@link TraceObject}
|
||||
* <ul>
|
||||
* <li>"Thread 1" : {@link TraceThread}, {@link TraceExecutionStateful},
|
||||
* {@link TraceAggregate}</li>
|
||||
* <li>"Thread 1" : {@link TraceThread}, {@link TraceExecutionStateful}, {@link TraceAggregate}
|
||||
* <ul>
|
||||
* <li>"Registers" : {@link TraceRegisterContainer}</li>
|
||||
* <li>"Registers" : {@link TraceRegisterContainer}
|
||||
* <ul>
|
||||
* <li>"r1" : {@link TraceRegister}</li>
|
||||
* <li>...</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>...more threads</li>
|
||||
* </ul>
|
||||
* <li>"Memory" : {@link TraceMemory}</li>
|
||||
* </li>
|
||||
* <li>"Memory" : {@link TraceMemory}
|
||||
* <ul>
|
||||
* <li>"[0x00400000:0x00401234]" : {@link TraceMemoryRegion}</li>
|
||||
* <li>...more regions</li>
|
||||
* </ul>
|
||||
* <li>"Modules" : {@link TraceObject}</li>
|
||||
* </li>
|
||||
* <li>"Modules" : {@link TraceObject}
|
||||
* <ul>
|
||||
* <li>"/usr/bin/echo" : {@link TraceModule}</li>
|
||||
* <li>"/usr/bin/echo" : {@link TraceModule}
|
||||
* <ul>
|
||||
* <li>".text" : {@link TraceSection}</li>
|
||||
* <li>...more sections</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>...more modules</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <li>"Environment": {@link TraceEnvironment}</li>
|
||||
* </li>
|
||||
* <li>"Environment": {@link TraceEnvironment}
|
||||
* <ul>
|
||||
* <li>"Process 321" : {@link TraceObject}</li>
|
||||
* <li>...more processes</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
|
|
|
@ -390,13 +390,13 @@ public interface TraceObjectSchema {
|
|||
* path. Thus, for a path of length n, the resulting list has n+1 entries. This is useful for
|
||||
* searches along the ancestry of a given path:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* List<TargetObjectSchema> schemas = getSuccessorSchemas(path);
|
||||
* for (; path != null; path = PathUtils.parent(path)) {
|
||||
* TargetObjectSchema schema = schemas.get(path.size());
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* All entries are non-null, though they may be {@link PrimitiveTraceObjectSchema#VOID}.
|
||||
|
@ -1009,17 +1009,17 @@ public interface TraceObjectSchema {
|
|||
*
|
||||
* <p>
|
||||
* This places some conventional restrictions / expectations on models where registers are given
|
||||
* on a frame-by-frame basis. The schema should present the {@link TraceRegisterContainer}
|
||||
* as the same object or a successor to {@link TraceStackFrame}, which must in turn be a
|
||||
* successor to {@link TraceStack}. The frame level (an index) must be in the path from stack to
|
||||
* frame. There can be no wildcards between the frame and the register container. For example,
|
||||
* the container for {@code Threads[1]} may be {@code Threads[1].Stack[n].Registers}, where
|
||||
* on a frame-by-frame basis. The schema should present the {@link TraceRegisterContainer} as
|
||||
* the same object or a successor to {@link TraceStackFrame}, which must in turn be a successor
|
||||
* to {@link TraceStack}. The frame level (an index) must be in the path from stack to frame.
|
||||
* There can be no wildcards between the frame and the register container. For example, the
|
||||
* container for {@code Threads[1]} may be {@code Threads[1].Stack[n].Registers}, where
|
||||
* {@code n} is the frame level. {@code Threads[1].Stack} would have the {@link TraceStack}
|
||||
* interface, {@code Threads[1].Stack[0]} would have the {@link TraceStackFrame} interface, and
|
||||
* {@code Threads[1].Stack[0].Registers} would have the {@link TraceRegisterContainer}
|
||||
* interface. Note it is not sufficient for {@link TraceRegisterContainer} to be a
|
||||
* successor of {@link TraceStack} with a single index between. There <em>must</em> be an
|
||||
* intervening {@link TraceStackFrame}, and the frame level (index) must precede it.
|
||||
* interface. Note it is not sufficient for {@link TraceRegisterContainer} to be a successor of
|
||||
* {@link TraceStack} with a single index between. There <em>must</em> be an intervening
|
||||
* {@link TraceStackFrame}, and the frame level (index) must precede it.
|
||||
*
|
||||
* @param frameLevel the frame level. May be ignored if not applicable
|
||||
* @param path the path of the seed object relative to the root
|
||||
|
|
|
@ -1418,12 +1418,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
|
|||
.create(Lifespan.nowOn(0), b.language.getRegister("r4"), LongDataType.dataType);
|
||||
}
|
||||
|
||||
assertEquals(thread, regCode.codeUnits().getThread());
|
||||
assertEquals(thread, regCode.data().getThread());
|
||||
assertEquals(thread, regCode.definedUnits().getThread());
|
||||
assertEquals(thread, regCode.instructions().getThread());
|
||||
assertEquals(thread, regCode.definedData().getThread());
|
||||
assertEquals(thread, regCode.undefinedData().getThread());
|
||||
assertEquals(thread, regCode.getThread());
|
||||
|
||||
assertEquals(List.of(dR4), list(regCode.definedUnits().get(0, true)));
|
||||
|
||||
|
@ -1441,7 +1436,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
|
|||
}
|
||||
|
||||
assertEquals(1, frameCode.getFrameLevel());
|
||||
assertEquals(thread, frameCode.codeUnits().getThread());
|
||||
assertEquals(thread, frameCode.getThread());
|
||||
assertEquals(List.of(dR5), list(frameCode.definedUnits().get(0, true)));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ apply from: "${rootProject.projectDir}/gradle/javaProject.gradle"
|
|||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug ProposedUtils'
|
||||
|
|
|
@ -40,7 +40,10 @@ import ghidra.graph.*;
|
|||
* <p>
|
||||
* A-->B-->D, A-->C-->D yields either [A, B, C, D] or [A, C, B, D]
|
||||
*
|
||||
* @see {@link https://en.wikipedia.org/wiki/Topological_sorting}
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Topological_sorting">Wikipedia: Topological
|
||||
* Sorting</a>
|
||||
* @param <V> the type of vector
|
||||
* @param <E> the type of edge
|
||||
*/
|
||||
public class TopologicalSorter<V, E extends GEdge<V>> {
|
||||
private final GDirectedGraph<V, E> graph;
|
||||
|
@ -53,7 +56,7 @@ public class TopologicalSorter<V, E extends GEdge<V>> {
|
|||
*
|
||||
* @param graph the graph
|
||||
* @param requireTotal true to require a unique solution
|
||||
* @note if a unique solution is not requested, this algorithm will choose a solution
|
||||
* @implNote if a unique solution is not requested, this algorithm will choose a solution
|
||||
* arbitrarily. It does not yield all possible solutions.
|
||||
*/
|
||||
public TopologicalSorter(GDirectedGraph<V, E> graph, boolean requireTotal) {
|
||||
|
|
|
@ -271,7 +271,7 @@ public abstract class AbstractVarnodeEvaluator<T> implements VarnodeEvaluator<T>
|
|||
* This is only invoked when trying to evaluate a leaf, which should never occur for a unique
|
||||
* variable. Thus, by default, this throws a {@link PcodeExecutionException}.
|
||||
*
|
||||
* @param long the offset of the variable
|
||||
* @param offset the offset of the variable
|
||||
* @param size the size of the variable in bytes
|
||||
* @return the value
|
||||
*/
|
||||
|
|
|
@ -46,7 +46,7 @@ public interface VarnodeEvaluator<T> {
|
|||
* Evaluate variable storage
|
||||
*
|
||||
* <p>
|
||||
* Each varnode is evaluated as in {@link #evaluateStorage(VariableStorage)} and then
|
||||
* Each varnode is evaluated as in {@link #evaluateStorage(Program, VariableStorage)} and then
|
||||
* concatenated. The lower-indexed varnodes in storage are the more significant pieces, similar
|
||||
* to big endian.
|
||||
*
|
||||
|
|
|
@ -34,12 +34,12 @@ import ghidra.util.database.annot.DBAnnotatedObjectInfo;
|
|||
* fields from the record. These objects are managed using a {@link DBCachedObjectStore}. An example
|
||||
* object definition:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* interface Person {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* @DBAnnotatedObjectInfo(version = 1)
|
||||
* @DBAnnotatedObjectInfo(version = 1)
|
||||
* public class DBPerson extends DBAnnotatedObject implements Person {
|
||||
* public static final String TABLE_NAME = "Person"; // Conventionally defined here
|
||||
*
|
||||
|
@ -48,15 +48,15 @@ import ghidra.util.database.annot.DBAnnotatedObjectInfo;
|
|||
* static final String ADDRESS_COLUMN_NAME = "Address";
|
||||
*
|
||||
* // Column handles
|
||||
* @DBAnnotatedColumn(NAME_COLUMN_NAME)
|
||||
* @DBAnnotatedColumn(NAME_COLUMN_NAME)
|
||||
* static DBObjectColumn NAME_COLUMN;
|
||||
* @DBAnnotatedColumn(ADDRESS_COLUMN_NAME)
|
||||
* @DBAnnotatedColumn(ADDRESS_COLUMN_NAME)
|
||||
* static DBObjectColumn ADDRESS_COLUMN;
|
||||
*
|
||||
* // Column-backed fields
|
||||
* @DBAnnotatedField(column = NAME_COLUMN_NAME, indexed = true)
|
||||
* @DBAnnotatedField(column = NAME_COLUMN_NAME, indexed = true)
|
||||
* private String name;
|
||||
* @DBAnnotatedField(column = ADDRESS_COLUMN_NAME)
|
||||
* @DBAnnotatedField(column = ADDRESS_COLUMN_NAME)
|
||||
* private String address;
|
||||
*
|
||||
* DBPerson(DBCachedObjectStore<DBPerson> store, DBRecord record) {
|
||||
|
@ -72,7 +72,7 @@ import ghidra.util.database.annot.DBAnnotatedObjectInfo;
|
|||
*
|
||||
* // ... other methods, getters, setters
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* See {@link DBCachedObjectStoreFactory} for example code that uses the example {@code DBPerson}
|
||||
|
@ -192,7 +192,7 @@ public class DBAnnotatedObject extends DatabaseObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* 2-arity version of {@link #update(DBObjectColumn...)}
|
||||
* 3-arity version of {@link #update(DBObjectColumn...)}
|
||||
*
|
||||
* @param col1 a column
|
||||
* @param col2 another column
|
||||
|
|
|
@ -162,7 +162,7 @@ public abstract class DBCachedDomainObjectAdapter extends DBDomainObjectSupport
|
|||
protected ReadWriteLock rwLock;
|
||||
|
||||
/**
|
||||
* @see {@link DBDomainObjectSupport}
|
||||
* @see DBDomainObjectSupport
|
||||
*/
|
||||
protected DBCachedDomainObjectAdapter(DBHandle dbh, OpenMode openMode, TaskMonitor monitor,
|
||||
String name, int timeInterval, int bufSize, Object consumer) {
|
||||
|
|
|
@ -41,7 +41,7 @@ import ghidra.util.exception.VersionException;
|
|||
* See {@link DBAnnotatedObject} for more documentation, including an example object definition. To
|
||||
* create a store, e.g., for {@code Person}:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* interface MyDomainObject {
|
||||
* Person createPerson(String name, String address);
|
||||
*
|
||||
|
@ -71,7 +71,7 @@ import ghidra.util.exception.VersionException;
|
|||
* }
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public Person createPerson(String name, String address) {
|
||||
* // Locking details elided
|
||||
* DBPerson person = people.create();
|
||||
|
@ -79,19 +79,19 @@ import ghidra.util.exception.VersionException;
|
|||
* return person;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public Person getPerson(int id) {
|
||||
* // Locking details elided
|
||||
* return people.getAt(id);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public Collection<Person> getPeopleNamed(String name) {
|
||||
* // Locking details elided
|
||||
* return peopleByName.get(name);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* The factory manages tables on behalf of the domain object, so it is typically the first thing
|
||||
|
@ -159,7 +159,7 @@ public class DBCachedObjectStoreFactory {
|
|||
* {@link DBAnnotatedObject} is sufficient. If context is required, then additional interfaces
|
||||
* can be required via type intersection:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* public interface MyContext {
|
||||
* // ...
|
||||
* }
|
||||
|
@ -175,14 +175,14 @@ public class DBCachedObjectStoreFactory {
|
|||
* super(MyType.class, objectType, BinaryField.class, field, column);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* protected void doStore(OT obj, DBRecord record) {
|
||||
* MyContext ctx = obj.getContext();
|
||||
* // ...
|
||||
* }
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Note that this implementation uses {@link AbstractDBFieldCodec}, which is highly recommended.
|
||||
|
@ -194,25 +194,25 @@ public class DBCachedObjectStoreFactory {
|
|||
* {@link BinaryField}. See {@link ByteDBFieldCodec} for the simplest example with actual
|
||||
* encoding and decoding implementations. To use the example codec in an object:
|
||||
*
|
||||
* <pre>
|
||||
* @DBAnnotatedObjectInfo(version = 1)
|
||||
* <pre>{@code
|
||||
* @DBAnnotatedObjectInfo(version = 1)
|
||||
* public static class SomeObject extends DBAnnotatedObject implements ContextProvider {
|
||||
* static final String MY_COLUMN_NAME = "My";
|
||||
*
|
||||
* @DBAnnotatedColumn(MY_COLUMN_NAME)
|
||||
* @DBAnnotatedColumn(MY_COLUMN_NAME)
|
||||
* static DBObjectColumn MY_COLUMN;
|
||||
*
|
||||
* @DBAnnotatedField(column = MY_COLUMN_NAME, codec = MyDBFieldCodec.class)
|
||||
* @DBAnnotatedField(column = MY_COLUMN_NAME, codec = MyDBFieldCodec.class)
|
||||
* private MyType my;
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public MyContext getContext() {
|
||||
* // ...
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Notice that {@code SomeObject} must implement {@code ContextProvider}. This restriction is
|
||||
|
@ -406,7 +406,7 @@ public class DBCachedObjectStoreFactory {
|
|||
throws IllegalArgumentException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* Same as {@link #load(DBAnnotatedObject, DBRecord), but permits exceptions
|
||||
* Same as {@link #load(DBAnnotatedObject, DBRecord)}, but permits exceptions
|
||||
*/
|
||||
protected abstract void doLoad(OT obj, DBRecord record)
|
||||
throws IllegalArgumentException, IllegalAccessException;
|
||||
|
|
|
@ -119,7 +119,6 @@ public abstract class AbstractConstraintsTree< //
|
|||
* {@link Collection#size()}. Filtering is performed by {@link TreeRecordVisitor}.
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param query a query to control the ordering of the children
|
||||
* @return a collection of the children
|
||||
*/
|
||||
protected Collection<DR> getDataChildrenOf(NR parent) {
|
||||
|
@ -137,7 +136,6 @@ public abstract class AbstractConstraintsTree< //
|
|||
* {@link TreeRecordVisitor}.
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param query a query to control the ordering of the children
|
||||
* @return a collection of the children
|
||||
*/
|
||||
protected Collection<? extends DBTreeRecord<?, ? extends NS>> getChildrenOf(NR parent) {
|
||||
|
|
|
@ -113,12 +113,13 @@ public interface SpatialMap<DS extends BoundedShape<?>, T, Q> {
|
|||
/**
|
||||
* Put an entry into the map
|
||||
*
|
||||
* <p>
|
||||
* Note that the map may copy, and possibly modify, the given value. The value returned is the
|
||||
* value actually stored by the map. This may be useful when the map's values are identical to
|
||||
* its records. This allows the creation of a "blank" entry with a given shape. The entry is
|
||||
* then populated by the user.
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* class MyDBDataRecord extends DBTreeDataRecord<MyShape, MyNodeShape, MyDBDataRecord> {
|
||||
* @Override
|
||||
* protected void setValue(MyDBDataRecord value) {
|
||||
|
@ -129,18 +130,17 @@ public interface SpatialMap<DS extends BoundedShape<?>, T, Q> {
|
|||
* return this; // The record is the value
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* MyDBDataRecord rec = map.put(MyShape.create(args), null);
|
||||
* rec.setSomething(6);
|
||||
* rec.setAnother("My user data");
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This practice is preferred when the values are not simple, and/or when the shape is a
|
||||
* property of the value. In other cases, e.g., when the value is an enum or a {@link Color},
|
||||
* then {@link DBTreeDataRecord#setValue(Object)} and {@link DBTreeDataRecord#getValue()} should
|
||||
* be implemented as field accessors.
|
||||
* then {@link DBTreeDataRecord#setRecordValue(Object)} and
|
||||
* {@link DBTreeDataRecord#getRecordValue()} should be implemented as field accessors.
|
||||
*
|
||||
* @param shape the shape of the entry
|
||||
* @param value the value for the entry
|
||||
|
@ -151,6 +151,7 @@ public interface SpatialMap<DS extends BoundedShape<?>, T, Q> {
|
|||
/**
|
||||
* Remove an entry from the map
|
||||
*
|
||||
* <p>
|
||||
* Removes a single matching entry, if found, from the map. If you have a reference to an entry
|
||||
* obtained from this map, use {@link #remove(Entry)} instead. Otherwise, this is the preferred
|
||||
* method.
|
||||
|
@ -164,6 +165,7 @@ public interface SpatialMap<DS extends BoundedShape<?>, T, Q> {
|
|||
/**
|
||||
* Remove an entry from the map
|
||||
*
|
||||
* <p>
|
||||
* This method is preferred <em>only</em> when the given entry comes directly from this map.
|
||||
* This spares the implementation from having to search for a matching entry. If the entry does
|
||||
* not come from this map, it will behave like {@link #remove(BoundedShape, Object)}.
|
||||
|
@ -176,6 +178,7 @@ public interface SpatialMap<DS extends BoundedShape<?>, T, Q> {
|
|||
/**
|
||||
* Get or compute the size of this map
|
||||
*
|
||||
* <p>
|
||||
* Note that this may not necessarily be a quick operation, esp., if this map is the result of
|
||||
* {@link #reduce(Object)}. In the worst case, all elements in the reduced map will be visited.
|
||||
*
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.function.*;
|
|||
* A common use case is for a method to suppress any recursive calls, i.e., it is self suppressing,
|
||||
* e.g.:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* private final SuppressableCallback<Void> cbDoSomething = new SuppressableCallback<>();
|
||||
*
|
||||
* public boolean doSomething() {
|
||||
|
@ -51,7 +51,7 @@ import java.util.function.*;
|
|||
* // do the other thing
|
||||
* return doSomething();
|
||||
* }
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This example is very trivial, but this sort of thing can easily happen in event driven
|
||||
|
@ -62,6 +62,8 @@ import java.util.function.*;
|
|||
* resulting in unending oscillation between the requested states. A more robust solution demands we
|
||||
* know the cause(s) of events. For now, the solution is to suppress event firing whenever a state
|
||||
* change is due to receiving an event.
|
||||
*
|
||||
* @param <T> the type of return value, often {@link Void}
|
||||
*/
|
||||
public class SuppressableCallback<T> {
|
||||
/**
|
||||
|
@ -193,7 +195,7 @@ public class SuppressableCallback<T> {
|
|||
* The callback is always invoked, allowing it to decide what actions to take (or not take)
|
||||
* based on the values present in the stack.
|
||||
*
|
||||
* @param callback
|
||||
* @param callback a method to receive the stack
|
||||
*/
|
||||
public void invokeWithStack(Consumer<List<T>> callback) {
|
||||
callback.accept(stack.get().view);
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug TaintAnalysis'
|
||||
|
|
|
@ -51,12 +51,13 @@ import ghidra.taint.model.TaintVec;
|
|||
* <li>P-code Arithmetic: {@link TaintPcodeArithmetic}</li>
|
||||
* <li>Userop Library: {@link TaintPcodeUseropLibrary}</li>
|
||||
* <li>P-code Executor: {@link TaintPcodeThreadExecutor}</li>
|
||||
* <li>Machine State</li>
|
||||
* <li>Machine State
|
||||
* <ul>
|
||||
* <li>Stand alone: {@link TaintPcodeExecutorState}</li>
|
||||
* <li>Trace integrated: {@link TaintTracePcodeExecutorState}</li>
|
||||
* <li>Debugger integrated: {@link TaintTracePcodeExecutorState} (same as Trace integrated)</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
|
|
|
@ -19,8 +19,8 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
|
||||
import ghidra.pcode.emu.DefaultPcodeThread;
|
||||
import ghidra.pcode.emu.DefaultPcodeThread.PcodeThreadExecutor;
|
||||
import ghidra.pcode.exec.PcodeExecutor;
|
||||
import ghidra.pcode.exec.PcodeFrame;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.taint.model.TaintVec;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -52,9 +52,8 @@ public class TaintPcodeThreadExecutor extends PcodeThreadExecutor<Pair<byte[], T
|
|||
* This is invoked on every {@link PcodeOp#CBRANCH}, allowing us a decent place to instrument
|
||||
* the emulator and add some diagnostics. Refer to
|
||||
* {@link PcodeExecutor#executeConditionalBranch(PcodeOp, PcodeFrame)} to see the operations
|
||||
* inputs. Alternatively, we could override
|
||||
* {@link TaintPcodeArithmetic#isTrue(TaintVec, Purpose)}; however, we'd have access to less
|
||||
* contextual information at that position.
|
||||
* inputs. Alternatively, we could override {@link PcodeArithmetic#isTrue(Object, Purpose)};
|
||||
* however, we'd have access to less contextual information at that position.
|
||||
*/
|
||||
@Override
|
||||
public void executeConditionalBranch(PcodeOp op, PcodeFrame frame) {
|
||||
|
|
|
@ -42,8 +42,7 @@ public class TaintDebuggerPcodeEmulator extends AuxDebuggerPcodeEmulator<TaintVe
|
|||
* Here, we just return the singleton parts factory. This appears simple because all the
|
||||
* complexity is encapsulated in the factory. See {@link TaintPartsFactory} to see everything
|
||||
* the implementation actually entails. Notice that this is the same parts factory used by
|
||||
* {@link TaintPcodeEmulator}. The {@link AuxDebugggerPcodeEmulator} knows to use the more
|
||||
* capable state parts.
|
||||
* {@link TaintPcodeEmulator}.
|
||||
*/
|
||||
@Override
|
||||
protected AuxDebuggerEmulatorPartsFactory<TaintVec> getPartsFactory() {
|
||||
|
|
|
@ -39,8 +39,8 @@ import ghidra.program.model.lang.Language;
|
|||
* want to implement {@link TracePcodeExecutorState} directly, take the concrete piece provided, and
|
||||
* wrap it as you see fit. You may still benefit by referring to the implementation of
|
||||
* {@link PairedPcodeExecutorState}. When implementing your flavor of
|
||||
* {@link PairedPcodeExecutorState#getVar(AddressSpace, Pair, int, boolean)}, still consider that
|
||||
* you could benefit from the concrete element of the offset pair passed in.
|
||||
* {@link PairedPcodeExecutorState#getVar(AddressSpace, Pair, int, boolean, Reason)}, still consider
|
||||
* that you could benefit from the concrete element of the offset pair passed in.
|
||||
*/
|
||||
public class TaintPcodeExecutorStatePiece extends AbstractTaintPcodeExecutorStatePiece<TaintSpace> {
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ import ghidra.trace.model.property.TracePropertyMapSpace;
|
|||
* The trace-integrated state piece for holding taint marks
|
||||
*
|
||||
* <p>
|
||||
* See {@link AbstractTaintTracePcodeExecutorStatePiece} for framing. We'll store taint sets in the
|
||||
* See {@link AbstractTaintPcodeExecutorStatePiece} for framing. We'll store taint sets in the
|
||||
* trace's address property map, which is the recommended scheme for auxiliary state.
|
||||
*/
|
||||
public class TaintTracePcodeExecutorStatePiece
|
||||
|
|
|
@ -37,8 +37,7 @@ public class TaintTraceSpace extends TaintSpace {
|
|||
* Create the space
|
||||
*
|
||||
* @param space the address space
|
||||
* @param backing if present, the backing object
|
||||
* @param snap the source snap
|
||||
* @param property the trace property backing this space
|
||||
*/
|
||||
public TaintTraceSpace(AddressSpace space, PcodeTracePropertyAccess<String> property) {
|
||||
this.space = space;
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
* The trace-integrated Taint Emulator
|
||||
*
|
||||
* <p>
|
||||
* This package builds on {@link ghidra.pcode.emu.plain} to construct a trace-integrated emulator.
|
||||
* See that package for remarks about this "working solution." Those state components were factored
|
||||
* to accommodate the state components introduced by this package.
|
||||
* This package builds on the emulation framework to construct a trace-integrated emulator. The
|
||||
* framework's state components were designed to accommodate the state components introduced by this
|
||||
* package.
|
||||
*
|
||||
* <p>
|
||||
* For this package, I recommend a bottom-up approach, since you should already be familiar with the
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
* The Taint domain package
|
||||
*
|
||||
* <p>
|
||||
* This package implements the domain of taint analysis. {@link TaintVec} models an array of bytes,
|
||||
* each having a {@link TaintSet}. A {@link TaintSet} is in turn made of several {@link TaintMarks}.
|
||||
* Each mark is a symbol with optional tags. We use the tags as a means of handling indirection, so
|
||||
* that we don't have to decide up front whether tainted offsets taint the values read and written
|
||||
* from memory. We allow them to be tainted, but add a tag to the mark, so they can be examined
|
||||
* and/or filtered by the user.
|
||||
* This package implements the domain of taint analysis. {@link ghidra.taint.model.TaintVec} models
|
||||
* an array of bytes, each having a {@link ghidra.taint.model.TaintSet}. A
|
||||
* {@link ghidra.taint.model.TaintSet} is in turn made of several
|
||||
* {@link ghidra.taint.model.TaintMark}s. Each mark is a symbol with optional tags. We use the tags
|
||||
* as a means of handling indirection, so that we don't have to decide up front whether tainted
|
||||
* offsets taint the values read and written from memory. We allow them to be tainted, but add a tag
|
||||
* to the mark, so they can be examined and/or filtered by the user.
|
||||
*
|
||||
* <p>
|
||||
* To facilitate storage and presentation of taint, we will need to implement some
|
||||
|
@ -30,7 +31,8 @@
|
|||
* parse method for sets and marks.
|
||||
*
|
||||
* <p>
|
||||
* We recommend you read the documentation and source from the bottom up: {@link TaintMark},
|
||||
* {@link TaintSet}, {@link TaintVec}.
|
||||
* We recommend you read the documentation and source from the bottom up:
|
||||
* {@link ghidra.taint.model.TaintMark}, {@link ghidra.taint.model.TaintSet},
|
||||
* {@link ghidra.taint.model.TaintVec}.
|
||||
*/
|
||||
package ghidra.taint.model;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue