mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
GP-1447: Added 'View all Memory' override toggle to Debugger.
This commit is contained in:
parent
59402a2951
commit
8b2af5241a
30 changed files with 674 additions and 229 deletions
|
@ -65,5 +65,14 @@
|
|||
<P>This action is available when the dynamic listing's cursor is at a valid location. It
|
||||
selects the region containing that cursor. If the dynamic listing has a selection, it selects
|
||||
all regions intersecting that selection.</P>
|
||||
|
||||
<H3><A name="force_full_view"></A>Force Full View</H3>
|
||||
|
||||
<P>This action is available when a trace is active. It forces all physical address spaces into
|
||||
the view. Ordinarily, only those addresses contained in a region at the active snap are
|
||||
presented in the listing and memory windows. When this toggle is on, regions are ignored.
|
||||
Instead, all physical addresses are presented. (Here "physical" includes all memory spaces
|
||||
except <CODE>OTHER</CODE>.) This toggle applies only to the current trace for the duration it
|
||||
is open.</P>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
@ -1749,6 +1749,22 @@ public interface DebuggerResources {
|
|||
}
|
||||
}
|
||||
|
||||
interface ForceFullViewAction {
|
||||
String NAME = "Force Full View";
|
||||
String DESCRIPTION = "Ignore regions and fiew full address spaces";
|
||||
String GROUP = GROUP_GENERAL;
|
||||
String HELP_ANCHOR = "force_full_view";
|
||||
|
||||
static ToggleActionBuilder builder(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ToggleActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.menuGroup(GROUP_GENERAL)
|
||||
.menuPath(NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AbstractDebuggerConnectionsNode extends GTreeNode {
|
||||
@Override
|
||||
public String getName() {
|
||||
|
|
|
@ -46,8 +46,14 @@ public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent
|
|||
List<ColoredFieldSelection> selections) {
|
||||
Color selectionColor = paintContext.getSelectionColor();
|
||||
Color highlightColor = paintContext.getHighlightColor();
|
||||
selections.add(new ColoredFieldSelection(getSelection(), selectionColor));
|
||||
selections.add(new ColoredFieldSelection(getHighlight(), highlightColor));
|
||||
FieldSelection selection = getSelection();
|
||||
if (!selection.isEmpty()) {
|
||||
selections.add(new ColoredFieldSelection(selection, selectionColor));
|
||||
}
|
||||
FieldSelection highlight = getHighlight();
|
||||
if (!highlight.isEmpty()) {
|
||||
selections.add(new ColoredFieldSelection(highlight, highlightColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,8 +35,7 @@ import docking.widgets.table.CustomToStringCellRenderer;
|
|||
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
|
||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.SelectRowsAction;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||
import ghidra.app.plugin.core.debug.utils.DebouncedRowWrappedEnumeratedColumnTableModel;
|
||||
import ghidra.app.services.DebuggerListingService;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
|
@ -233,6 +232,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
|||
|
||||
SelectAddressesAction actionSelectAddresses;
|
||||
DockingAction actionSelectRows;
|
||||
ToggleDockingAction actionForceFullView;
|
||||
|
||||
public DebuggerRegionsProvider(DebuggerRegionsPlugin plugin) {
|
||||
super(plugin.getTool(), DebuggerResources.TITLE_PROVIDER_REGIONS, plugin.getName(),
|
||||
|
@ -341,6 +341,11 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
|||
.enabledWhen(ctx -> currentTrace != null)
|
||||
.onAction(this::activatedSelectCurrent)
|
||||
.buildAndInstallLocal(this);
|
||||
|
||||
actionForceFullView = ForceFullViewAction.builder(plugin)
|
||||
.enabledWhen(ctx -> currentTrace != null)
|
||||
.onAction(this::activatedForceFullView)
|
||||
.buildAndInstallLocal(this);
|
||||
}
|
||||
|
||||
private void activatedSelectCurrent(ActionContext ignored) {
|
||||
|
@ -371,6 +376,15 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private void activatedForceFullView(ActionContext ignored) {
|
||||
if (currentTrace == null) {
|
||||
return;
|
||||
}
|
||||
currentTrace.getProgramView()
|
||||
.getMemory()
|
||||
.setForceFullView(actionForceFullView.isSelected());
|
||||
}
|
||||
|
||||
public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
|
||||
DebuggerResources.setSelectedRows(sel, regionTableModel::getRow, regionTable,
|
||||
regionTableModel, regionFilterPanel);
|
||||
|
@ -396,6 +410,16 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
|||
contextChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextChanged() {
|
||||
super.contextChanged();
|
||||
if (currentTrace != null) {
|
||||
actionForceFullView.setSelected(currentTrace.getProgramView()
|
||||
.getMemory()
|
||||
.isForceFullView());
|
||||
}
|
||||
}
|
||||
|
||||
private void removeOldListeners() {
|
||||
if (currentTrace == null) {
|
||||
return;
|
||||
|
|
|
@ -716,30 +716,38 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
}
|
||||
|
||||
public void updateViewsAddBlock(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryAddBlock(region));
|
||||
public void updateViewsAddRegionBlock(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryAddRegionBlock(region));
|
||||
}
|
||||
|
||||
public void updateViewsChangeBlockName(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryChangeBlockName(region));
|
||||
public void updateViewsChangeRegionBlockName(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryChangeRegionBlockName(region));
|
||||
}
|
||||
|
||||
public void updateViewsChangeBlockFlags(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryChangeBlockFlags(region));
|
||||
public void updateViewsChangeRegionBlockFlags(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryChangeRegionBlockFlags(region));
|
||||
}
|
||||
|
||||
public void updateViewsChangeBlockRange(DBTraceMemoryRegion region,
|
||||
public void updateViewsChangeRegionBlockRange(DBTraceMemoryRegion region,
|
||||
AddressRange oldRange, AddressRange newRange) {
|
||||
allViews(v -> v.updateMemoryChangeBlockRange(region, oldRange, newRange));
|
||||
allViews(v -> v.updateMemoryChangeRegionBlockRange(region, oldRange, newRange));
|
||||
}
|
||||
|
||||
public void updateViewsChangeBlockLifespan(DBTraceMemoryRegion region,
|
||||
public void updateViewsChangeRegionBlockLifespan(DBTraceMemoryRegion region,
|
||||
Range<Long> oldLifespan, Range<Long> newLifespan) {
|
||||
allViews(v -> v.updateMemoryChangeBlockLifespan(region, oldLifespan, newLifespan));
|
||||
allViews(v -> v.updateMemoryChangeRegionBlockLifespan(region, oldLifespan, newLifespan));
|
||||
}
|
||||
|
||||
public void updateViewsDeleteBlock(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryDeleteBlock(region));
|
||||
public void updateViewsDeleteRegionBlock(DBTraceMemoryRegion region) {
|
||||
allViews(v -> v.updateMemoryDeleteRegionBlock(region));
|
||||
}
|
||||
|
||||
public void updateViewsAddSpaceBlock(AddressSpace space) {
|
||||
allViews(v -> v.updateMemoryAddSpaceBlock(space));
|
||||
}
|
||||
|
||||
public void updateViewsDeleteSpaceBlock(AddressSpace space) {
|
||||
allViews(v -> v.updateMemoryDeleteSpaceBlock(space));
|
||||
}
|
||||
|
||||
public void updateViewsRefreshBlocks() {
|
||||
|
|
|
@ -255,6 +255,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
|||
// Only if it succeeds do we store the record
|
||||
DBTraceOverlaySpaceEntry ent = overlayStore.create();
|
||||
ent.set(space.getName(), base.getName());
|
||||
trace.updateViewsAddSpaceBlock(space);
|
||||
return space;
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +269,10 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
|||
}
|
||||
overlayStore.delete(exists);
|
||||
TraceAddressFactory factory = trace.getInternalAddressFactory();
|
||||
AddressSpace space = factory.getAddressSpace(name);
|
||||
assert space != null;
|
||||
factory.removeOverlaySpace(name);
|
||||
trace.updateViewsDeleteSpaceBlock(space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public class DBTraceMemoryRegion
|
|||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
this.name = name;
|
||||
update(NAME_COLUMN);
|
||||
space.trace.updateViewsChangeBlockName(this);
|
||||
space.trace.updateViewsChangeRegionBlockName(this);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.CHANGED, space, this));
|
||||
|
@ -175,7 +175,7 @@ public class DBTraceMemoryRegion
|
|||
checkPathConflicts(newLifespan, path);
|
||||
Range<Long> oldLifespan = getLifespan();
|
||||
doSetLifespan(newLifespan);
|
||||
space.trace.updateViewsChangeBlockLifespan(this, oldLifespan, newLifespan);
|
||||
space.trace.updateViewsChangeRegionBlockLifespan(this, oldLifespan, newLifespan);
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.LIFESPAN_CHANGED,
|
||||
space, this, oldLifespan, newLifespan));
|
||||
|
@ -218,7 +218,7 @@ public class DBTraceMemoryRegion
|
|||
oldRange = range;
|
||||
checkOverlapConflicts(lifespan, newRange);
|
||||
doSetRange(newRange);
|
||||
space.trace.updateViewsChangeBlockRange(this, oldRange, newRange);
|
||||
space.trace.updateViewsChangeRegionBlockRange(this, oldRange, newRange);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.CHANGED, space, this));
|
||||
|
@ -278,7 +278,7 @@ public class DBTraceMemoryRegion
|
|||
this.flags.add(f);
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
space.trace.updateViewsChangeBlockFlags(this);
|
||||
space.trace.updateViewsChangeRegionBlockFlags(this);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.CHANGED, space, this));
|
||||
|
@ -293,7 +293,7 @@ public class DBTraceMemoryRegion
|
|||
this.flags.add(f);
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
space.trace.updateViewsChangeBlockFlags(this);
|
||||
space.trace.updateViewsChangeRegionBlockFlags(this);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.CHANGED, space, this));
|
||||
|
@ -308,7 +308,7 @@ public class DBTraceMemoryRegion
|
|||
this.flags.remove(f);
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
space.trace.updateViewsChangeBlockFlags(this);
|
||||
space.trace.updateViewsChangeRegionBlockFlags(this);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.CHANGED, space, this));
|
||||
|
|
|
@ -161,7 +161,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
|||
DBTraceMemoryRegion region =
|
||||
regionMapSpace.put(new ImmutableTraceAddressSnapRange(range, lifespan), null);
|
||||
region.set(path, path, flags);
|
||||
trace.updateViewsAddBlock(region);
|
||||
trace.updateViewsAddRegionBlock(region);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.ADDED, this, region));
|
||||
return region;
|
||||
|
@ -244,7 +244,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
|||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
regionMapSpace.deleteData(region);
|
||||
regionCache.remove(region);
|
||||
trace.updateViewsDeleteBlock(region);
|
||||
trace.updateViewsDeleteRegionBlock(region);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceMemoryRegionChangeType.DELETED, this, region));
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
|
|||
DBTraceMemorySpace mem = trace.getMemoryManager().get(this, false);
|
||||
if (mem == null) {
|
||||
// TODO: 0-fill instead? Will need to check memory space bounds.
|
||||
return 0;
|
||||
}
|
||||
return mem.getViewBytes(program.snap, address.add(addressOffset), buffer);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.cache.RemovalNotification;
|
||||
|
||||
|
@ -42,6 +43,7 @@ public abstract class AbstractDBTraceProgramViewMemory
|
|||
protected final DBTraceMemoryManager memoryManager;
|
||||
|
||||
protected AddressSetView addressSet;
|
||||
protected boolean forceFullView = false;
|
||||
protected long snap;
|
||||
|
||||
public AbstractDBTraceProgramViewMemory(DBTraceProgramView program) {
|
||||
|
@ -50,16 +52,57 @@ public abstract class AbstractDBTraceProgramViewMemory
|
|||
setSnap(program.snap);
|
||||
}
|
||||
|
||||
protected void blockRemoved(
|
||||
RemovalNotification<DBTraceMemoryRegion, DBTraceProgramViewMemoryBlock> rn) {
|
||||
protected void regionBlockRemoved(
|
||||
RemovalNotification<DBTraceMemoryRegion, DBTraceProgramViewMemoryRegionBlock> rn) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
protected void spaceBlockRemoved(
|
||||
RemovalNotification<AddressSpace, DBTraceProgramViewMemorySpaceBlock> rn) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
protected abstract void recomputeAddressSet();
|
||||
|
||||
protected void forPhysicalSpaces(Consumer<AddressSpace> consumer) {
|
||||
for (AddressSpace space : program.getAddressFactory().getAddressSpaces()) {
|
||||
// NB. Overlay's isMemory depends on its base space
|
||||
// TODO: Allow other?
|
||||
// For some reason "other" is omitted from factory.getAddressSet
|
||||
if (space.isMemorySpace() && space.getType() != AddressSpace.TYPE_OTHER) {
|
||||
consumer.accept(space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void computeFullAdddressSet() {
|
||||
AddressSet temp = new AddressSet();
|
||||
forPhysicalSpaces(space -> temp.add(space.getMinAddress(), space.getMaxAddress()));
|
||||
addressSet = temp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceFullView(boolean forceFullView) {
|
||||
this.forceFullView = forceFullView;
|
||||
if (forceFullView) {
|
||||
computeFullAdddressSet();
|
||||
}
|
||||
else {
|
||||
recomputeAddressSet();
|
||||
}
|
||||
program.fireObjectRestored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceFullView() {
|
||||
return forceFullView;
|
||||
}
|
||||
|
||||
void setSnap(long snap) {
|
||||
this.snap = snap;
|
||||
recomputeAddressSet();
|
||||
if (!forceFullView) {
|
||||
recomputeAddressSet();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -463,17 +506,23 @@ public abstract class AbstractDBTraceProgramViewMemory
|
|||
}
|
||||
|
||||
protected synchronized void addRange(AddressRange range) {
|
||||
addressSet = addressSet.union(new AddressSet(range));
|
||||
if (!forceFullView) {
|
||||
addressSet = addressSet.union(new AddressSet(range));
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void removeRange(AddressRange range) {
|
||||
addressSet = addressSet.subtract(new AddressSet(range));
|
||||
if (!forceFullView) {
|
||||
addressSet = addressSet.subtract(new AddressSet(range));
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void changeRange(AddressRange remove, AddressRange add) {
|
||||
AddressSet temp = new AddressSet(addressSet);
|
||||
temp.delete(remove);
|
||||
temp.add(add);
|
||||
addressSet = temp;
|
||||
if (!forceFullView) {
|
||||
AddressSet temp = new AddressSet(addressSet);
|
||||
temp.delete(remove);
|
||||
temp.add(add);
|
||||
addressSet = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,42 +16,39 @@
|
|||
package ghidra.trace.database.program;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.mem.ByteMappingScheme;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegion;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
|
||||
import ghidra.util.MathUtilities;
|
||||
|
||||
// TODO: Proper locking all over here
|
||||
public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
||||
public abstract class AbstractDBTraceProgramViewMemoryBlock implements MemoryBlock {
|
||||
|
||||
private class DBTraceProgramViewMemoryBlockSourceInfo implements MemoryBlockSourceInfo {
|
||||
private class MyMemoryBlockSourceInfo implements MemoryBlockSourceInfo {
|
||||
@Override
|
||||
public long getLength() {
|
||||
return region.getLength();
|
||||
return getMemoryBlock().getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() {
|
||||
return region.getMinAddress();
|
||||
return getMemoryBlock().getStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
return region.getMaxAddress();
|
||||
return getMemoryBlock().getEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Trace region: " + region;
|
||||
return getInfoDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,12 +78,12 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
|
||||
@Override
|
||||
public MemoryBlock getMemoryBlock() {
|
||||
return DBTraceProgramViewMemoryBlock.this;
|
||||
return AbstractDBTraceProgramViewMemoryBlock.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Address address) {
|
||||
return region.getRange().contains(address);
|
||||
return getMemoryBlock().contains(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,15 +92,26 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
}
|
||||
}
|
||||
|
||||
private final DBTraceProgramView program;
|
||||
private final DBTraceMemoryRegion region;
|
||||
|
||||
protected final DBTraceProgramView program;
|
||||
private final List<MemoryBlockSourceInfo> info =
|
||||
Collections.singletonList(new DBTraceProgramViewMemoryBlockSourceInfo());
|
||||
Collections.singletonList(new MyMemoryBlockSourceInfo());
|
||||
|
||||
public DBTraceProgramViewMemoryBlock(DBTraceProgramView program, DBTraceMemoryRegion region) {
|
||||
protected AbstractDBTraceProgramViewMemoryBlock(DBTraceProgramView program) {
|
||||
this.program = program;
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
protected abstract String getInfoDescription();
|
||||
|
||||
protected AddressSpace getAddressSpace() {
|
||||
return getStart().getAddressSpace();
|
||||
}
|
||||
|
||||
protected DBTraceMemorySpace getMemorySpace() {
|
||||
return program.trace.getMemoryManager().getMemorySpace(getAddressSpace(), false);
|
||||
}
|
||||
|
||||
protected AddressRange getAddressRange() {
|
||||
return new AddressRangeImpl(getStart(), getEnd());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,112 +119,40 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
return this.getStart().compareTo(that.getStart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermissions(boolean read, boolean write, boolean execute) {
|
||||
region.setRead(read);
|
||||
region.setWrite(write);
|
||||
region.setExecute(execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPermissions() {
|
||||
int bits = 0;
|
||||
for (TraceMemoryFlag flag : region.getFlags()) {
|
||||
bits |= flag.getBits();
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getData() {
|
||||
AddressRange range = region.getRange();
|
||||
DBTraceMemorySpace space =
|
||||
program.trace.getMemoryManager().getMemorySpace(range.getAddressSpace(), false);
|
||||
if (space == null) {
|
||||
return null;
|
||||
}
|
||||
return new TraceMemorySpaceInputStream(program, space, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Address addr) {
|
||||
return region.getRange().contains(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getStart() {
|
||||
return region.getRange().getMinAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getEnd() {
|
||||
return region.getRange().getMaxAddress();
|
||||
return getAddressRange().contains(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return region.getRange().getLength();
|
||||
return getEnd().subtract(getStart()) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return region.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws LockException {
|
||||
region.setName(name);
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
return getEnd().getOffsetAsBigInteger()
|
||||
.subtract(getStart().getOffsetAsBigInteger())
|
||||
.add(BigInteger.ONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return region.isRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean r) {
|
||||
region.setRead(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrite() {
|
||||
return region.isWrite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWrite(boolean w) {
|
||||
region.setWrite(w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecute() {
|
||||
return region.isExecute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecute(boolean e) {
|
||||
region.setExecute(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVolatile() {
|
||||
return region.isVolatile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolatile(boolean v) {
|
||||
region.setVolatile(v);
|
||||
public InputStream getData() {
|
||||
DBTraceMemorySpace ms = getMemorySpace();
|
||||
if (ms == null) {
|
||||
return null;
|
||||
}
|
||||
return new TraceMemorySpaceInputStream(program, ms, getAddressRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -231,7 +167,7 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
|
||||
@Override
|
||||
public byte getByte(Address addr) throws MemoryAccessException {
|
||||
AddressRange range = region.getRange();
|
||||
AddressRange range = getAddressRange();
|
||||
if (!range.contains(addr)) {
|
||||
throw new MemoryAccessException();
|
||||
}
|
||||
|
@ -254,7 +190,7 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
|
||||
@Override
|
||||
public int getBytes(Address addr, byte[] b, int off, int len) throws MemoryAccessException {
|
||||
AddressRange range = region.getRange();
|
||||
AddressRange range = getAddressRange();
|
||||
if (!range.contains(addr)) {
|
||||
throw new MemoryAccessException();
|
||||
}
|
||||
|
@ -263,7 +199,7 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
if (space == null) {
|
||||
throw new MemoryAccessException("Space does not exist");
|
||||
}
|
||||
len = (int) Math.min(len, range.getMaxAddress().subtract(addr) + 1);
|
||||
len = MathUtilities.unsignedMin(len, range.getMaxAddress().subtract(addr) + 1);
|
||||
return space.getViewBytes(program.snap, addr, ByteBuffer.wrap(b, off, len));
|
||||
}
|
||||
|
||||
|
@ -281,7 +217,7 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
|
||||
@Override
|
||||
public int putBytes(Address addr, byte[] b, int off, int len) throws MemoryAccessException {
|
||||
AddressRange range = region.getRange();
|
||||
AddressRange range = getAddressRange();
|
||||
if (!range.contains(addr)) {
|
||||
throw new MemoryAccessException();
|
||||
}
|
||||
|
@ -308,7 +244,8 @@ public class DBTraceProgramViewMemoryBlock implements MemoryBlock {
|
|||
|
||||
@Override
|
||||
public boolean isOverlay() {
|
||||
return false;
|
||||
// TODO: What effect does this have? Does it makes sense for trace "overlays"?
|
||||
return getAddressSpace().isOverlaySpace();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -943,6 +943,13 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires object-restored event on this view and all associated register views.
|
||||
*/
|
||||
protected void fireObjectRestored() {
|
||||
fireEventAllViews(new DomainObjectChangeRecord(DomainObject.DO_OBJECT_RESTORED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("<%s on %s at snap=%d>", getClass().getSimpleName(), trace, snap);
|
||||
|
@ -1555,52 +1562,63 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
trace.removeTransactionListener(listener);
|
||||
}
|
||||
|
||||
public void updateMemoryAddBlock(DBTraceMemoryRegion region) {
|
||||
public void updateMemoryAddRegionBlock(DBTraceMemoryRegion region) {
|
||||
if (!isRegionVisible(region)) {
|
||||
return;
|
||||
}
|
||||
memory.updateAddBlock(region);
|
||||
memory.updateAddRegionBlock(region);
|
||||
}
|
||||
|
||||
public void updateMemoryChangeBlockName(DBTraceMemoryRegion region) {
|
||||
public void updateMemoryChangeRegionBlockName(DBTraceMemoryRegion region) {
|
||||
if (!isRegionVisible(region)) {
|
||||
return;
|
||||
}
|
||||
memory.updateChangeBlockName(region);
|
||||
memory.updateChangeRegionBlockName(region);
|
||||
}
|
||||
|
||||
public void updateMemoryChangeBlockFlags(DBTraceMemoryRegion region) {
|
||||
public void updateMemoryChangeRegionBlockFlags(DBTraceMemoryRegion region) {
|
||||
if (!isRegionVisible(region)) {
|
||||
return;
|
||||
}
|
||||
memory.updateChangeBlockFlags(region);
|
||||
memory.updateChangeRegionBlockFlags(region);
|
||||
}
|
||||
|
||||
public void updateMemoryChangeBlockRange(DBTraceMemoryRegion region, AddressRange oldRange,
|
||||
public void updateMemoryChangeRegionBlockRange(DBTraceMemoryRegion region,
|
||||
AddressRange oldRange,
|
||||
AddressRange newRange) {
|
||||
if (!isRegionVisible(region)) {
|
||||
return;
|
||||
}
|
||||
memory.updateChangeBlockRange(region, oldRange, newRange);
|
||||
memory.updateChangeRegionBlockRange(region, oldRange, newRange);
|
||||
}
|
||||
|
||||
public void updateMemoryChangeBlockLifespan(DBTraceMemoryRegion region,
|
||||
public void updateMemoryChangeRegionBlockLifespan(DBTraceMemoryRegion region,
|
||||
Range<Long> oldLifespan, Range<Long> newLifespan) {
|
||||
boolean inOld = isRegionVisible(region, oldLifespan);
|
||||
boolean inNew = isRegionVisible(region, newLifespan);
|
||||
if (inOld && !inNew) {
|
||||
memory.updateDeleteBlock(region);
|
||||
memory.updateDeleteRegionBlock(region);
|
||||
}
|
||||
if (!inOld && inNew) {
|
||||
memory.updateAddBlock(region);
|
||||
memory.updateAddRegionBlock(region);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMemoryDeleteBlock(DBTraceMemoryRegion region) {
|
||||
public void updateMemoryDeleteRegionBlock(DBTraceMemoryRegion region) {
|
||||
if (!isRegionVisible(region)) {
|
||||
return;
|
||||
}
|
||||
memory.updateAddBlock(region);
|
||||
memory.updateAddRegionBlock(region);
|
||||
}
|
||||
|
||||
public void updateMemoryAddSpaceBlock(AddressSpace space) {
|
||||
// Spaces not not time-bound. No visibility check.
|
||||
memory.updateAddSpaceBlock(space);
|
||||
}
|
||||
|
||||
public void updateMemoryDeleteSpaceBlock(AddressSpace space) {
|
||||
// Spaces not not time-bound. No visibility check.
|
||||
memory.updateDeleteSpaceBlock(space);
|
||||
}
|
||||
|
||||
public void updateMemoryRefreshBlocks() {
|
||||
|
|
|
@ -27,8 +27,19 @@ import ghidra.trace.database.memory.DBTraceMemoryRegion;
|
|||
|
||||
public class DBTraceProgramViewMemory extends AbstractDBTraceProgramViewMemory {
|
||||
|
||||
private final Map<DBTraceMemoryRegion, DBTraceProgramViewMemoryBlock> blocks =
|
||||
CacheBuilder.newBuilder().removalListener(this::blockRemoved).weakValues().build().asMap();
|
||||
// NB. Keep both per-region and force-full (per-space) block sets ready
|
||||
private final Map<DBTraceMemoryRegion, DBTraceProgramViewMemoryRegionBlock> regionBlocks =
|
||||
CacheBuilder.newBuilder()
|
||||
.removalListener(this::regionBlockRemoved)
|
||||
.weakValues()
|
||||
.build()
|
||||
.asMap();
|
||||
private final Map<AddressSpace, DBTraceProgramViewMemorySpaceBlock> spaceBlocks =
|
||||
CacheBuilder.newBuilder()
|
||||
.removalListener(this::spaceBlockRemoved)
|
||||
.weakValues()
|
||||
.build()
|
||||
.asMap();
|
||||
|
||||
public DBTraceProgramViewMemory(DBTraceProgramView program) {
|
||||
super(program);
|
||||
|
@ -64,58 +75,84 @@ public class DBTraceProgramViewMemory extends AbstractDBTraceProgramViewMemory {
|
|||
addressSet = temp;
|
||||
}
|
||||
|
||||
protected MemoryBlock getBlock(DBTraceMemoryRegion region) {
|
||||
return blocks.computeIfAbsent(region,
|
||||
r -> new DBTraceProgramViewMemoryBlock(program, region));
|
||||
protected MemoryBlock getRegionBlock(DBTraceMemoryRegion region) {
|
||||
return regionBlocks.computeIfAbsent(region,
|
||||
r -> new DBTraceProgramViewMemoryRegionBlock(program, region));
|
||||
}
|
||||
|
||||
protected MemoryBlock getSpaceBlock(AddressSpace space) {
|
||||
return spaceBlocks.computeIfAbsent(space,
|
||||
s -> new DBTraceProgramViewMemorySpaceBlock(program, space));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock getBlock(Address addr) {
|
||||
if (forceFullView) {
|
||||
return getSpaceBlock(addr.getAddressSpace());
|
||||
}
|
||||
DBTraceMemoryRegion region = getTopRegion(s -> memoryManager.getRegionContaining(s, addr));
|
||||
return region == null ? null : getBlock(region);
|
||||
return region == null ? null : getRegionBlock(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock getBlock(String blockName) {
|
||||
if (forceFullView) {
|
||||
AddressSpace space = program.getAddressFactory().getAddressSpace(blockName);
|
||||
return space == null ? null : getSpaceBlock(space);
|
||||
}
|
||||
DBTraceMemoryRegion region =
|
||||
getTopRegion(s -> memoryManager.getLiveRegionByPath(s, blockName));
|
||||
return region == null ? null : getBlock(region);
|
||||
return region == null ? null : getRegionBlock(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock[] getBlocks() {
|
||||
List<MemoryBlock> result = new ArrayList<>();
|
||||
forVisibleRegions(reg -> result.add(getBlock(reg)));
|
||||
if (forceFullView) {
|
||||
forPhysicalSpaces(space -> result.add(getSpaceBlock(space)));
|
||||
}
|
||||
else {
|
||||
forVisibleRegions(reg -> result.add(getRegionBlock(reg)));
|
||||
}
|
||||
Collections.sort(result, Comparator.comparing(b -> b.getStart()));
|
||||
return result.toArray(new MemoryBlock[result.size()]);
|
||||
}
|
||||
|
||||
public void updateAddBlock(DBTraceMemoryRegion region) {
|
||||
public void updateAddRegionBlock(DBTraceMemoryRegion region) {
|
||||
// TODO: add block to cache?
|
||||
addRange(region.getRange());
|
||||
}
|
||||
|
||||
public void updateChangeBlockName(DBTraceMemoryRegion region) {
|
||||
public void updateChangeRegionBlockName(DBTraceMemoryRegion region) {
|
||||
// Nothing. Block name is taken from region, uncached
|
||||
}
|
||||
|
||||
public void updateChangeBlockFlags(DBTraceMemoryRegion region) {
|
||||
public void updateChangeRegionBlockFlags(DBTraceMemoryRegion region) {
|
||||
// Nothing. Block flags are taken from region, uncached
|
||||
}
|
||||
|
||||
public void updateChangeBlockRange(DBTraceMemoryRegion region, AddressRange oldRange,
|
||||
public void updateChangeRegionBlockRange(DBTraceMemoryRegion region, AddressRange oldRange,
|
||||
AddressRange newRange) {
|
||||
// TODO: update cached block? Nothing to update.
|
||||
changeRange(oldRange, newRange);
|
||||
}
|
||||
|
||||
public void updateDeleteBlock(DBTraceMemoryRegion region) {
|
||||
blocks.remove(region);
|
||||
public void updateDeleteRegionBlock(DBTraceMemoryRegion region) {
|
||||
regionBlocks.remove(region);
|
||||
removeRange(region.getRange());
|
||||
}
|
||||
|
||||
public void updateAddSpaceBlock(AddressSpace space) {
|
||||
// Nothing. Cache will construct it upon request, lazily
|
||||
}
|
||||
|
||||
public void updateDeleteSpaceBlock(AddressSpace space) {
|
||||
spaceBlocks.remove(space);
|
||||
}
|
||||
|
||||
public void updateRefreshBlocks() {
|
||||
blocks.clear();
|
||||
regionBlocks.clear();
|
||||
spaceBlocks.clear();
|
||||
recomputeAddressSet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.trace.database.program;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegion;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
|
||||
|
||||
// TODO: Proper locking all over here
|
||||
public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramViewMemoryBlock {
|
||||
|
||||
private final DBTraceMemoryRegion region;
|
||||
|
||||
public DBTraceProgramViewMemoryRegionBlock(DBTraceProgramView program,
|
||||
DBTraceMemoryRegion region) {
|
||||
super(program);
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoDescription() {
|
||||
return "Trace region: " + region;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AddressSpace getAddressSpace() {
|
||||
return region.getRange().getAddressSpace();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AddressRange getAddressRange() {
|
||||
return region.getRange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermissions(boolean read, boolean write, boolean execute) {
|
||||
region.setRead(read);
|
||||
region.setWrite(write);
|
||||
region.setExecute(execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPermissions() {
|
||||
int bits = 0;
|
||||
for (TraceMemoryFlag flag : region.getFlags()) {
|
||||
bits |= flag.getBits();
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getData() {
|
||||
AddressRange range = region.getRange();
|
||||
DBTraceMemorySpace space =
|
||||
program.trace.getMemoryManager().getMemorySpace(range.getAddressSpace(), false);
|
||||
if (space == null) {
|
||||
return null;
|
||||
}
|
||||
return new TraceMemorySpaceInputStream(program, space, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getStart() {
|
||||
return region.getRange().getMinAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getEnd() {
|
||||
return region.getRange().getMaxAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return region.getRange().getLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
return region.getRange().getBigLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return region.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws LockException {
|
||||
region.setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return region.isRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean r) {
|
||||
region.setRead(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrite() {
|
||||
return region.isWrite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWrite(boolean w) {
|
||||
region.setWrite(w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecute() {
|
||||
return region.isExecute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecute(boolean e) {
|
||||
region.setExecute(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVolatile() {
|
||||
return region.isVolatile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolatile(boolean v) {
|
||||
region.setVolatile(v);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.trace.database.program;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.mem.ByteMappingScheme;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
|
||||
|
||||
public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramViewMemoryBlock {
|
||||
|
||||
private final AddressSpace space;
|
||||
|
||||
public DBTraceProgramViewMemorySpaceBlock(DBTraceProgramView program, AddressSpace space) {
|
||||
super(program);
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoDescription() {
|
||||
return "Trace space: " + space;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AddressSpace getAddressSpace() {
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getStart() {
|
||||
return space.getMinAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getEnd() {
|
||||
return space.getMaxAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPermissions() {
|
||||
return MemoryBlock.READ | MemoryBlock.WRITE | MemoryBlock.EXECUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return space.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws IllegalArgumentException, LockException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRead() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRead(boolean r) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWrite(boolean w) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecute(boolean e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermissions(boolean read, boolean write, boolean execute) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVolatile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolatile(boolean v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return "Trace"; // TODO: What does this method actually do?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceName(String sourceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -33,6 +33,11 @@ public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramView
|
|||
space.getAddressSpace().getMaxAddress()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceFullView(boolean forceFullView) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recomputeAddressSet() {
|
||||
// AddressSet is always full space
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.trace.database.program;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -144,6 +145,11 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
|
|||
return range.getLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
return range.getBigLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REGS_BLOCK_NAME;
|
||||
|
|
|
@ -28,7 +28,6 @@ import ghidra.program.database.map.AddressMap;
|
|||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.reloc.RelocationTable;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -40,6 +39,7 @@ import ghidra.trace.database.thread.DBTraceThread;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.data.TraceBasedDataTypeManager;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.program.TraceProgramViewMemory;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceTimeViewport;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -113,7 +113,7 @@ public class DBTraceProgramViewRegisters implements TraceProgramView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Memory getMemory() {
|
||||
public TraceProgramViewMemory getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,6 @@ public class DBTraceVariableSnapProgramView extends DBTraceProgramView
|
|||
super(trace, snap, compilerSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires object-restored event on this view and all associated register views.
|
||||
*/
|
||||
protected void fireObjectRestored() {
|
||||
fireEventAllViews(new DomainObjectChangeRecord(DomainObject.DO_OBJECT_RESTORED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSnap(long newSnap) {
|
||||
if (this.snap == newSnap) {
|
||||
|
|
|
@ -24,6 +24,10 @@ import ghidra.trace.util.TraceTimeViewport;
|
|||
* View of a trace at a particular time, as a program
|
||||
*/
|
||||
public interface TraceProgramView extends Program {
|
||||
|
||||
@Override
|
||||
TraceProgramViewMemory getMemory();
|
||||
|
||||
/**
|
||||
* Get the trace this view presents
|
||||
*
|
||||
|
|
|
@ -20,4 +20,8 @@ import ghidra.program.model.mem.Memory;
|
|||
public interface TraceProgramViewMemory extends Memory, SnapSpecificTraceView {
|
||||
@Override
|
||||
TraceProgramView getProgram();
|
||||
|
||||
void setForceFullView(boolean forceFullView);
|
||||
|
||||
boolean isForceFullView();
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public class DBTraceProgramViewMemoryTest extends AbstractGhidraHeadlessIntegrat
|
|||
assertEquals(1, blocks.length);
|
||||
|
||||
MemoryBlock blk = blocks[0];
|
||||
assertSame(blk, vmem.getBlock(io));
|
||||
assertSame(blk, vmem.getRegionBlock(io));
|
||||
assertEquals(".io", blk.getName());
|
||||
assertEquals(b.addr(os, 0x1000), blk.getStart());
|
||||
assertEquals(b.addr(os, 0x1fff), blk.getEnd());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.app.plugin.core.checksums;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -60,6 +61,11 @@ class MyTestMemoryBlock implements MemoryBlock {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -467,17 +467,17 @@ public class ByteViewerComponent extends FieldPanel implements FieldMouseListene
|
|||
// adjust the end index/field because the selection does not
|
||||
// include the end
|
||||
int endFieldOffset = endLoc.getFieldNum();
|
||||
int endIndex = endLoc.getIndex().intValue();
|
||||
BigInteger endIndex = endLoc.getIndex();
|
||||
|
||||
if (endFieldOffset == fieldFactories.length - 1) {
|
||||
endFieldOffset = 0;
|
||||
++endIndex;
|
||||
endIndex = endIndex.add(BigInteger.ONE);
|
||||
}
|
||||
else {
|
||||
++endFieldOffset;
|
||||
}
|
||||
fsel.addRange(
|
||||
new FieldLocation(startLoc.getIndex().intValue(), startLoc.getFieldNum(), 0, 0),
|
||||
new FieldLocation(startLoc.getIndex(), startLoc.getFieldNum(), 0, 0),
|
||||
new FieldLocation(endIndex, endFieldOffset, 0, 0));
|
||||
}
|
||||
return fsel;
|
||||
|
|
|
@ -125,7 +125,7 @@ public class ByteViewerLayoutModel implements LayoutModel {
|
|||
if (index.compareTo(numIndexes) >= 0) {
|
||||
return null;
|
||||
}
|
||||
List<Field> fields = new ArrayList<Field>(8);
|
||||
List<Field> fields = new ArrayList<Field>(factorys.length);
|
||||
for (FieldFactory factory : factorys) {
|
||||
Field field = factory.getField(index);
|
||||
if (field != null) {
|
||||
|
|
|
@ -91,14 +91,7 @@ public class MemoryByteBlock implements ByteBlock {
|
|||
*/
|
||||
@Override
|
||||
public BigInteger getLength() {
|
||||
|
||||
long size = block.getSize();
|
||||
if (size < 0) {
|
||||
return BigInteger.valueOf(size + 0x8000000000000000L)
|
||||
.subtract(
|
||||
BigInteger.valueOf(0x8000000000000000L));
|
||||
}
|
||||
return BigInteger.valueOf(size);
|
||||
return block.getSizeAsBigInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.program.database.mem;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import db.DBBuffer;
|
||||
|
@ -26,6 +27,7 @@ import ghidra.program.database.map.AddressMap;
|
|||
import ghidra.program.database.map.AddressMapDB;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
public class MemoryBlockDB implements MemoryBlock {
|
||||
|
@ -52,6 +54,7 @@ public class MemoryBlockDB implements MemoryBlock {
|
|||
|
||||
/**
|
||||
* Returns the id for this memory block
|
||||
*
|
||||
* @return the id for this memory block
|
||||
*/
|
||||
long getID() {
|
||||
|
@ -81,6 +84,7 @@ public class MemoryBlockDB implements MemoryBlock {
|
|||
|
||||
/**
|
||||
* Add a block which is mapped onto this block
|
||||
*
|
||||
* @param mappedBlock mapped memory block
|
||||
*/
|
||||
void addMappedBlock(MemoryBlockDB mappedBlock) {
|
||||
|
@ -99,6 +103,7 @@ public class MemoryBlockDB implements MemoryBlock {
|
|||
|
||||
/**
|
||||
* Get collection of blocks which map onto this block.
|
||||
*
|
||||
* @return collection of blocks which map onto this block or null if none identified
|
||||
*/
|
||||
Collection<MemoryBlockDB> getMappedBlocks() {
|
||||
|
@ -144,6 +149,11 @@ public class MemoryBlockDB implements MemoryBlock {
|
|||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
return NumericUtilities.unsignedLongToBigInteger(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = record.getString(MemoryMapDBAdapter.NAME_COL);
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.program.model.mem;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
|
@ -30,8 +31,8 @@ import ghidra.util.NamingUtilities;
|
|||
public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
||||
|
||||
/**
|
||||
* A special EXTERNAL block may be created by certain program loaders (e.g., Elf) to
|
||||
* act as a stand-in for unknown external symbol locations.
|
||||
* A special EXTERNAL block may be created by certain program loaders (e.g., Elf) to act as a
|
||||
* stand-in for unknown external symbol locations.
|
||||
*/
|
||||
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL";
|
||||
|
||||
|
@ -42,19 +43,20 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
public static int EXECUTE = 0x1;
|
||||
|
||||
/**
|
||||
* Returns block permissions as a bit mask.
|
||||
* Permission bits defined as READ, WRITE, EXECUTE and VOLATILE
|
||||
* Returns block permissions as a bit mask. Permission bits defined as READ, WRITE, EXECUTE and
|
||||
* VOLATILE
|
||||
*/
|
||||
public int getPermissions();
|
||||
|
||||
/**
|
||||
* Get memory data in the form of an InputStream.
|
||||
* Null is returned for thos memory blocks which have no data.
|
||||
* Get memory data in the form of an InputStream. Null is returned for thos memory blocks which
|
||||
* have no data.
|
||||
*/
|
||||
public InputStream getData();
|
||||
|
||||
/**
|
||||
* Return whether addr is contained in this block.
|
||||
*
|
||||
* @param addr address
|
||||
*/
|
||||
public boolean contains(Address addr);
|
||||
|
@ -80,14 +82,22 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
*/
|
||||
public long getSize();
|
||||
|
||||
/**
|
||||
* Get the number of bytes in this block.
|
||||
*
|
||||
* @return the number of bytes in this block as a BigInteger
|
||||
*/
|
||||
public BigInteger getSizeAsBigInteger();
|
||||
|
||||
/**
|
||||
* Get the name of this block
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Set the name for this block (See {@link NamingUtilities#isValidName(String)} for
|
||||
* naming rules). Specified name must not conflict with an address space name.
|
||||
* Set the name for this block (See {@link NamingUtilities#isValidName(String)} for naming
|
||||
* rules). Specified name must not conflict with an address space name.
|
||||
*
|
||||
* @param name the new name for this block.
|
||||
* @throws IllegalArgumentException if invalid name specified
|
||||
* @throws LockException renaming an Overlay block without exclusive access
|
||||
|
@ -102,6 +112,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Set the comment associated with this block.
|
||||
*
|
||||
* @param comment the comment to associate with this block.
|
||||
*/
|
||||
public void setComment(String comment);
|
||||
|
@ -113,6 +124,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Sets the read property associated with this block.
|
||||
*
|
||||
* @param r the value to set the read property to.
|
||||
*/
|
||||
public void setRead(boolean r);
|
||||
|
@ -124,6 +136,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Sets the write property associated with this block.
|
||||
*
|
||||
* @param w the value to set the write property to.
|
||||
*/
|
||||
public void setWrite(boolean w);
|
||||
|
@ -135,12 +148,14 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Sets the execute property associated with this block.
|
||||
*
|
||||
* @param e the value to set the execute property to.
|
||||
*/
|
||||
public void setExecute(boolean e);
|
||||
|
||||
/**
|
||||
* Sets the read, write, execute permissions on this block
|
||||
*
|
||||
* @param read the read permission
|
||||
* @param write the write permission
|
||||
* @param execute the execute permission
|
||||
|
@ -148,13 +163,14 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
public void setPermissions(boolean read, boolean write, boolean execute);
|
||||
|
||||
/**
|
||||
* Returns the value of the volatile property associated with this block.
|
||||
* This attribute is generally associated with block of I/O regions of memory.
|
||||
* Returns the value of the volatile property associated with this block. This attribute is
|
||||
* generally associated with block of I/O regions of memory.
|
||||
*/
|
||||
public boolean isVolatile();
|
||||
|
||||
/**
|
||||
* Sets the volatile property associated with this block.
|
||||
*
|
||||
* @param v the value to set the volatile property to.
|
||||
*/
|
||||
public void setVolatile(boolean v);
|
||||
|
@ -168,48 +184,50 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Sets the name of the source file that provided the data.
|
||||
*
|
||||
* @param sourceName the name of the source file.
|
||||
*/
|
||||
public void setSourceName(String sourceName);
|
||||
|
||||
/**
|
||||
* Returns the byte at the given address in this block.
|
||||
*
|
||||
* @param addr the address.
|
||||
* @throws MemoryAccessException if any of the requested bytes are
|
||||
* uninitialized.
|
||||
* @throws MemoryAccessException if any of the requested bytes are uninitialized.
|
||||
* @throws IllegalArgumentException if the Address is not in this block.
|
||||
*/
|
||||
public byte getByte(Address addr) throws MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Tries to get b.length bytes from this block at the given address. May
|
||||
* return fewer bytes if the requested length is beyond the end of the block.
|
||||
* Tries to get b.length bytes from this block at the given address. May return fewer bytes if
|
||||
* the requested length is beyond the end of the block.
|
||||
*
|
||||
* @param addr the address from which to get the bytes.
|
||||
* @param b the byte array to populate.
|
||||
* @return the number of bytes actually populated.
|
||||
* @throws MemoryAccessException if any of the requested bytes are
|
||||
* uninitialized.
|
||||
* @throws MemoryAccessException if any of the requested bytes are uninitialized.
|
||||
* @throws IllegalArgumentException if the Address is not in this block.
|
||||
*/
|
||||
public int getBytes(Address addr, byte[] b) throws MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Tries to get len bytes from this block at the given address and put them
|
||||
* into the given byte array at the specified offet. May return
|
||||
* fewer bytes if the requested length is beyond the end of the block.
|
||||
* Tries to get len bytes from this block at the given address and put them into the given byte
|
||||
* array at the specified offet. May return fewer bytes if the requested length is beyond the
|
||||
* end of the block.
|
||||
*
|
||||
* @param addr the address from which to get the bytes.
|
||||
* @param b the byte array to populate.
|
||||
* @param off the offset into the byte array.
|
||||
* @param len the number of bytes to get.
|
||||
* @return the number of bytes actually populated.
|
||||
* @throws MemoryAccessException if any of the requested bytes are
|
||||
* uninitialized.
|
||||
* @throws MemoryAccessException if any of the requested bytes are uninitialized.
|
||||
* @throws IllegalArgumentException if the Address is not in this block.
|
||||
*/
|
||||
public int getBytes(Address addr, byte[] b, int off, int len) throws MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Puts the given byte at the given address in this block.
|
||||
*
|
||||
* @param addr the address.
|
||||
* @throws MemoryAccessException if the block is uninitialized
|
||||
* @throws IllegalArgumentException if the Address is not in this block.
|
||||
|
@ -217,9 +235,9 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
public void putByte(Address addr, byte b) throws MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Tries to put b.length bytes from the specified byte array to this block.
|
||||
* All the bytes may not be put if the requested length is beyond the end of
|
||||
* the block.
|
||||
* Tries to put b.length bytes from the specified byte array to this block. All the bytes may
|
||||
* not be put if the requested length is beyond the end of the block.
|
||||
*
|
||||
* @param addr the address of where to put the bytes.
|
||||
* @param b the byte array containing the bytes to write.
|
||||
* @return the number of bytes actually written.
|
||||
|
@ -229,9 +247,9 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
public int putBytes(Address addr, byte[] b) throws MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Tries to put len bytes from the specified byte array to this block. All
|
||||
* the bytes may not be written if the requested length is beyond the end of
|
||||
* the block.
|
||||
* Tries to put len bytes from the specified byte array to this block. All the bytes may not be
|
||||
* written if the requested length is beyond the end of the block.
|
||||
*
|
||||
* @param addr the address of where to put the bytes.
|
||||
* @param b the byte array containing the bytes to write.
|
||||
* @param off the offset into the byte array.
|
||||
|
@ -259,6 +277,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
|
||||
/**
|
||||
* Returns true if this is an overlay block (i.e., contained within overlay space).
|
||||
*
|
||||
* @return true if this is an overlay block
|
||||
*/
|
||||
public boolean isOverlay();
|
||||
|
@ -266,21 +285,24 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
|||
/**
|
||||
* Returns true if this memory block is a real loaded block (i.e. RAM) and not a special block
|
||||
* containing file header data such as debug sections.
|
||||
*
|
||||
* @return true if this is a loaded block and not a "special" block such as a file header.
|
||||
*/
|
||||
public boolean isLoaded();
|
||||
|
||||
/**
|
||||
* Returns a list of {@link MemoryBlockSourceInfo} objects for this block. A block may consist of
|
||||
* multiple sequences of bytes from different sources. Each such source of bytes is described
|
||||
* by its respective SourceInfo object. Blocks may have multiple sources after two or more
|
||||
* Returns a list of {@link MemoryBlockSourceInfo} objects for this block. A block may consist
|
||||
* of multiple sequences of bytes from different sources. Each such source of bytes is described
|
||||
* by its respective SourceInfo object. Blocks may have multiple sources after two or more
|
||||
* memory blocks have been joined together and the underlying byte sources can't be joined.
|
||||
*
|
||||
* @return a list of SourceInfo objects, one for each different source of bytes in this block.
|
||||
*/
|
||||
public List<MemoryBlockSourceInfo> getSourceInfos();
|
||||
|
||||
/**
|
||||
* Determine if the specified address is contained within the reserved EXTERNAL block.
|
||||
*
|
||||
* @param address address of interest
|
||||
* @param program
|
||||
* @return true if address is contained within the reserved EXTERNAL block, else false.
|
||||
|
|
|
@ -16,15 +16,16 @@
|
|||
package ghidra.program.model.mem;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
/**
|
||||
* MemoryBlockStub can be extended for use by tests. It throws an UnsupportedOperationException
|
||||
* for all methods in the MemoryBlock interface. Any method that is needed for your test can then
|
||||
* be overridden so it can provide its own test implementation and return value.
|
||||
* MemoryBlockStub can be extended for use by tests. It throws an UnsupportedOperationException for
|
||||
* all methods in the MemoryBlock interface. Any method that is needed for your test can then be
|
||||
* overridden so it can provide its own test implementation and return value.
|
||||
*/
|
||||
public class MemoryBlockStub implements MemoryBlock {
|
||||
Address start;
|
||||
|
@ -74,6 +75,11 @@ public class MemoryBlockStub implements MemoryBlock {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSizeAsBigInteger() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue