GP-2581: Allow dynamic listing and memory view to follow the adress of a watch.

This commit is contained in:
Dan 2022-10-03 13:35:52 -04:00
parent dc76aa811e
commit 958afa58cc
60 changed files with 1632 additions and 552 deletions

View file

@ -0,0 +1,114 @@
/* ###
* 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.pcode.exec.trace;
import java.util.HashMap;
import java.util.Map;
import javax.help.UnsupportedOperationException;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
import ghidra.program.model.mem.MemBuffer;
/**
* An auxilliary state piece that reports the (trace) address ranges
*
* <p>
* Except for unique spaces, sets are ignored, and gets simply echo back the range of addresses of
* the requested read. In unique spaces, the "addresses read" is treated as the value, so that
* values transiting unique space can correct have their source address ranges reported. Use this
* with {@link AddressesReadPcodeArithmetic} to compute the union of these ranges during Sleigh
* expression evaluation. The ranges are translated from the guest platform, if applicable, to the
* trace address. In the case of registers, the addresses are also translated to the appropriate
* overlay space, if applicable.
*/
public class AddressesReadTracePcodeExecutorStatePiece
extends AbstractLongOffsetPcodeExecutorStatePiece<byte[], AddressSetView, AddressSpace>
implements TracePcodeExecutorStatePiece<byte[], AddressSetView> {
protected final PcodeTraceDataAccess data;
private final Map<Long, AddressSetView> unique = new HashMap<>();
/**
* Construct the state piece
*
* @param data the trace data access shim
*/
public AddressesReadTracePcodeExecutorStatePiece(PcodeTraceDataAccess data) {
super(data.getLanguage(), BytesPcodeArithmetic.forLanguage(data.getLanguage()),
AddressesReadPcodeArithmetic.INSTANCE);
this.data = data;
}
@Override
public MemBuffer getConcreteBuffer(Address address, Purpose purpose) {
throw new ConcretionError("Cannot make 'addresses read' concrete buffers", purpose);
}
@Override
public PcodeTraceDataAccess getData() {
return data;
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
throw new UnsupportedOperationException();
}
@Override
protected AddressSpace getForSpace(AddressSpace space, boolean toWrite) {
return space;
}
@Override
protected void setInSpace(AddressSpace space, long offset, int size, AddressSetView val) {
if (!space.isUniqueSpace()) {
return;
}
// TODO: size is not considered
unique.put(offset, val);
}
@Override
protected AddressSetView getFromSpace(AddressSpace space, long offset, int size,
Reason reason) {
if (space.isUniqueSpace()) {
AddressSetView result = unique.get(offset);
if (result == null) {
return new AddressSet();
}
return result;
}
Address start = data.translate(space.getAddress(offset));
if (start == null) {
return new AddressSet();
}
try {
return new AddressSet(new AddressRangeImpl(start, size));
}
catch (AddressOverflowException e) {
throw new AssertionError(e);
}
}
@Override
public void clear() {
unique.clear();
}
}

View file

@ -67,7 +67,7 @@ public class DirectBytesTracePcodeExecutorStatePiece
*
* @param data the trace-data access shim
*/
protected DirectBytesTracePcodeExecutorStatePiece(PcodeTraceDataAccess data) {
public DirectBytesTracePcodeExecutorStatePiece(PcodeTraceDataAccess data) {
this(BytesPcodeArithmetic.forLanguage(data.getLanguage()), data);
}
@ -138,4 +138,9 @@ public class DirectBytesTracePcodeExecutorStatePiece
public void writeDown(PcodeTraceDataAccess into) {
// Writes directly, so just ignore
}
@Override
public void clear() {
unique.clear();
}
}

View file

@ -120,4 +120,9 @@ public class TraceMemoryStatePcodeExecutorStatePiece extends
public MemBuffer getConcreteBuffer(Address address, Purpose purpose) {
throw new ConcretionError("Cannot make TraceMemoryState into a concrete buffer", purpose);
}
@Override
public void clear() {
unique.clear();
}
}

View file

@ -51,6 +51,11 @@ public abstract class AbstractPcodeTraceDataAccess implements InternalPcodeTrace
this.mm = platform.getTrace().getMemoryManager();
}
@Override
public TraceTimeViewport getViewport() {
return viewport;
}
@Override
public Language getLanguage() {
return platform.getLanguage();
@ -186,6 +191,15 @@ public abstract class AbstractPcodeTraceDataAccess implements InternalPcodeTrace
return ops.getViewBytes(snap, toOverlay(hostStart), buf);
}
@Override
public Address translate(Address address) {
Address host = platform.mapGuestToHost(address);
if (host == null) {
return null;
}
return toOverlay(host);
}
@Override
public <T> PcodeTracePropertyAccess<T> getPropertyAccess(String name, Class<T> type) {
return new DefaultPcodeTracePropertyAccess<>(this, name, type);

View file

@ -46,12 +46,12 @@ public class DefaultPcodeTraceAccess extends AbstractPcodeTraceAccess //
}
@Override
public DefaultPcodeTraceMemoryAccess newDataForSharedState() {
protected DefaultPcodeTraceMemoryAccess newDataForSharedState() {
return new DefaultPcodeTraceMemoryAccess(platform, snap, viewport);
}
@Override
public DefaultPcodeTraceRegistersAccess newDataForLocalState(TraceThread thread, int frame) {
protected DefaultPcodeTraceRegistersAccess newDataForLocalState(TraceThread thread, int frame) {
return new DefaultPcodeTraceRegistersAccess(platform, snap, thread, frame, viewport);
}
}

View file

@ -101,6 +101,14 @@ public class DefaultPcodeTraceThreadAccess
return memory.getBytes(start, buf);
}
@Override
public Address translate(Address address) {
if (address.isRegisterAddress()) {
return registers.translate(address);
}
return memory.translate(address);
}
@Override
public <T> PcodeTracePropertyAccess<T> getPropertyAccess(String name, Class<T> type) {
throw new UnsupportedOperationException("This is meant for p-code executor use");

View file

@ -16,6 +16,7 @@
package ghidra.pcode.exec.trace.data;
import ghidra.lifecycle.Internal;
import ghidra.trace.model.TraceTimeViewport;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.property.TracePropertyMapOperations;
@ -27,4 +28,6 @@ public interface InternalPcodeTraceDataAccess extends PcodeTraceDataAccess {
<T> TracePropertyMapOperations<T> getPropertyOps(String name, Class<T> type,
boolean createIfAbsent);
TraceTimeViewport getViewport();
}

View file

@ -106,6 +106,18 @@ public interface PcodeTraceAccess {
*/
PcodeTraceRegistersAccess getDataForLocalState(TraceThread thread, int frame);
/**
* Construct a new trace thread data-access shim
*
* @param shared the shared (memory) state
* @param local the local (register) state
* @return the thread data-access shim
*/
default PcodeTraceDataAccess newPcodeTraceThreadAccess(PcodeTraceMemoryAccess shared,
PcodeTraceRegistersAccess local) {
return new DefaultPcodeTraceThreadAccess(shared, local);
}
/**
* Get the data-access shim for use in an executor having thread context
*
@ -123,7 +135,7 @@ public interface PcodeTraceAccess {
if (thread == null) {
return getDataForSharedState();
}
return new DefaultPcodeTraceThreadAccess(getDataForSharedState(),
return newPcodeTraceThreadAccess(getDataForSharedState(),
getDataForLocalState(thread, frame));
}
}

View file

@ -123,6 +123,14 @@ public interface PcodeTraceDataAccess {
*/
int getBytes(Address start, ByteBuffer buf);
/**
* Translate the given emulator address to a host/overlay address
*
* @param address the emulator address
* @return the host/overlay address
*/
Address translate(Address address);
/**
* Get a property-access shim for the named property
*

View file

@ -291,6 +291,7 @@ public class DBTraceTimeViewport implements TraceTimeViewport {
}
}
@Override
public List<Range<Long>> getOrderedSpans() {
try (LockHold hold = trace.lockRead()) {
synchronized (ordered) {

View file

@ -173,6 +173,9 @@ public interface TraceTimeViewport {
<T> AddressSet computeVisibleParts(AddressSetView set, Range<Long> lifespan, T object,
Occlusion<T> occlusion);
List<Range<Long>> getOrderedSpans();
/**
* Get the snaps involved in the view in most-recent-first order
*