Merge remote-tracking branch 'origin/GP-5379_Dan_fixKeyReuse--SQUASHED'

(Closes #7497)
This commit is contained in:
Ryan Kurtz
2025-03-03 13:07:33 -05:00
167 changed files with 2523 additions and 2784 deletions
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -241,6 +241,7 @@ public interface DebuggerStaticMappingService {
* @param entries the entries to add
* @param monitor a monitor to cancel the operation
* @param truncateExisting true to delete or truncate the lifespan of overlapping entries
* @throws CancelledException if the user cancels
* @see #addMapping(TraceLocation, ProgramLocation, long, boolean)
* @throws TraceConflictedMappingException if a conflicting mapping overlaps the source and
* {@code truncateExisting} is false.
@@ -259,6 +260,7 @@ public interface DebuggerStaticMappingService {
* @param entries the entries to add
* @param monitor a monitor to cancel the operation
* @param truncateExisting true to delete or truncate the lifespan of overlapping entries
* @throws CancelledException if the user cancels
* @see #addMapping(TraceLocation, ProgramLocation, long, boolean)
*/
void addSectionMappings(Collection<SectionMapEntry> entries, TaskMonitor monitor,
@@ -275,6 +277,7 @@ public interface DebuggerStaticMappingService {
* @param entries the entries to add
* @param monitor a monitor to cancel the operation
* @param truncateExisting true to delete or truncate the lifespan of overlapping entries
* @throws CancelledException if the user cancels
* @see #addMapping(TraceLocation, ProgramLocation, long, boolean)
*/
void addRegionMappings(Collection<RegionMapEntry> entries, TaskMonitor monitor,
@@ -421,17 +424,18 @@ public interface DebuggerStaticMappingService {
* The service maintains an index of likely module names to domain files in the active project.
* This will search that index for the module's full file path. Failing that, it will search
* just for the module's file name. Among the programs found, it first prefers those whose
* module name list (see {@link ProgramModuleIndexer#setModulePaths(Program, List)}) include the
* sought module. Then, it prefers those whose executable path (see
* {@link Program#setExecutablePath(String)}) matches the sought module. Finally, it prefers
* matches on the program name and the domain file name. Ties in name matching are broken by
* looking for domain files in the same folders as those programs already mapped into the trace
* in the given address space.
* module name list includes the sought module. Then, it prefers those whose executable path
* (see {@link Program#setExecutablePath(String)}) matches the sought module. Finally, it
* prefers matches on the program name and the domain file name. Ties in name matching are
* broken by looking for domain files in the same folders as those programs already mapped into
* the trace in the given address space.
*
* @param space the fallback address space if the module is missing its base
* @param module the trace module
* @param snap the snapshot to consider
* @return the, possibly empty, set of probable matches
*/
DomainFile findBestModuleProgram(AddressSpace space, TraceModule module);
DomainFile findBestModuleProgram(AddressSpace space, TraceModule module, long snap);
/**
* Propose a module map for the given module to the given program
@@ -440,14 +444,15 @@ public interface DebuggerStaticMappingService {
* Note, no sanity check is performed on the given parameters. This will simply propose the
* given module-program pair. It is strongly advised to use
* {@link ModuleMapProposal#computeScore()} to assess the proposal. Alternatively, use
* {@link #proposeModuleMap(TraceModule, Collection)} to have the service select the best-scored
* mapping from a collection of proposed programs.
* {@link #proposeModuleMap(TraceModule, long, Collection)} to have the service select the
* best-scored mapping from a collection of proposed programs.
*
* @param module the module to consider
* @param snap the source snapshot key
* @param program the destination program to consider
* @return the proposal
*/
ModuleMapProposal proposeModuleMap(TraceModule module, Program program);
ModuleMapProposal proposeModuleMap(TraceModule module, long snap, Program program);
/**
* Compute the best-scored module map for the given module and programs
@@ -460,10 +465,12 @@ public interface DebuggerStaticMappingService {
* @see ModuleMapProposal#computeScore()
*
* @param module the module to consider
* @param snap the source snapshot key
* @param programs a set of proposed destination programs
* @return the best-scored proposal, or {@code null} if no program is proposed
*/
ModuleMapProposal proposeModuleMap(TraceModule module, Collection<? extends Program> programs);
ModuleMapProposal proposeModuleMap(TraceModule module, long snap,
Collection<? extends Program> programs);
/**
* Compute the "best" map of trace module to program for each given module given a collection of
@@ -476,11 +483,13 @@ public interface DebuggerStaticMappingService {
* {@code null} values.
*
* @param modules the modules to map
* @param snap the source snapshot key
* @param programs the set of proposed destination programs
* @return the proposal
*/
Map<TraceModule, ModuleMapProposal> proposeModuleMaps(
Collection<? extends TraceModule> modules, Collection<? extends Program> programs);
Collection<? extends TraceModule> modules, long snap,
Collection<? extends Program> programs);
/**
* Propose a singleton section map from the given section to the given program memory block
@@ -489,15 +498,17 @@ public interface DebuggerStaticMappingService {
* Note, no sanity check is performed on the given parameters. This will simply give a singleton
* map of the given entry. It is strongly advised to use
* {@link SectionMapProposal#computeScore()} to assess the proposal. Alternatively, use
* {@link #proposeSectionMap(TraceModule, Collection)} to have the service select the
* {@link #proposeSectionMap(TraceModule, long, Collection)} to have the service select the
* best-scored mapping from a collection of proposed programs.
*
* @param section the section to map
* @param snap the source snapshot key
* @param program the destination program
* @param block the memory block in the destination program
* @return the proposed map
*/
SectionMapProposal proposeSectionMap(TraceSection section, Program program, MemoryBlock block);
SectionMapProposal proposeSectionMap(TraceSection section, long snap, Program program,
MemoryBlock block);
/**
* Propose a section map for the given module to the given program
@@ -506,14 +517,15 @@ public interface DebuggerStaticMappingService {
* Note, no sanity check is performed on the given parameters. This will do its best to map
* sections from the given module to memory blocks in the given program. It is strongly advised
* to use {@link SectionMapProposal#computeScore()} to assess the proposal. Alternatively, use
* {@link #proposeSectionMap(TraceModule, Collection)} to have the service select the
* {@link #proposeSectionMap(TraceModule, long, Collection)} to have the service select the
* best-scored mapping from a collection of proposed programs.
*
* @param module the module whose sections to map
* @param snap the source snapshot key
* @param program the destination program whose blocks to consider
* @return the proposed map
*/
SectionMapProposal proposeSectionMap(TraceModule module, Program program);
SectionMapProposal proposeSectionMap(TraceModule module, long snap, Program program);
/**
* Proposed the best-scored section map for the given module and programs
@@ -526,10 +538,11 @@ public interface DebuggerStaticMappingService {
* @see SectionMapProposal#computeScore()
*
* @param module the module whose sections to map
* @param snap the source snapshot key
* @param programs a set of proposed destination programs
* @return the best-scored map, or {@code null} if no program is proposed
*/
SectionMapProposal proposeSectionMap(TraceModule module,
SectionMapProposal proposeSectionMap(TraceModule module, long snap,
Collection<? extends Program> programs);
/**
@@ -543,11 +556,13 @@ public interface DebuggerStaticMappingService {
* {@code null} values.
*
* @param modules the modules to map
* @param snap the source snapshot key
* @param programs a set of proposed destination programs
* @return the composite proposal
*/
Map<TraceModule, SectionMapProposal> proposeSectionMaps(
Collection<? extends TraceModule> modules, Collection<? extends Program> programs);
Collection<? extends TraceModule> modules, long snap,
Collection<? extends Program> programs);
/**
* Propose a singleton region map from the given region to the given program memory block
@@ -556,15 +571,16 @@ public interface DebuggerStaticMappingService {
* Note, no sanity check is performed on the given parameters. This will simply give a singleton
* map of the given entry. It is strongly advised to use
* {@link RegionMapProposal#computeScore()} to assess the proposal. Alternatively, use
* {@link #proposeRegionMap(Collection, Collection)} to have the service select the best-scored
* mapping from a collection of proposed programs.
* {@link #proposeRegionMaps(Collection, long, Collection)} to have the service select the
* best-scored mapping from a collection of proposed programs.
*
* @param region the region to map
* @param snap the source snapshot key
* @param program the destination program
* @param block the memory block in the destination program
* @return the proposed map
*/
RegionMapProposal proposeRegionMap(TraceMemoryRegion region, Program program,
RegionMapProposal proposeRegionMap(TraceMemoryRegion region, long snap, Program program,
MemoryBlock block);
/**
@@ -575,14 +591,16 @@ public interface DebuggerStaticMappingService {
* regions to memory blocks in the given program. For the best results, regions should all
* comprise the same module, and the minimum address among the regions should be the module's
* base address. It is strongly advised to use {@link RegionMapProposal#computeScore()} to
* assess the proposal. Alternatively, use {@link #proposeRegionMap(Collection, Collection)} to
* have the service select the best-scored mapping from a collection of proposed programs.
* assess the proposal. Alternatively, use
* {@link #proposeRegionMaps(Collection, long, Collection)} to have the service select the
* best-scored mapping from a collection of proposed programs.
*
* @param region the region to map
* @param regions the regions to map
* @param snap the source snapshot key
* @param program the destination program whose blocks to consider
* @return the proposed map
*/
RegionMapProposal proposeRegionMap(Collection<? extends TraceMemoryRegion> regions,
RegionMapProposal proposeRegionMap(Collection<? extends TraceMemoryRegion> regions, long snap,
Program program);
/**
@@ -597,11 +615,12 @@ public interface DebuggerStaticMappingService {
* regions into likely modules. For the best results, the minimum address of each module should
* be among the regions.
*
* @param modules the modules to map
* @param regions the regions to map
* @param snap the source snapshot key
* @param programs a set of proposed destination programs
* @return the composite proposal
*/
Map<Collection<TraceMemoryRegion>, RegionMapProposal> proposeRegionMaps(
Collection<? extends TraceMemoryRegion> regions,
Collection<? extends TraceMemoryRegion> regions, long snap,
Collection<? extends Program> programs);
}
@@ -93,7 +93,7 @@ public interface AutoMapSpec extends ExtensionPoint {
boolean objectHasType(TraceObjectValue value);
String getInfoForObjects(Trace trace);
String getInfoForObjects(Trace trace, long snap);
default boolean hasTask() {
return true;
@@ -103,7 +103,7 @@ public interface AutoMapSpec extends ExtensionPoint {
return getMenuName();
}
default void runTask(PluginTool tool, Trace trace) {
default void runTask(PluginTool tool, Trace trace, long snap) {
DebuggerStaticMappingService mappingService =
tool.getService(DebuggerStaticMappingService.class);
ProgramManager programManager = tool.getService(ProgramManager.class);
@@ -114,7 +114,7 @@ public interface AutoMapSpec extends ExtensionPoint {
@Override
public boolean applyTo(Trace trace, TaskMonitor monitor) {
try {
performMapping(mappingService, trace, programManager, monitor);
performMapping(mappingService, trace, snap, programManager, monitor);
return true;
}
catch (CancelledException e) {
@@ -132,12 +132,13 @@ public interface AutoMapSpec extends ExtensionPoint {
*
* @param mappingService the mapping service
* @param trace the trace
* @param snap the snap
* @param programs the programs to consider
* @param monitor a task monitor
* @return true if any mappings were added
* @throws CancelledException if the task monitor cancelled the task
*/
boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace, long snap,
List<Program> programs, TaskMonitor monitor) throws CancelledException;
/**
@@ -145,13 +146,15 @@ public interface AutoMapSpec extends ExtensionPoint {
*
* @param mappingService the mapping service
* @param trace the trace
* @param snap the snap
* @param programManager the program manager
* @param monitor a task monitor
* @return true if any mappings were added
* @throws CancelledException if the task monitor cancelled the task
*/
default boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
return performMapping(mappingService, trace, programs(programManager), monitor);
long snap, ProgramManager programManager, TaskMonitor monitor)
throws CancelledException {
return performMapping(mappingService, trace, snap, programs(programManager), monitor);
}
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -25,14 +25,20 @@ import ghidra.trace.model.target.TraceObjectValue;
public class DebuggerObjectActionContext extends DefaultActionContext {
private final List<TraceObjectValue> objectValues;
private final long snap;
public DebuggerObjectActionContext(Collection<TraceObjectValue> objectValues,
ComponentProvider provider, Component sourceComponent) {
ComponentProvider provider, Component sourceComponent, long snap) {
super(provider, sourceComponent);
this.objectValues = List.copyOf(objectValues);
this.snap = snap;
}
public List<TraceObjectValue> getObjectValues() {
return objectValues;
}
public long getSnap() {
return snap;
}
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -33,6 +33,13 @@ public interface ModuleMapProposal extends MapProposal<TraceModule, Program, Mod
*/
TraceModule getModule();
/**
* Get the module name for this entry (may depend on the snap)
*
* @return the name
*/
String getModuleName();
/**
* Get the address range of the module in the trace, as computed from the matched program's
* image size
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,6 +16,7 @@
package ghidra.debug.api.modules;
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.trace.model.memory.TraceMemoryRegion;
@@ -34,6 +35,20 @@ public interface RegionMapProposal
*/
TraceMemoryRegion getRegion();
/**
* Get the region's name (may depend on snap)
*
* @return the name
*/
String getRegionName();
/**
* Get the region's minimum address (may depend on snap)
*
* @return the address
*/
Address getRegionMinAddress();
/**
* Get the matched memory block
*
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,6 +16,7 @@
package ghidra.debug.api.modules;
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.trace.model.modules.TraceModule;
@@ -36,6 +37,20 @@ public interface SectionMapProposal
*/
TraceSection getSection();
/**
* Get the section name (may depend on the snap)
*
* @return the name
*/
String getSectionName();
/**
* Get the start address of the section (may depend on the snap)
*
* @return the start address
*/
Address getSectionStart();
/**
* Get the module containing the section
*
@@ -43,6 +58,13 @@ public interface SectionMapProposal
*/
TraceModule getModule();
/**
* Get the name of the module containing the section (may depend on snap)
*
* @return the name
*/
String getModuleName();
/**
* Get the matched memory block
*
@@ -71,5 +93,6 @@ public interface SectionMapProposal
*
* @return the program
*/
@Override
Program getProgram();
}
@@ -320,8 +320,9 @@ public class DebuggerCoordinates {
return objThread.getCanonicalPath();
}
TraceStack stack;
long snap = time.getSnap();
try {
stack = thread.getTrace().getStackManager().getStack(thread, time.getSnap(), false);
stack = thread.getTrace().getStackManager().getStack(thread, snap, false);
}
catch (IllegalStateException e) {
// Schema does not specify a stack
@@ -330,7 +331,7 @@ public class DebuggerCoordinates {
if (stack == null) {
return objThread.getCanonicalPath();
}
TraceStackFrame frame = stack.getFrame(frameLevel, false);
TraceStackFrame frame = stack.getFrame(snap, frameLevel, false);
if (frame == null) {
return objThread.getCanonicalPath();
}
@@ -406,9 +407,8 @@ public class DebuggerCoordinates {
return NOWHERE;
}
long snap = newTime.getSnap();
Lifespan threadLifespan = thread == null ? null : thread.getLifespan();
TraceThread newThread = threadLifespan != null && threadLifespan.contains(snap) ? thread
: resolveThread(trace, target, newTime);
boolean isThreadValid = thread == null ? false : thread.isValid(snap);
TraceThread newThread = isThreadValid ? thread : resolveThread(trace, target, newTime);
// This will cause the frame to reset to 0 on every snap change. That's fair....
Integer newFrame = resolveFrame(newThread, newTime);
KeyPath threadOrFramePath = resolvePath(newThread, newFrame, newTime);
@@ -1444,8 +1444,10 @@ public interface FlatDebuggerAPI {
}
default ActionContext createContext(TraceObject object) {
Trace trace = object.getTrace();
DebuggerCoordinates coords = getTraceManager().getCurrentFor(trace);
TraceObjectValue value = object.getCanonicalParents(Lifespan.ALL).findAny().orElseThrow();
return new DebuggerObjectActionContext(List.of(value), null, null);
return new DebuggerObjectActionContext(List.of(value), null, null, coords.getSnap());
}
default ActionContext createContext(TraceThread thread) {
@@ -1720,8 +1722,7 @@ public interface FlatDebuggerAPI {
* This does not consider the current snap. It only considers a live target thread in the
* present. In other words, if the user rewinds trace history to a point where the thread was
* alive, this method still considers that thread terminated. To compute state with respect to
* trace history, use {@link TraceThread#getLifespan()} and check if it contains the current
* snap.
* trace history, use {@link TraceThread#isValid(long)}.
*
* @param thread
* @return the thread's execution state
@@ -190,7 +190,8 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
return false;
}
if (spec.performMapping(mappingService, trace, List.of(program), monitor)) {
long snap = connection.getLastSnapshot(trace);
if (spec.performMapping(mappingService, trace, snap, List.of(program), monitor)) {
return true;
}
@@ -206,7 +207,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
return true; // Probably shouldn't happen, but if it does, say "success"
}
ProgramLocation probe = new ProgramLocation(program, probeAddress);
long snap = connection.getLastSnapshot(trace);
return mappingService.getOpenMappedLocation(trace, probe, snap) != null;
}
@@ -938,7 +938,8 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
// Want addresses satisfying {@code known | (readOnly & everKnown)}
TraceMemoryManager memoryManager = open.trace.getMemoryManager();
AddressSetView readOnly = memoryManager.getRegionsAddressSetWith(snap, r -> !r.isWrite());
AddressSetView readOnly =
memoryManager.getRegionsAddressSetWith(snap, r -> !r.isWrite(snap));
AddressSetView everKnown = memoryManager.getAddressesWithState(Lifespan.since(snap),
s -> s == TraceMemoryState.KNOWN);
AddressSetView roEverKnown = new IntersectionAddressSetView(readOnly, everKnown);
@@ -1334,7 +1334,7 @@ public class TraceRmiTarget extends AbstractTarget {
RemoteParameter paramFrame = writeReg.params.get("frame");
if (paramFrame != null) {
TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap());
TraceStackFrame frame = stack.getFrame(frameLevel, false);
TraceStackFrame frame = stack.getFrame(getSnap(), frameLevel, false);
if (!(frame instanceof TraceObjectStackFrame tof)) {
Msg.error(this, "Non-object trace with TraceRmi!");
return AsyncUtils.nil();
@@ -1568,10 +1568,11 @@ public class TraceRmiTarget extends AbstractTarget {
@Override
public boolean isBreakpointValid(TraceBreakpoint breakpoint) {
if (breakpoint.getName().endsWith("emu-" + breakpoint.getMinAddress())) {
long snap = getSnap();
if (breakpoint.getName(snap).endsWith("emu-" + breakpoint.getMinAddress(snap))) {
return false;
}
if (!breakpoint.isAlive(getSnap())) {
if (!breakpoint.isValid(snap)) {
return false;
}
return true;
@@ -288,9 +288,8 @@ public class PopulateDemoTrace extends GhidraScript {
int pc2 = 0;
/**
* For clarity, I will add each tick to the trace in its own transaction. The
* Transaction class eases the syntax and reduces errors in starting and ending
* transactions.
* For clarity, I will add each tick to the trace in its own transaction. The Transaction
* class eases the syntax and reduces errors in starting and ending transactions.
*/
try (Transaction tx = trace.openTransaction("Populate First Snapshot")) {
/**
@@ -699,7 +698,7 @@ public class PopulateDemoTrace extends GhidraScript {
long snap =
trace.getTimeManager().createSnapshot("Stepped Thread 2: CALL exit").getKey();
thread2.setDestructionSnap(snap);
thread2.remove(snap);
}
/**
@@ -709,7 +708,7 @@ public class PopulateDemoTrace extends GhidraScript {
long snap =
trace.getTimeManager().createSnapshot("Stepped Thread 1: CALL exit").getKey();
thread1.setDestructionSnap(snap);
thread1.remove(snap);
}
/**
@@ -117,13 +117,13 @@ public class DebuggerDisassemblerPlugin extends Plugin implements PopupActionPro
// It has never been known up to this snap
return null;
}
TraceMemoryRegion region =
memoryManager.getRegionContaining(mrent.getKey().getY1(), start);
if (region == null || region.isWrite()) {
long ks = mrent.getKey().getY1();
TraceMemoryRegion region = memoryManager.getRegionContaining(ks, start);
if (region == null || region.isWrite(ks)) {
// It could have changed this snap, so unknown
return null;
}
return mrent.getKey().getY1();
return ks;
}
/**
@@ -133,8 +133,8 @@ public class DebuggerDisassemblerPlugin extends Plugin implements PopupActionPro
* The view contains the addresses in {@code known | (readOnly & everKnown)}, where {@code
* known} is the set of addresses in the {@link TraceMemoryState#KNOWN} state, {@code readOnly}
* is the set of addresses in a {@link TraceMemoryRegion} having
* {@link TraceMemoryRegion#isWrite()} false, and {@code everKnown} is the set of addresses in
* the {@link TraceMemoryState#KNOWN} state in any previous snapshot.
* {@link TraceMemoryRegion#isWrite(long)} false, and {@code everKnown} is the set of addresses
* in the {@link TraceMemoryState#KNOWN} state in any previous snapshot.
*
* <p>
* In plainer English, we want addresses that have freshly read bytes right now, or addresses in
@@ -158,7 +158,7 @@ public class DebuggerDisassemblerPlugin extends Plugin implements PopupActionPro
}
TraceMemoryManager memoryManager = trace.getMemoryManager();
AddressSetView readOnly =
memoryManager.getRegionsAddressSetWith(ks, r -> !r.isWrite());
memoryManager.getRegionsAddressSetWith(ks, r -> !r.isWrite(ks));
AddressSetView everKnown = memoryManager.getAddressesWithState(Lifespan.since(ks),
s -> s == TraceMemoryState.KNOWN);
AddressSetView roEverKnown = new IntersectionAddressSetView(readOnly, everKnown);
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -81,18 +81,19 @@ public class DebuggerBlockChooserDialog extends ReusableDialogComponentProvider
return score;
}
public double score(TraceSection section, DebuggerStaticMappingService service) {
public double score(TraceSection section, long snap, DebuggerStaticMappingService service) {
if (section == null) {
return score = 0;
}
return score = service.proposeSectionMap(section, program, block).computeScore();
return score = service.proposeSectionMap(section, snap, program, block).computeScore();
}
public double score(TraceMemoryRegion region, DebuggerStaticMappingService service) {
public double score(TraceMemoryRegion region, long snap,
DebuggerStaticMappingService service) {
if (region == null) {
return score = 0;
}
return score = service.proposeRegionMap(region, program, block).computeScore();
return score = service.proposeRegionMap(region, snap, program, block).computeScore();
}
public ProgramLocation getProgramLocation() {
@@ -201,15 +202,15 @@ public class DebuggerBlockChooserDialog extends ReusableDialogComponentProvider
}
public Map.Entry<Program, MemoryBlock> chooseBlock(PluginTool tool, TraceSection section,
Collection<Program> programs) {
long snap, Collection<Program> programs) {
DebuggerStaticMappingService service = tool.getService(DebuggerStaticMappingService.class);
return chooseBlock(tool, programs, rec -> rec.score(section, service));
return chooseBlock(tool, programs, rec -> rec.score(section, snap, service));
}
public Map.Entry<Program, MemoryBlock> chooseBlock(PluginTool tool, TraceMemoryRegion region,
Collection<Program> programs) {
long snap, Collection<Program> programs) {
DebuggerStaticMappingService service = tool.getService(DebuggerStaticMappingService.class);
return chooseBlock(tool, programs, rec -> rec.score(region, service));
return chooseBlock(tool, programs, rec -> rec.score(region, snap, service));
}
protected Map.Entry<Program, MemoryBlock> chooseBlock(PluginTool tool,
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -142,13 +142,14 @@ public class DebuggerLocationLabel extends JLabel {
if (sections.isEmpty()) {
return null;
}
long snap = current.getSnap();
/**
* TODO: DB's R-Tree could probably do this natively. Not sure it's an optimization, though,
* since few, if any, overlapping sections are expected.
*/
sections.sort(ComparatorUtils.chainedComparator(List.of(
Comparator.comparing(s -> s.getRange().getMinAddress()),
Comparator.comparing(s -> -s.getRange().getLength()))));
Comparator.comparing(s -> s.getRange(snap).getMinAddress()),
Comparator.comparing(s -> -s.getRange(snap).getLength()))));
return sections.get(sections.size() - 1);
}
@@ -162,10 +163,11 @@ public class DebuggerLocationLabel extends JLabel {
if (modules.isEmpty()) {
return null;
}
long snap = current.getSnap();
// TODO: DB's R-Tree could probably do this natively
modules.sort(ComparatorUtils.chainedComparator(List.of(
Comparator.comparing(m -> m.getRange().getMinAddress()),
Comparator.comparing(m -> -m.getRange().getLength()))));
Comparator.comparing(m -> m.getRange(snap).getMinAddress()),
Comparator.comparing(m -> -m.getRange(snap).getLength()))));
return modules.get(modules.size() - 1);
}
@@ -185,18 +187,19 @@ public class DebuggerLocationLabel extends JLabel {
if (address == null) {
return "(nowhere)";
}
long snap = current.getSnap();
try {
TraceSection section = getNearestSectionContaining();
if (section != null) {
return section.getModule().getName() + ":" + section.getName();
return section.getModule().getName(snap) + ":" + section.getName(snap);
}
TraceModule module = getNearestModuleContaining();
if (module != null) {
return module.getName();
return module.getName(snap);
}
TraceMemoryRegion region = getRegionContaining();
if (region != null) {
return region.getName();
return region.getName(snap);
}
return "(unknown)";
}
@@ -81,14 +81,14 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
}
@Override
public String getInfoForObjects(Trace trace) {
public String getInfoForObjects(Trace trace, long snap) {
String modPart = trace.getModuleManager()
.getAllModules()
.getLoadedModules(snap)
.stream()
.map(m -> m.getName() + ":" + m.getBase())
.map(m -> m.getName(snap) + ":" + m.getBase(snap))
.sorted()
.collect(Collectors.joining(","));
String regPart = ByRegionAutoMapSpec.getInfoForRegions(trace);
String regPart = ByRegionAutoMapSpec.getInfoForRegions(trace, snap);
return modPart + ";" + regPart;
}
@@ -99,9 +99,9 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
@Override
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
List<Program> programs, TaskMonitor monitor) throws CancelledException {
long snap, List<Program> programs, TaskMonitor monitor) throws CancelledException {
Map<?, ModuleMapProposal> maps = mappingService
.proposeModuleMaps(trace.getModuleManager().getAllModules(), programs);
.proposeModuleMaps(trace.getModuleManager().getLoadedModules(snap), snap, programs);
Collection<ModuleMapEntry> entries = MapProposal.flatten(maps.values());
entries = MapProposal.removeOverlapping(entries);
mappingService.addModuleMappings(entries, monitor, false);
@@ -64,18 +64,18 @@ public class ByRegionAutoMapSpec implements AutoMapSpec {
return value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null;
}
static String getInfoForRegions(Trace trace) {
static String getInfoForRegions(Trace trace, long snap) {
return trace.getMemoryManager()
.getAllRegions()
.getRegionsAtSnap(snap)
.stream()
.map(r -> r.getName() + ":" + r.getMinAddress())
.map(r -> r.getName(snap) + ":" + r.getMinAddress(snap))
.sorted()
.collect(Collectors.joining(","));
}
@Override
public String getInfoForObjects(Trace trace) {
return getInfoForRegions(trace);
public String getInfoForObjects(Trace trace, long snap) {
return getInfoForRegions(trace, snap);
}
@Override
@@ -85,9 +85,9 @@ public class ByRegionAutoMapSpec implements AutoMapSpec {
@Override
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
List<Program> programs, TaskMonitor monitor) throws CancelledException {
long snap, List<Program> programs, TaskMonitor monitor) throws CancelledException {
Map<?, RegionMapProposal> maps = mappingService
.proposeRegionMaps(trace.getMemoryManager().getAllRegions(), programs);
.proposeRegionMaps(trace.getMemoryManager().getRegionsAtSnap(snap), snap, programs);
Collection<RegionMapEntry> entries = MapProposal.flatten(maps.values());
entries = MapProposal.removeOverlapping(entries);
mappingService.addRegionMappings(entries, monitor, false);
@@ -65,11 +65,12 @@ public class BySectionAutoMapSpec implements AutoMapSpec {
}
@Override
public String getInfoForObjects(Trace trace) {
public String getInfoForObjects(Trace trace, long snap) {
return trace.getModuleManager()
.getAllSections()
.stream()
.map(s -> s.getName() + ":" + s.getStart())
.filter(s -> s.isValid(snap))
.map(s -> s.getName(snap) + ":" + s.getStart(snap))
.sorted()
.collect(Collectors.joining(","));
}
@@ -81,9 +82,9 @@ public class BySectionAutoMapSpec implements AutoMapSpec {
@Override
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
List<Program> programs, TaskMonitor monitor) throws CancelledException {
Map<?, SectionMapProposal> maps = mappingService
.proposeSectionMaps(trace.getModuleManager().getAllModules(), programs);
long snap, List<Program> programs, TaskMonitor monitor) throws CancelledException {
Map<?, SectionMapProposal> maps = mappingService.proposeSectionMaps(
trace.getModuleManager().getLoadedModules(snap), snap, programs);
Collection<SectionMapEntry> entries = MapProposal.flatten(maps.values());
entries = MapProposal.removeOverlapping(entries);
mappingService.addSectionMappings(entries, monitor, false);
@@ -61,7 +61,7 @@ public class NoneAutoMapSpec implements AutoMapSpec {
}
@Override
public String getInfoForObjects(Trace trace) {
public String getInfoForObjects(Trace trace, long snap) {
return "";
}
@@ -71,7 +71,7 @@ public class NoneAutoMapSpec implements AutoMapSpec {
}
@Override
public void runTask(PluginTool tool, Trace trace) {
public void runTask(PluginTool tool, Trace trace, long snap) {
// Don't bother launching a task that does nothing
}
@@ -82,7 +82,7 @@ public class NoneAutoMapSpec implements AutoMapSpec {
@Override
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
List<Program> programs, TaskMonitor monitor) throws CancelledException {
long snap, List<Program> programs, TaskMonitor monitor) throws CancelledException {
return false;
}
}
@@ -62,7 +62,7 @@ public class OneToOneAutoMapSpec implements AutoMapSpec {
}
@Override
public String getInfoForObjects(Trace trace) {
public String getInfoForObjects(Trace trace, long snap) {
return "";
}
@@ -77,12 +77,11 @@ public class OneToOneAutoMapSpec implements AutoMapSpec {
@Override
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
List<Program> programs, TaskMonitor monitor) throws CancelledException {
long snap, List<Program> programs, TaskMonitor monitor) throws CancelledException {
boolean result = false;
for (Program program : programs) {
try {
mappingService.addIdentityMapping(trace, program,
Lifespan.nowOn(trace.getProgramView().getSnap()), false);
mappingService.addIdentityMapping(trace, program, Lifespan.nowOn(snap), false);
result = true;
}
catch (TraceConflictedMappingException e) {
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -85,7 +85,7 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat
return null;
}
int level = coordinates.getFrame();
TraceStackFrame frame = stack.getFrame(level, false);
TraceStackFrame frame = stack.getFrame(snap, level, false);
if (frame == null) {
return null;
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,7 +22,8 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
@@ -64,8 +65,7 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca
if (reg == null) {
return null;
}
Lifespan lifespan = thread.getLifespan();
if (lifespan == null || !lifespan.contains(snap)) {
if (!thread.isValid(snap)) {
return null;
}
TraceMemorySpace regs = reg.getAddressSpace().isRegisterSpace()
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -60,7 +60,8 @@ public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec {
}
Target target = coordinates.getTarget();
TraceMemoryManager mm = coordinates.getTrace().getMemoryManager();
AddressSetView alreadyKnown = mm.getAddressesWithState(coordinates.getSnap(), visible,
long snap = coordinates.getSnap();
AddressSetView alreadyKnown = mm.getAddressesWithState(snap, visible,
s -> s == TraceMemoryState.KNOWN || s == TraceMemoryState.ERROR);
AddressSet toRead = visible.subtract(alreadyKnown);
@@ -70,19 +71,18 @@ public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec {
AddressSet everKnown = new AddressSet();
for (AddressRange range : visible) {
for (Entry<TraceAddressSnapRange, TraceMemoryState> ent : mm
.getMostRecentStates(coordinates.getSnap(), range)) {
for (Entry<TraceAddressSnapRange, TraceMemoryState> ent : mm.getMostRecentStates(snap,
range)) {
everKnown.add(ent.getKey().getRange());
}
}
AddressSet readOnly = new AddressSet();
for (AddressRange range : visible) {
for (TraceMemoryRegion region : mm
.getRegionsIntersecting(Lifespan.at(coordinates.getSnap()), range)) {
if (region.isWrite()) {
for (TraceMemoryRegion region : mm.getRegionsIntersecting(Lifespan.at(snap), range)) {
if (region.isWrite(snap)) {
continue;
}
readOnly.add(region.getRange());
readOnly.add(region.getRange(snap));
}
}
toRead.delete(everKnown.intersect(readOnly));
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -25,7 +25,6 @@ import ghidra.pcode.exec.SleighUtils;
import ghidra.program.model.address.Address;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.thread.TraceThread;
public class BreakpointLocationRow {
private final DebuggerBreakpointsProvider provider;
@@ -36,13 +35,16 @@ public class BreakpointLocationRow {
this.loc = loc;
}
private long getSnap() {
return provider.traceManager.getCurrentFor(loc.getTrace()).getSnap();
}
public String getName() {
return loc.getName();
return loc.getName(getSnap());
}
public boolean isEnabled() {
long snap = provider.traceManager.getCurrentFor(loc.getTrace()).getSnap();
return loc.isEnabled(snap);
return loc.isEnabled(getSnap());
}
public State getState() {
@@ -75,12 +77,12 @@ public class BreakpointLocationRow {
public void setName(String name) {
try (Transaction tid = loc.getTrace().openTransaction("Set breakpoint name")) {
loc.setName(name);
loc.setName(getSnap(), name);
}
}
public Address getAddress() {
return loc.getMinAddress();
return loc.getMinAddress(getSnap());
}
public ProgramLocation getProgramLocation() {
@@ -92,25 +94,26 @@ public class BreakpointLocationRow {
}
public String getThreads() {
return loc.getThreads()
long snap = getSnap();
return loc.getThreads(snap)
.stream()
.map(TraceThread::getName)
.map(t -> t.getName(snap))
.collect(Collectors.toSet())
.toString();
}
public String getComment() {
return loc.getComment();
return loc.getComment(getSnap());
}
public void setComment(String comment) {
try (Transaction tid = loc.getTrace().openTransaction("Set breakpoint comment")) {
loc.setComment(comment);
loc.setComment(getSnap(), comment);
}
}
public boolean hasSleigh() {
return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh());
return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap()));
}
public TraceBreakpoint getTraceBreakpoint() {
@@ -699,7 +699,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
private boolean isVisible(TraceBreakpoint location) {
long snap = traceManager.getCurrentFor(trace).getSnap();
return location.isAlive(snap);
return location.isValid(snap);
}
private void locationAdded(TraceBreakpoint location) {
@@ -1336,7 +1336,8 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
}
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) {
if (!EXECUTE_KINDS.containsAll(tb.getKinds())) {
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
if (!EXECUTE_KINDS.containsAll(tb.getKinds(snap))) {
return false;
}
}
@@ -1368,7 +1369,8 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
}
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) {
String s = tb.getEmuSleigh();
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
String s = tb.getEmuSleigh(snap);
if (sleigh != null && !sleigh.equals(s)) {
return null;
}
@@ -1393,7 +1395,8 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
}
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) {
tb.setEmuSleigh(sleigh);
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
tb.setEmuSleigh(snap, sleigh);
}
}
else {
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -620,23 +620,26 @@ public class DebuggerCopyIntoProgramDialog extends ReusableDialogComponentProvid
protected String computeRegionString(AddressRange rng) {
TraceMemoryManager mm = source.getTrace().getMemoryManager();
long snap = source.getSnap();
Collection<? extends TraceMemoryRegion> regions =
mm.getRegionsIntersecting(Lifespan.at(source.getSnap()), rng);
return regions.isEmpty() ? "UNKNOWN" : regions.iterator().next().getName();
mm.getRegionsIntersecting(Lifespan.at(snap), rng);
return regions.isEmpty() ? "UNKNOWN" : regions.iterator().next().getName(snap);
}
protected String computeModulesString(AddressRange rng) {
TraceModuleManager mm = source.getTrace().getModuleManager();
long snap = source.getSnap();
Collection<? extends TraceModule> modules =
mm.getModulesIntersecting(Lifespan.at(source.getSnap()), rng);
return modules.stream().map(m -> m.getName()).collect(Collectors.joining(","));
mm.getModulesIntersecting(Lifespan.at(snap), rng);
return modules.stream().map(m -> m.getName(snap)).collect(Collectors.joining(","));
}
protected String computeSectionsString(AddressRange rng) {
TraceModuleManager mm = source.getTrace().getModuleManager();
long snap = source.getSnap();
Collection<? extends TraceSection> sections =
mm.getSectionsIntersecting(Lifespan.at(source.getSnap()), rng);
return sections.stream().map(s -> s.getName()).collect(Collectors.joining(","));
mm.getSectionsIntersecting(Lifespan.at(snap), rng);
return sections.stream().map(s -> s.getName(snap)).collect(Collectors.joining(","));
}
protected void createEntry(Collection<RangeEntry> result, AddressRange srcRange,
@@ -692,10 +695,11 @@ public class DebuggerCopyIntoProgramDialog extends ReusableDialogComponentProvid
protected List<AddressRange> breakRangeByRegions(AddressRange srcRange) {
AddressSet remains = new AddressSet(srcRange);
List<AddressRange> result = new ArrayList<>();
long snap = source.getSnap();
for (TraceMemoryRegion region : source.getTrace()
.getMemoryManager()
.getRegionsIntersecting(Lifespan.at(source.getSnap()), srcRange)) {
AddressRange range = region.getRange().intersect(srcRange);
.getRegionsIntersecting(Lifespan.at(snap), srcRange)) {
AddressRange range = region.getRange(snap).intersect(srcRange);
result.add(range);
remains.delete(range);
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -219,21 +219,22 @@ public class DebuggerCopyPlan {
@Override
public void copy(TraceProgramView from, AddressRange fromRange, Program into,
Address intoAddress, TaskMonitor monitor) throws Exception {
long snap = from.getSnap();
for (TraceBreakpoint bpt : from.getTrace()
.getBreakpointManager()
.getBreakpointsIntersecting(Lifespan.at(from.getSnap()), fromRange)) {
monitor.checkCancelled();
long off = bpt.getMinAddress().subtract(fromRange.getMinAddress());
long off = bpt.getMinAddress(snap).subtract(fromRange.getMinAddress());
Address dest = intoAddress.add(off);
ProgramBreakpoint pb =
new ProgramBreakpoint(into, dest, bpt.getLength(), bpt.getKinds());
new ProgramBreakpoint(into, dest, bpt.getLength(snap), bpt.getKinds(snap));
if (bpt.isEnabled(from.getSnap())) {
pb.enable();
}
else {
pb.disable();
}
pb.setEmuSleigh(bpt.getEmuSleigh());
pb.setEmuSleigh(bpt.getEmuSleigh(snap));
}
}
},
@@ -1081,13 +1081,13 @@ public class DebuggerListingProvider extends CodeViewerProvider {
Set<DomainFile> toOpen = new HashSet<>();
TraceModuleManager modMan = trace.getModuleManager();
Collection<TraceModule> modules = Stream.concat(
modMan.getModulesAt(snap, address).stream().filter(m -> m.getSections().isEmpty()),
modMan.getModulesAt(snap, address).stream().filter(m -> m.getSections(snap).isEmpty()),
modMan.getSectionsAt(snap, address).stream().map(s -> s.getModule()))
.collect(Collectors.toSet());
// Attempt to open probable matches. All others, list to import
for (TraceModule mod : modules) {
DomainFile match = mappingService.findBestModuleProgram(space, mod);
DomainFile match = mappingService.findBestModuleProgram(space, mod, snap);
if (match == null) {
missing.add(mod);
}
@@ -1108,7 +1108,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
for (TraceModule mod : missing) {
consoleService.log(DebuggerResources.ICON_LOG_ERROR,
"<html>The module <b><tt>" + HTMLUtilities.escapeHTML(mod.getName()) +
"<html>The module <b><tt>" + HTMLUtilities.escapeHTML(mod.getName(snap)) +
"</tt></b> was not found in the project</html>",
new DebuggerMissingModuleActionContext(mod));
}
@@ -1139,12 +1139,13 @@ public class DebuggerListingProvider extends CodeViewerProvider {
if (!affectedTraces.contains(module.getTrace())) {
continue;
}
if (isMapped(module.getRange())) {
long snap = traceManager.getCurrentFor(module.getTrace()).getSnap();
if (isMapped(module.getRange(snap))) {
consoleService.removeFromLog(mmCtx);
continue;
}
for (TraceSection section : module.getSections()) {
if (isMapped(section.getRange())) {
for (TraceSection section : module.getSections(snap)) {
if (isMapped(section.getRange(snap))) {
consoleService.removeFromLog(mmCtx);
continue nextCtx;
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -71,13 +71,14 @@ public class MemoryStateListingBackgroundColorModel implements ListingBackground
}
protected Color getUnknownColor(Address address) {
long snap = view.getSnap();
Entry<TraceAddressSnapRange, TraceMemoryState> ent =
memory.getViewMostRecentStateEntry(view.getSnap(), address);
memory.getViewMostRecentStateEntry(snap, address);
if (ent == null || ent.getValue() != TraceMemoryState.KNOWN) {
return COLOR_BACKGROUND_UNKNOWN;
}
TraceMemoryRegion region = memory.getRegionContaining(ent.getKey().getY1(), address);
if (region != null && !region.isWrite()) {
if (region != null && !region.isWrite(snap)) {
return COLOR_BACKGROUND_UNKNOWN_BLENDED;
}
return COLOR_BACKGROUND_UNKNOWN;
@@ -40,7 +40,8 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.memory.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.util.TraceEvents;
@@ -53,7 +54,6 @@ public class DebuggerLegacyRegionsPanel extends JPanel {
protected enum RegionTableColumns
implements EnumeratedTableColumn<RegionTableColumns, RegionRow> {
NAME("Name", String.class, RegionRow::getName, RegionRow::setName),
LIFESPAN("Lifespan", Lifespan.class, RegionRow::getLifespan),
START("Start", Address.class, RegionRow::getMinAddress),
END("End", Address.class, RegionRow::getMaxAddress),
LENGTH("Length", Long.class, RegionRow::getLength),
@@ -159,7 +159,7 @@ public class DebuggerLegacyRegionsPanel extends JPanel {
}
AddressSet sel = new AddressSet();
for (TraceMemoryRegion s : regions) {
sel.add(s.getRange());
sel.add(s.getRange(0));
}
ProgramSelection ps = new ProgramSelection(sel);
listingService.setCurrentSelection(ps);
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -42,8 +42,8 @@ public class DebuggerRegionMapProposalDialog
protected enum RegionMapTableColumns
implements EnumeratedTableColumn<RegionMapTableColumns, RegionMapEntry> {
REMOVE("Remove", String.class, e -> "Remove Proposed Entry", (e, v) -> nop()),
REGION_NAME("Region", String.class, e -> e.getRegion().getName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getRegion().getMinAddress()),
REGION_NAME("Region", String.class, e -> e.getRegionName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getRegionMinAddress()),
CHOOSE("Choose", String.class, e -> "Choose Block", (e, s) -> nop()),
PROGRAM_NAME("Program", String.class, e -> e.getToProgram().getName()),
BLOCK_NAME("Block", String.class, e -> e.getBlock().getName()),
@@ -193,7 +193,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
}
AddressSet sel = new AddressSet();
for (TraceMemoryRegion s : regions) {
sel.add(s.getRange());
sel.add(s.getRange(current.getSnap()));
}
ProgramSelection ps = new ProgramSelection(sel);
listingService.setCurrentSelection(ps);
@@ -403,7 +403,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
return;
}
Map<?, RegionMapProposal> map = staticMappingService.proposeRegionMaps(regions,
List.of(programManager.getAllOpenPrograms()));
current.getSnap(), List.of(programManager.getAllOpenPrograms()));
Collection<RegionMapEntry> proposal = MapProposal.flatten(map.values());
promptRegionProposal(proposal);
}
@@ -416,7 +416,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
if (program == null) {
return;
}
RegionMapProposal map = staticMappingService.proposeRegionMap(regions, program);
RegionMapProposal map =
staticMappingService.proposeRegionMap(regions, current.getSnap(), program);
Collection<RegionMapEntry> proposal = map.computeMap().values();
promptRegionProposal(proposal);
}
@@ -431,7 +432,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
return;
}
RegionMapProposal map =
staticMappingService.proposeRegionMap(region, location.getProgram(), block);
staticMappingService.proposeRegionMap(region, current.getSnap(), location.getProgram(),
block);
promptRegionProposal(map.computeMap().values());
}
@@ -548,7 +550,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
Msg.warn(this, "No program manager!");
return null;
}
return blockChooserDialog.chooseBlock(getTool(), region,
return blockChooserDialog.chooseBlock(getTool(), region, current.getSnap(),
List.of(programManager.getAllOpenPrograms()));
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,7 +18,6 @@ package ghidra.app.plugin.core.debug.gui.memory;
import db.Transaction;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.memory.TraceMemoryRegion;
public class RegionRow {
@@ -34,84 +33,71 @@ public class RegionRow {
public void setName(String name) {
try (Transaction tx = region.getTrace().openTransaction("Rename region")) {
region.setName(name);
region.setName(0, name);
}
}
public String getName() {
return region.getName();
}
public Lifespan getLifespan() {
return region.getLifespan();
}
public long getCreatedSnap() {
return region.getCreationSnap();
}
public String getDestroyedSnap() {
long snap = region.getDestructionSnap();
return snap == Long.MAX_VALUE ? "" : Long.toString(snap);
return region.getName(0);
}
public AddressRange getRange() {
return region.getRange();
return region.getRange(0);
}
public Address getMaxAddress() {
return region.getMaxAddress();
return region.getMaxAddress(0);
}
public Address getMinAddress() {
return region.getMinAddress();
return region.getMinAddress(0);
}
public long getLength() {
return region.getLength();
return region.getLength(0);
}
public void setRead(boolean read) {
try (Transaction tx =
region.getTrace().openTransaction("Toggle region read flag")) {
region.setRead(read);
region.setRead(0, read);
}
}
public boolean isRead() {
return region.isRead();
return region.isRead(0);
}
public void setWrite(boolean write) {
try (Transaction tx =
region.getTrace().openTransaction("Toggle region write flag")) {
region.setWrite(write);
region.setWrite(0, write);
}
}
public boolean isWrite() {
return region.isWrite();
return region.isWrite(0);
}
public void setExecute(boolean execute) {
try (Transaction tx =
region.getTrace().openTransaction("Toggle region execute flag")) {
region.setExecute(execute);
region.setExecute(0, execute);
}
}
public boolean isExecute() {
return region.isExecute();
return region.isExecute(0);
}
public void setVolatile(boolean vol) {
try (Transaction tx =
region.getTrace().openTransaction("Toggle region volatile flag")) {
region.setVolatile(vol);
region.setVolatile(0, vol);
}
}
public boolean isVolatile() {
return region.isVolatile();
return region.isVolatile(0);
}
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,14 +21,13 @@ import ghidra.async.AsyncDebouncer;
import ghidra.async.AsyncTimer;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.program.model.address.*;
import ghidra.trace.database.module.TraceObjectSection;
import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointManager;
import ghidra.trace.model.memory.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.breakpoint.*;
import ghidra.trace.model.memory.*;
import ghidra.trace.model.modules.*;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.thread.TraceThreadManager;
import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.thread.*;
import ghidra.trace.util.TraceEvents;
import ghidra.util.Swing;
@@ -91,60 +90,79 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
}
private void threadChanged(TraceThread thread) {
if (!trackThreads || !trackTrace) {
if (!trackThreads || !trackTrace || !(thread instanceof TraceObjectThread objThread)) {
return;
}
AddressFactory factory = thread.getTrace().getBaseAddressFactory();
AddressSpace defaultSpace = factory.getDefaultAddressSpace();
Long threadId = thread.getKey();
AddressRange rng = rng(defaultSpace, threadId, threadId);
MemoryBox box = new MemoryBox("Thread " + thread.getName(), MemviewBoxType.THREAD, rng,
thread.getLifespan());
updateList.add(box);
TraceObject obj = objThread.getObject();
obj.getCanonicalParents(Lifespan.ALL).forEach(p -> {
MemoryBox box = new MemoryBox("Thread " + thread.getName(p.getMinSnap()),
MemviewBoxType.THREAD, rng, p.getLifespan());
updateList.add(box);
});
updateLabelDebouncer.contact(null);
}
private void regionChanged(TraceMemoryRegion region) {
if (!trackRegions || !trackTrace) {
if (!trackRegions || !trackTrace ||
!(region instanceof TraceObjectMemoryRegion objRegion)) {
return;
}
MemoryBox box = new MemoryBox("Region " + region.getName(), MemviewBoxType.VIRTUAL_ALLOC,
region.getRange(), region.getLifespan());
updateList.add(box);
TraceObject obj = objRegion.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectMemoryRegion.KEY_RANGE, true).forEach(v -> {
MemoryBox box = new MemoryBox("Region " + region.getName(v.getMinSnap()),
MemviewBoxType.VIRTUAL_ALLOC, v.castValue(), v.getLifespan());
updateList.add(box);
});
updateLabelDebouncer.contact(null);
}
private void moduleChanged(TraceModule module) {
if (!trackModules || !trackTrace) {
if (!trackModules || !trackTrace || !(module instanceof TraceObjectModule objModule)) {
return;
}
AddressRange range = module.getRange();
if (range == null) {
return;
}
MemoryBox box = new MemoryBox("Module " + module.getName(), MemviewBoxType.MODULE, range,
module.getLifespan());
updateList.add(box);
TraceObject obj = objModule.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectModule.KEY_RANGE, true).forEach(v -> {
MemoryBox box = new MemoryBox("Module " + module.getName(v.getMinSnap()),
MemviewBoxType.MODULE, v.castValue(), v.getLifespan());
updateList.add(box);
});
updateLabelDebouncer.contact(null);
}
private void sectionChanged(TraceSection section) {
if (!trackSections || !trackTrace) {
if (!trackSections || !trackTrace || !(section instanceof TraceObjectSection objSection)) {
return;
}
MemoryBox box = new MemoryBox("Section " + section.getName(), MemviewBoxType.IMAGE,
section.getRange(), section.getModule().getLifespan());
updateList.add(box);
TraceObject obj = objSection.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectSection.KEY_RANGE, true).forEach(v -> {
MemoryBox box = new MemoryBox("Module " + section.getName(v.getMinSnap()),
MemviewBoxType.IMAGE, v.castValue(), v.getLifespan());
updateList.add(box);
});
updateLabelDebouncer.contact(null);
}
private void breakpointChanged(TraceBreakpoint bpt) {
if (!trackBreakpoints || !trackTrace) {
if (!trackBreakpoints || !trackTrace ||
!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
return;
}
MemoryBox box = new MemoryBox("Breakpoint " + bpt.getName(), MemviewBoxType.BREAKPOINT,
bpt.getRange(), bpt.getLifespan());
updateList.add(box);
TraceObject obj = objBpt.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
.forEach(v -> {
MemoryBox box = new MemoryBox("Module " + bpt.getName(v.getMinSnap()),
MemviewBoxType.BREAKPOINT, v.castValue(), v.getLifespan());
updateList.add(box);
});
updateLabelDebouncer.contact(null);
}
@@ -238,7 +256,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
TraceModuleManager moduleManager = trace.getModuleManager();
for (TraceModule module : moduleManager.getAllModules()) {
moduleChanged(module);
Collection<? extends TraceSection> sections = module.getSections();
Collection<? extends TraceSection> sections = module.getAllSections();
for (TraceSection section : sections) {
sectionChanged(section);
}
@@ -34,7 +34,7 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.trace.model.Trace;
import ghidra.trace.model.target.*;
import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.iface.TraceObjectInterface;
import ghidra.trace.model.target.path.KeyPath;
@@ -115,7 +115,8 @@ public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterf
List<ValueRow> sel = getSelectedItems();
if (!sel.isEmpty()) {
myActionContext = new DebuggerObjectActionContext(
sel.stream().map(r -> r.getValue()).collect(Collectors.toList()), provider, table);
sel.stream().map(r -> r.getValue()).collect(Collectors.toList()), provider, table,
current.getSnap());
}
}
@@ -541,7 +541,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
.map(n -> n.getValue())
.filter(o -> o != null) // Root for no trace would return null
.collect(Collectors.toList()),
DebuggerModelProvider.this, objectsTreePanel);
DebuggerModelProvider.this, objectsTreePanel, current.getSnap());
}
}
@@ -610,7 +610,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
return new DebuggerObjectActionContext(sel.stream()
.map(r -> r.getValue())
.collect(Collectors.toList()),
DebuggerModelProvider.this, elementsTablePanel);
DebuggerModelProvider.this, elementsTablePanel, current.getSnap());
}
}
@@ -664,7 +664,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
return new DebuggerObjectActionContext(sel.stream()
.map(r -> Objects.requireNonNull(r.getPath().getLastEntry()))
.collect(Collectors.toList()),
DebuggerModelProvider.this, attributesTablePanel);
DebuggerModelProvider.this, attributesTablePanel, current.getSnap());
}
}
@@ -768,7 +768,8 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
return;
}
Map<String, ActionEntry> actions = target.collectActions(ActionName.REFRESH,
new DebuggerObjectActionContext(List.of(value), this, objectsTreePanel));
new DebuggerObjectActionContext(List.of(value), this, objectsTreePanel,
current.getSnap()));
for (ActionEntry ent : actions.values()) {
if (ent.requiresPrompt()) {
continue;
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -53,7 +53,8 @@ public class DebuggerLegacyModulesPanel extends JPanel {
DebuggerModuleActionContext context) {
return context.getSelectedModules()
.stream()
.flatMap(m -> m.getSections().stream())
// snap does not matter for legacy module
.flatMap(m -> m.getSections(0).stream())
.collect(Collectors.toSet());
}
@@ -61,7 +62,8 @@ public class DebuggerLegacyModulesPanel extends JPanel {
DebuggerModuleActionContext context) {
AddressSet sel = new AddressSet();
for (TraceModule module : getSelectedModulesFromContext(context)) {
sel.add(module.getRange());
// snap does not matter for legacy module
sel.add(module.getRange(0));
}
return sel;
}
@@ -73,7 +75,6 @@ public class DebuggerLegacyModulesPanel extends JPanel {
SHORT_NAME("Name", String.class, ModuleRow::getShortName),
NAME("Module Name", String.class, ModuleRow::getName, ModuleRow::setName),
MAPPING("Mapping", String.class, ModuleRow::getMapping),
LIFESPAN("Lifespan", Lifespan.class, ModuleRow::getLifespan),
LENGTH("Length", Long.class, ModuleRow::getLength);
private final String header;
@@ -251,7 +252,7 @@ public class DebuggerLegacyModulesPanel extends JPanel {
moduleTableModel.addAllItems(moduleManager.getAllModules());
}
public void setTrace(Trace trace) {
private void setTrace(Trace trace) {
if (currentTrace == trace) {
return;
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -48,7 +48,7 @@ public class DebuggerLegacySectionsPanel extends JPanel {
protected static Set<TraceModule> getSelectedModulesFromContext(
DebuggerSectionActionContext context) {
return context.getSelectedSections(false)
return context.getSelectedSections(false, 0)
.stream()
.map(r -> r.getModule())
.collect(Collectors.toSet());
@@ -56,14 +56,14 @@ public class DebuggerLegacySectionsPanel extends JPanel {
protected static Set<TraceSection> getSelectedSectionsFromContext(
DebuggerSectionActionContext context, boolean allowExpansion) {
return context.getSelectedSections(allowExpansion);
return context.getSelectedSections(allowExpansion, 0);
}
protected static AddressSetView getSelectedAddressesFromContext(
DebuggerSectionActionContext context) {
AddressSet sel = new AddressSet();
for (TraceSection section : getSelectedSectionsFromContext(context, false)) {
sel.add(section.getRange());
sel.add(section.getRange(0));
}
return sel;
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -41,7 +41,7 @@ public class DebuggerModuleMapProposalDialog
protected enum ModuleMapTableColumns
implements EnumeratedTableColumn<ModuleMapTableColumns, ModuleMapEntry> {
REMOVE("Remove", String.class, e -> "Remove Proposed Entry", (e, v) -> nop()),
MODULE_NAME("Module", String.class, e -> e.getModule().getName()),
MODULE_NAME("Module", String.class, e -> e.getModuleName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getFromRange().getMinAddress()),
CHOOSE("Choose", String.class, e -> "Choose Program", (e, v) -> nop()),
PROGRAM_NAME("Program", String.class, e -> (e.getToProgram().getDomainFile() == null
@@ -190,7 +190,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
TraceObject child = value.getChild();
TraceObjectModule module = child.queryInterface(TraceObjectModule.class);
if (module != null) {
result.addAll(module.getSections());
result.addAll(module.getSections(ctx.getSnap()));
continue;
}
TraceObjectSection section = child.queryInterface(TraceObjectSection.class);
@@ -208,12 +208,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
TraceObject child = value.getChild();
TraceObjectModule module = child.queryInterface(TraceObjectModule.class);
if (module != null) {
result.add(module.getRange());
result.add(module.getRange(ctx.getSnap()));
continue;
}
TraceObjectSection section = child.queryInterface(TraceObjectSection.class);
if (section != null) {
result.add(section.getRange());
result.add(section.getRange(ctx.getSnap()));
continue;
}
}
@@ -402,13 +402,20 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
return;
}
couldHaveChanged = false;
String infosThisTime = spec.getInfoForObjects(trace);
DebuggerTraceManagerService traceManager =
tool.getService(DebuggerTraceManagerService.class);
if (traceManager == null) {
return;
}
DebuggerCoordinates current = traceManager.getCurrentFor(trace);
long snap = current.getSnap();
String infosThisTime = spec.getInfoForObjects(trace, snap);
if (Objects.equals(infosThisTime, infosLastTime)) {
return;
}
infosLastTime = infosThisTime;
spec.runTask(tool, trace);
spec.runTask(tool, trace, snap);
}
public void forceMap() {
@@ -593,7 +600,6 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
boolean filterSectionsByModules = false;
private final Map<Trace, AutoMapState> autoMapStateByTrace = new WeakHashMap<>();
private AutoMapState forMappingListener;
DockingAction actionImportMissingModule;
DockingAction actionMapMissingModule;
@@ -634,7 +640,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
private void importModuleFromFileSystem(TraceModule module) {
GhidraFileChooser chooser = new GhidraFileChooser(getComponent());
chooser.setSelectedFile(new File(module.getName()));
chooser.setSelectedFile(new File(module.getName(current.getSnap())));
File file = chooser.getSelectedFile();
chooser.dispose();
if (file == null) { // Perhaps cancelled
@@ -837,7 +843,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
return !ctx.getSelectedModules().isEmpty();
}
if (context instanceof DebuggerSectionActionContext ctx) {
return !ctx.getSelectedSections(false).isEmpty();
return !ctx.getSelectedSections(false, current.getSnap()).isEmpty();
}
if (context instanceof DebuggerObjectActionContext ctx) {
return !ctx.getObjectValues().isEmpty();
@@ -978,10 +984,13 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
if (staticMappingService == null) {
return;
}
Program program = context.getProgram();
Trace trace = context.getTrace();
long snap = traceManager.getCurrentFor(trace).getSnap();
Map<TraceModule, ModuleMapProposal> map = staticMappingService.proposeModuleMaps(
trace.getModuleManager().getAllModules(), List.of(program));
trace.getModuleManager().getAllModules(), snap, List.of(program));
Collection<ModuleMapEntry> proposal = MapProposal.flatten(map.values());
promptModuleProposal(proposal, FMT_NO_MODULES_PROPOSAL_RETRY.formatted(
trace.getDomainFile().getName(), program.getDomainFile().getName()));
@@ -1022,10 +1031,10 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
Program program = context.getProgram();
ModuleMapProposal proposal =
staticMappingService.proposeModuleMap(module, program);
staticMappingService.proposeModuleMap(module, snap, program);
Map<TraceModule, ModuleMapEntry> map = proposal.computeMap();
promptModuleProposal(map.values(), FMT_NO_MODULES_PROPOSAL_CURRENT.formatted(
module.getName(), program.getDomainFile().getName()));
module.getName(snap), program.getDomainFile().getName()));
}
private void activatedMapMissingProgramIdentically(
@@ -1089,16 +1098,16 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
return;
}
long snap = current.getSnap();
ProgramSelection progSel = listingService.getCurrentSelection();
TraceModuleManager moduleManager = current.getTrace().getModuleManager();
if (progSel != null && !progSel.isEmpty()) {
long snap = traceManager.getCurrentSnap();
Set<TraceModule> modSel = new HashSet<>();
Set<TraceSection> sectionSel = new HashSet<>();
for (AddressRange range : progSel) {
for (TraceModule module : moduleManager
.getModulesIntersecting(Lifespan.at(snap), range)) {
if (module.getSections().isEmpty()) {
if (module.getSections(snap).isEmpty()) {
modSel.add(module);
}
}
@@ -1127,7 +1136,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
TraceModule bestModule = null;
for (TraceModule module : moduleManager
.getLoadedModules(traceManager.getCurrentSnap())) {
Address base = module.getBase();
Address base = module.getBase(snap);
if (base == null || base.getAddressSpace() != address.getAddressSpace()) {
continue;
}
@@ -1138,12 +1147,12 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
if (base.compareTo(address) > 0) {
continue;
}
if (base.compareTo(bestModule.getBase()) <= 0) {
if (base.compareTo(bestModule.getBase(snap)) <= 0) {
continue;
}
bestModule = module;
}
if (bestModule.getSections().isEmpty()) {
if (bestModule.getSections(snap).isEmpty()) {
setSelectedModules(Set.of(bestModule));
return;
}
@@ -1168,8 +1177,9 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
if (staticMappingService == null) {
return;
}
Map<TraceModule, ModuleMapProposal> map = staticMappingService.proposeModuleMaps(modules,
List.of(programManager.getAllOpenPrograms()));
Map<TraceModule, ModuleMapProposal> map =
staticMappingService.proposeModuleMaps(modules, current.getSnap(),
List.of(programManager.getAllOpenPrograms()));
Collection<ModuleMapEntry> proposal = MapProposal.flatten(map.values());
promptModuleProposal(proposal, NO_MODULES_PROPOSAL_SEL);
}
@@ -1182,7 +1192,8 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
if (program == null) {
return;
}
ModuleMapProposal proposal = staticMappingService.proposeModuleMap(module, program);
ModuleMapProposal proposal =
staticMappingService.proposeModuleMap(module, current.getSnap(), program);
Map<TraceModule, ModuleMapEntry> map = proposal.computeMap();
promptModuleProposal(map.values(), NO_MODULES_PROPOSAL_SEL);
}
@@ -1209,8 +1220,9 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
}
Set<TraceModule> modules =
sections.stream().map(TraceSection::getModule).collect(Collectors.toSet());
Map<?, SectionMapProposal> map = staticMappingService.proposeSectionMaps(modules,
List.of(programManager.getAllOpenPrograms()));
Map<?, SectionMapProposal> map =
staticMappingService.proposeSectionMaps(modules, current.getSnap(),
List.of(programManager.getAllOpenPrograms()));
Collection<SectionMapEntry> proposal = MapProposal.flatten(map.values());
Collection<SectionMapEntry> filtered = proposal.stream()
.filter(e -> sections.contains(e.getSection()))
@@ -1232,7 +1244,8 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
return;
}
TraceModule module = modules.iterator().next();
SectionMapProposal map = staticMappingService.proposeSectionMap(module, program);
SectionMapProposal map =
staticMappingService.proposeSectionMap(module, current.getSnap(), program);
Collection<SectionMapEntry> proposal = map.computeMap().values();
Collection<SectionMapEntry> filtered = proposal.stream()
.filter(e -> sections.contains(e.getSection()))
@@ -1249,8 +1262,8 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
if (block == null) {
return;
}
SectionMapProposal map =
staticMappingService.proposeSectionMap(section, location.getProgram(), block);
SectionMapProposal map = staticMappingService.proposeSectionMap(section, current.getSnap(),
location.getProgram(), block);
promptSectionProposal(map.computeMap().values());
}
@@ -1444,7 +1457,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
Msg.warn(this, "No program manager!");
return null;
}
return blockChooserDialog.chooseBlock(getTool(), section,
return blockChooserDialog.chooseBlock(getTool(), section, current.getSnap(),
List.of(programManager.getAllOpenPrograms()));
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -45,10 +45,10 @@ public class DebuggerSectionActionContext extends DefaultActionContext {
this.forcedSingle = forcedSingle;
}
public Set<TraceSection> getSelectedSections(boolean allowExpansion) {
public Set<TraceSection> getSelectedSections(boolean allowExpansion, long snap) {
if (forcedSingle && allowExpansion) {
return selectedSections.stream()
.flatMap(s -> s.getModule().getSections().stream())
.flatMap(s -> s.getModule().getSections(snap).stream())
.collect(Collectors.toUnmodifiableSet());
}
return selectedSections;
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -42,9 +42,9 @@ public class DebuggerSectionMapProposalDialog
protected enum SectionMapTableColumns
implements EnumeratedTableColumn<SectionMapTableColumns, SectionMapEntry> {
REMOVE("Remove", String.class, e -> "Remove Proposed Entry", (e, v) -> nop()),
MODULE_NAME("Module", String.class, e -> e.getModule().getName()),
SECTION_NAME("Section", String.class, e -> e.getSection().getName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getSection().getStart()),
MODULE_NAME("Module", String.class, e -> e.getModuleName()),
SECTION_NAME("Section", String.class, e -> e.getSectionName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getSectionStart()),
CHOOSE("Choose", String.class, e -> "Choose Block", (e, s) -> nop()),
PROGRAM_NAME("Program", String.class, e -> e.getToProgram().getName()),
BLOCK_NAME("Block", String.class, e -> e.getBlock().getName()),
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,7 +18,6 @@ package ghidra.app.plugin.core.debug.gui.modules;
import db.Transaction;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
import ghidra.program.model.address.Address;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.modules.TraceModule;
public class ModuleRow {
@@ -36,16 +35,16 @@ public class ModuleRow {
public void setName(String name) {
try (Transaction tx = module.getTrace().openTransaction("Renamed module")) {
module.setName(name);
module.setName(0, name);
}
}
public String getShortName() {
return DebuggerStaticMappingUtils.computeModuleShortName(module.getName());
return DebuggerStaticMappingUtils.computeModuleShortName(module.getName(0));
}
public String getName() {
return module.getName();
return module.getName(0);
}
public String getMapping() {
@@ -54,31 +53,18 @@ public class ModuleRow {
// 2. Range/Life changes to this module
// 3. Snapshot navigation
return DebuggerStaticMappingUtils.computeMappedFiles(module.getTrace(),
provider.current.getSnap(), module.getRange());
provider.current.getSnap(), module.getRange(0));
}
public Address getBase() {
return module.getBase();
return module.getBase(0);
}
public Address getMaxAddress() {
return module.getMaxAddress();
}
public long getLoadedSnap() {
return module.getLoadedSnap();
}
public Long getUnloadedSnap() {
long snap = module.getUnloadedSnap();
return snap == Long.MAX_VALUE ? null : snap;
}
public Lifespan getLifespan() {
return module.getLifespan();
return module.getMaxAddress(0);
}
public long getLength() {
return module.getLength();
return module.getLength(0);
}
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,8 +18,6 @@ package ghidra.app.plugin.core.debug.gui.modules;
import db.Transaction;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.DefaultTraceLocation;
import ghidra.trace.model.TraceLocation;
import ghidra.trace.model.modules.TraceModule;
import ghidra.trace.model.modules.TraceSection;
import ghidra.util.Msg;
@@ -42,7 +40,7 @@ public class SectionRow {
public void setName(String name) {
try (Transaction tx = section.getTrace().openTransaction("Rename section")) {
section.setName(name);
section.setName(0, name);
}
catch (DuplicateNameException e) {
Msg.showError(this, null, "Rename Section",
@@ -51,31 +49,26 @@ public class SectionRow {
}
public String getName() {
return section.getName();
return section.getName(0);
}
public String getModuleName() {
return section.getModule().getName();
return section.getModule().getName(0);
}
public AddressRange getRange() {
return section.getRange();
return section.getRange(0);
}
public Address getStart() {
return section.getStart();
return section.getStart(0);
}
public Address getEnd() {
return section.getEnd();
return section.getEnd(0);
}
public long getLength() {
return section.getRange().getLength();
}
public TraceLocation getTraceLocation() {
return new DefaultTraceLocation(section.getModule().getTrace(), null,
section.getModule().getLifespan(), section.getStart());
return section.getRange(0).getLength();
}
}
@@ -783,7 +783,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
protected String computeSubTitle() {
TraceThread curThread = current.getThread();
return curThread == null ? "" : curThread.getName();
return curThread == null ? "" : curThread.getName(current.getSnap());
}
protected void updateSubTitle() {
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -129,9 +129,6 @@ public class DebuggerLegacyStackPanel extends JPanel {
}
private void stackAdded(TraceStack stack) {
if (stack.getSnap() != current.getViewSnap()) {
return;
}
TraceThread curThread = current.getThread();
if (curThread != stack.getThread()) {
return;
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -145,7 +145,7 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
protected String computeSubTitle() {
TraceThread curThread = current.getThread();
return curThread == null ? "" : curThread.getName();
return curThread == null ? "" : curThread.getName(current.getSnap());
}
protected void updateSubTitle() {
@@ -269,9 +269,10 @@ public enum VariableValueUtils {
RegisterValue spRV = regs.getValue(platform, viewSnap, sp);
Address spVal = cSpec.getStackBaseSpace().getAddress(spRV.getUnsignedValue().longValue());
Address max;
TraceMemoryRegion stackRegion = mem.getRegionContaining(coordinates.getSnap(), spVal);
long snap = coordinates.getSnap();
TraceMemoryRegion stackRegion = mem.getRegionContaining(snap, spVal);
if (stackRegion != null) {
max = stackRegion.getMaxAddress();
max = stackRegion.getMaxAddress(snap);
}
else {
long toMax = spVal.getAddressSpace().getMaxAddress().subtract(spVal);
@@ -408,7 +409,7 @@ public enum VariableValueUtils {
if (stack == null) {
return null;
}
TraceStackFrame frame = stack.getFrame(0, false);
TraceStackFrame frame = stack.getFrame(snap, 0, false);
if (frame == null) {
return null;
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -38,10 +38,10 @@ import ghidra.framework.model.DomainObjectEvent;
import ghidra.framework.plugintool.AutoService;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.thread.TraceThreadManager;
import ghidra.trace.model.time.TraceSnapshot;
import ghidra.trace.util.TraceEvents;
import ghidra.util.database.ObjectKey;
import ghidra.util.table.GhidraTable;
@@ -62,12 +62,9 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
true, true),
MODULE("Module", String.class, ThreadRow::getModule, true, false),
SP("SP", Address.class, ThreadRow::getStackPointer, true, false),
CREATED("Created", Long.class, ThreadRow::getCreationSnap, true, false),
DESTROYED("Destroyed", String.class, ThreadRow::getDestructionSnap, true, false),
STATE("State", ThreadState.class, ThreadRow::getState, true, true),
COMMENT("Comment", String.class, ThreadRow::getComment, ThreadRow::setComment, true, false),
PLOT("Plot", Lifespan.class, ThreadRow::getLifespan, false, true);
COMMENT("Comment", String.class, ThreadRow::getComment, ThreadRow::setComment, true, false);
private final String header;
private final Function<ThreadRow, ?> getter;
@@ -145,9 +142,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
listenFor(TraceEvents.THREAD_CHANGED, this::threadChanged);
listenFor(TraceEvents.THREAD_LIFESPAN_CHANGED, this::threadChanged);
listenFor(TraceEvents.THREAD_DELETED, this::threadDeleted);
listenFor(TraceEvents.SNAPSHOT_ADDED, this::snapAdded);
listenFor(TraceEvents.SNAPSHOT_DELETED, this::snapDeleted);
}
private void objectRestored(DomainObjectChangeRecord rec) {
@@ -165,14 +159,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
private void threadDeleted(TraceThread thread) {
threadTableModel.deleteItem(thread);
}
private void snapAdded(TraceSnapshot snapshot) {
updateTimelineMax();
}
private void snapDeleted() {
updateTimelineMax();
}
}
private final DebuggerThreadsProvider provider;
@@ -187,10 +173,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
private final ForThreadsListener forThreadsListener = new ForThreadsListener();
/* package access for testing */
final SpanTableCellRenderer<Long> spanRenderer = new SpanTableCellRenderer<>();
final RangeCursorTableHeaderRenderer<Long> headerRenderer;
final TableCellRenderer boldCurrentRenderer = new AbstractGColumnRenderer<Object>() {
@Override
public String getFilterString(Object t, Settings settings) {
@@ -225,8 +207,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
this.autoServiceWiring = AutoService.wireServicesConsumed(plugin, this);
threadTableModel = new ThreadTableModel(provider);
headerRenderer = new RangeCursorTableHeaderRenderer<>(0L,
threadTableModel.getColumn(ThreadTableColumns.PLOT.ordinal()));
threadTable = new GhidraTable(threadTableModel);
threadTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
add(new JScrollPane(threadTable));
@@ -269,32 +249,10 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
TableColumnModel columnModel = threadTable.getColumnModel();
TableColumn colName = columnModel.getColumn(ThreadTableColumns.NAME.ordinal());
colName.setCellRenderer(boldCurrentRenderer);
TableColumn colCreated = columnModel.getColumn(ThreadTableColumns.CREATED.ordinal());
colCreated.setCellRenderer(boldCurrentRenderer);
TableColumn colDestroyed = columnModel.getColumn(ThreadTableColumns.DESTROYED.ordinal());
colDestroyed.setCellRenderer(boldCurrentRenderer);
TableColumn colState = columnModel.getColumn(ThreadTableColumns.STATE.ordinal());
colState.setCellRenderer(boldCurrentRenderer);
TableColumn colComment = columnModel.getColumn(ThreadTableColumns.COMMENT.ordinal());
colComment.setCellRenderer(boldCurrentRenderer);
TableColumn colPlot = columnModel.getColumn(ThreadTableColumns.PLOT.ordinal());
colPlot.setCellRenderer(spanRenderer);
colPlot.setHeaderRenderer(headerRenderer);
headerRenderer.addSeekListener(seekListener = pos -> {
long snap = Math.round(pos);
if (snap < 0) {
snap = 0;
}
long max =
current.getTrace() == null ? 0 : current.getTrace().getTimeManager().getMaxSnap();
if (snap > max) {
snap = max;
}
traceManager.activateSnap(snap);
myActionContext = new DebuggerSnapActionContext(current.getTrace(), snap);
provider.legacyThreadsPanelContextChanged();
});
}
private void removeOldListeners() {
@@ -326,7 +284,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
current = coordinates;
doSetTrace(coordinates.getTrace());
doSetThread(coordinates.getThread());
doSetSnap(coordinates.getSnap());
}
private void doSetThread(TraceThread thread) {
@@ -339,11 +296,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
threadTableModel.fireTableDataChanged();
}
private void doSetSnap(long snap) {
headerRenderer.setCursorPosition(snap);
threadTable.getTableHeader().repaint();
}
protected void loadThreads() {
threadTableModel.clear();
Trace curTrace = current.getTrace();
@@ -352,16 +304,6 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
}
TraceThreadManager manager = curTrace.getThreadManager();
threadTableModel.addAllItems(manager.getAllThreads());
updateTimelineMax();
}
protected void updateTimelineMax() {
Trace trace = current.getTrace();
long max = orZero(trace == null ? null : trace.getTimeManager().getMaxSnap());
Lifespan fullRange = Lifespan.span(0, max + 1);
spanRenderer.setFullRange(fullRange);
headerRenderer.setFullRange(fullRange);
threadTable.getTableHeader().repaint();
}
private void threadRowSelected(ListSelectionEvent e) {

Some files were not shown because too many files have changed in this diff Show More