mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-18 00:20:10 +00:00
GP-3904: Adjusted pure emulation to work with overlays.
This commit is contained in:
parent
0fb2014df1
commit
4f9c672e49
@ -53,8 +53,10 @@ import ghidra.util.exception.DuplicateNameException;
|
|||||||
* Most of these are already integrated via the {@link DebuggerEmulationService}. Please see if that
|
* Most of these are already integrated via the {@link DebuggerEmulationService}. Please see if that
|
||||||
* service satisfies your use case before employing these directly.
|
* service satisfies your use case before employing these directly.
|
||||||
*/
|
*/
|
||||||
public enum ProgramEmulationUtils {
|
public class ProgramEmulationUtils {
|
||||||
;
|
private ProgramEmulationUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
public static final String BLOCK_NAME_STACK = "STACK";
|
public static final String BLOCK_NAME_STACK = "STACK";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,21 +124,27 @@ public enum ProgramEmulationUtils {
|
|||||||
* Create regions for each block in a program, without relocation, and map the program in
|
* Create regions for each block in a program, without relocation, and map the program in
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This creates a region for each loaded, non-overlay block in the program. Permissions/flags
|
* This creates a region for each loaded, block in the program. Typically, only non-overlay
|
||||||
* are assigned accordingly. A single static mapping is generated to cover the entire range of
|
* blocks are included. To activate an overlay space, include it in the set of
|
||||||
* created regions. Note that no bytes are copied in, as that could be prohibitive for large
|
* {@code activeOverlays}. This will alter the mapping from the trace to the static program such
|
||||||
* programs. Instead, the emulator should load them, based on the static mapping, as needed.
|
* that the specified overlays are effective. The gaps between overlays are mapped to their
|
||||||
|
* physical (non-overlay) portions. Permissions/flags are assigned accordingly. Note that no
|
||||||
|
* bytes are copied in, as that could be prohibitive for large programs. Instead, the emulator
|
||||||
|
* should load them, based on the static mapping, as needed.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* A transaction must already be started on the destination trace.
|
* A transaction must already be started on the destination trace.
|
||||||
*
|
*
|
||||||
* @param snapshot the destination snapshot, usually 0
|
* @param snapshot the destination snapshot, usually 0
|
||||||
* @param program the program to load
|
* @param program the program to load
|
||||||
|
* @param activeOverlays which overlay spaces to use
|
||||||
*/
|
*/
|
||||||
public static void loadExecutable(TraceSnapshot snapshot, Program program) {
|
public static void loadExecutable(TraceSnapshot snapshot, Program program,
|
||||||
|
List<AddressSpace> activeOverlays) {
|
||||||
Trace trace = snapshot.getTrace();
|
Trace trace = snapshot.getTrace();
|
||||||
PathPattern patRegion = computePatternRegion(trace);
|
PathPattern patRegion = computePatternRegion(trace);
|
||||||
Map<AddressSpace, Extrema> extremaBySpace = new HashMap<>();
|
Map<AddressSpace, Extrema> extremaBySpace = new HashMap<>();
|
||||||
|
Lifespan nowOn = Lifespan.nowOn(snapshot.getKey());
|
||||||
try {
|
try {
|
||||||
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
||||||
if (!DebuggerStaticMappingUtils.isReal(block)) {
|
if (!DebuggerStaticMappingUtils.isReal(block)) {
|
||||||
@ -147,18 +155,35 @@ public enum ProgramEmulationUtils {
|
|||||||
.consider(range);
|
.consider(range);
|
||||||
String modName = getModuleName(program);
|
String modName = getModuleName(program);
|
||||||
|
|
||||||
// TODO: Do I populate modules, since the mapping will already be done?
|
// NB. No need to populate as module.
|
||||||
|
// UI will sync from mapping, so it's obvious where the cursor is.
|
||||||
String path = PathUtils.toString(patRegion
|
String path = PathUtils.toString(patRegion
|
||||||
.applyKeys(block.getStart() + "-" + modName + ":" + block.getName())
|
.applyKeys(block.getStart() + "-" + modName + ":" + block.getName())
|
||||||
.getSingletonPath());
|
.getSingletonPath());
|
||||||
trace.getMemoryManager()
|
trace.getMemoryManager()
|
||||||
.createRegion(path, snapshot.getKey(), range, getRegionFlags(block));
|
.createRegion(path, snapshot.getKey(), range, getRegionFlags(block));
|
||||||
}
|
}
|
||||||
|
AddressSet identical = new AddressSet();
|
||||||
for (Extrema extrema : extremaBySpace.values()) {
|
for (Extrema extrema : extremaBySpace.values()) {
|
||||||
|
identical.add(extrema.getMin(), extrema.getMax());
|
||||||
|
}
|
||||||
|
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
||||||
|
if (!block.isOverlay() ||
|
||||||
|
!activeOverlays.contains(block.getStart().getAddressSpace())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Address phys = block.getStart().getPhysicalAddress();
|
||||||
DebuggerStaticMappingUtils.addMapping(
|
DebuggerStaticMappingUtils.addMapping(
|
||||||
new DefaultTraceLocation(trace, null, Lifespan.nowOn(snapshot.getKey()),
|
new DefaultTraceLocation(trace, null, nowOn, phys),
|
||||||
extrema.getMin()),
|
new ProgramLocation(program, block.getStart()),
|
||||||
new ProgramLocation(program, extrema.getMin()), extrema.getLength(), false);
|
block.getSize(), false);
|
||||||
|
identical.delete(phys, block.getEnd().getPhysicalAddress());
|
||||||
|
}
|
||||||
|
for (AddressRange range : identical) {
|
||||||
|
DebuggerStaticMappingUtils.addMapping(
|
||||||
|
new DefaultTraceLocation(trace, null, nowOn, range.getMinAddress()),
|
||||||
|
new ProgramLocation(program, range.getMinAddress()),
|
||||||
|
range.getLength(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (TraceOverlappedRegionException | DuplicateNameException
|
catch (TraceOverlappedRegionException | DuplicateNameException
|
||||||
@ -407,7 +432,10 @@ public enum ProgramEmulationUtils {
|
|||||||
TraceSnapshot initial =
|
TraceSnapshot initial =
|
||||||
trace.getTimeManager().createSnapshot(EMULATION_STARTED_AT + pc);
|
trace.getTimeManager().createSnapshot(EMULATION_STARTED_AT + pc);
|
||||||
long snap = initial.getKey();
|
long snap = initial.getKey();
|
||||||
loadExecutable(initial, program);
|
List<AddressSpace> overlays =
|
||||||
|
pc.getAddressSpace().isOverlaySpace() ? List.of(pc.getAddressSpace())
|
||||||
|
: List.of();
|
||||||
|
loadExecutable(initial, program, overlays);
|
||||||
doLaunchEmulationThread(trace, snap, program, pc, pc);
|
doLaunchEmulationThread(trace, snap, program, pc, pc);
|
||||||
}
|
}
|
||||||
trace.clearUndo();
|
trace.clearUndo();
|
||||||
|
@ -703,7 +703,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
createTrace(program.getLanguageID().getIdAsString());
|
createTrace(program.getLanguageID().getIdAsString());
|
||||||
try (Transaction startTransaction = tb.startTransaction()) {
|
try (Transaction startTransaction = tb.startTransaction()) {
|
||||||
TraceSnapshot initial = tb.trace.getTimeManager().getSnapshot(0, true);
|
TraceSnapshot initial = tb.trace.getTimeManager().getSnapshot(0, true);
|
||||||
ProgramEmulationUtils.loadExecutable(initial, program);
|
ProgramEmulationUtils.loadExecutable(initial, program, List.of());
|
||||||
Address pc = program.getMinAddress();
|
Address pc = program.getMinAddress();
|
||||||
ProgramEmulationUtils.doLaunchEmulationThread(tb.trace, 0, program, pc, pc);
|
ProgramEmulationUtils.doLaunchEmulationThread(tb.trace, 0, program, pc, pc);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user