Merge remote-tracking branch 'origin/GP-1488_Dan_emuLogging--REBASED-2--SQUASHED' into Ghidra_10.1

This commit is contained in:
ghidra1 2021-11-30 19:14:37 -05:00
commit c5957bf0d8
11 changed files with 94 additions and 48 deletions

View file

@ -17,9 +17,6 @@ package ghidra.app.plugin.core.debug.service.emulation;
import java.util.concurrent.*;
import com.google.common.collect.Range;
import com.google.common.primitives.UnsignedLong;
import ghidra.app.services.TraceRecorder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.pcode.exec.AccessPcodeExecutionException;
@ -56,17 +53,19 @@ public abstract class AbstractReadsTargetPcodeExecutorState
@Override
public byte[] read(long offset, int size) {
if (source != null) {
AddressSet uninitialized = new AddressSet();
for (Range<UnsignedLong> rng : cache.getUninitialized(offset, offset + size - 1)
.asRanges()) {
uninitialized.add(space.getAddress(lower(rng)),
space.getAddress(upper(rng)));
}
AddressSet uninitialized =
addrSet(cache.getUninitialized(offset, offset + size - 1));
if (uninitialized.isEmpty()) {
return super.read(offset, size);
}
fillUninitialized(uninitialized);
AddressSet unknown =
computeUnknown(addrSet(cache.getUninitialized(offset, offset + size - 1)));
if (!unknown.isEmpty()) {
warnUnknown(unknown);
}
}
// TODO: What to flush when bytes in the trace change?

View file

@ -62,7 +62,6 @@ public class ReadsTargetMemoryPcodeExecutorState
return;
}
}
Msg.warn(this, "Emulator read from UNKNOWN state: " + unknown);
}
protected boolean fillUnknownWithRecorder(AddressSet unknown) {
@ -92,7 +91,7 @@ public class ReadsTargetMemoryPcodeExecutorState
long shift = mappedRng.getShift();
for (AddressRange subsrng : initialized.intersectRange(srng.getMinAddress(),
srng.getMaxAddress())) {
Msg.warn(this,
Msg.debug(this,
"Filling in unknown trace memory in emulator using mapped image: " +
program + ": " + subsrng);
long lower = subsrng.getMinAddress().getOffset();
@ -107,6 +106,7 @@ public class ReadsTargetMemoryPcodeExecutorState
" Partial read of " + subsrng + ". Got " + read +
" bytes");
}
// write(lower - shift, data, 0 ,read);
cache.putData(lower - shift, data, 0, read);
}
catch (MemoryAccessException | AddressOutOfBoundsException e) {

View file

@ -15,7 +15,6 @@
*/
package ghidra.pcode.exec.trace;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.primitives.UnsignedLong;
@ -32,20 +31,6 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorState
super(space, source, snap);
}
protected AddressRange addrRng(Range<UnsignedLong> rng) {
Address start = space.getAddress(lower(rng));
Address end = space.getAddress(upper(rng));
return new AddressRangeImpl(start, end);
}
protected AddressSet addrSet(RangeSet<UnsignedLong> set) {
AddressSet result = new AddressSet();
for (Range<UnsignedLong> rng : set.asRanges()) {
result.add(addrRng(rng));
}
return result;
}
@Override
public byte[] read(long offset, int size) {
RangeSet<UnsignedLong> uninitialized =

View file

@ -16,8 +16,7 @@
package ghidra.pcode.exec.trace;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import com.google.common.collect.*;
import com.google.common.primitives.UnsignedLong;
@ -27,8 +26,9 @@ import ghidra.pcode.exec.AbstractLongOffsetPcodeExecutorState;
import ghidra.pcode.exec.BytesPcodeArithmetic;
import ghidra.pcode.exec.trace.TraceCachedWriteBytesPcodeExecutorState.CachedSpace;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.Memory;
import ghidra.trace.model.Trace;
@ -36,6 +36,7 @@ import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.MemBufferAdapter;
import ghidra.util.MathUtilities;
import ghidra.util.Msg;
/**
* A state which reads bytes from a trace, but caches writes internally.
@ -109,10 +110,10 @@ public class TraceCachedWriteBytesPcodeExecutorState
this.snap = snap;
}
public void write(long offset, byte[] val) {
cache.putData(offset, val);
public void write(long offset, byte[] buffer, int srcOffset, int length) {
cache.putData(offset, buffer, srcOffset, length);
UnsignedLong uLoc = UnsignedLong.fromLongBits(offset);
UnsignedLong uEnd = UnsignedLong.fromLongBits(offset + val.length);
UnsignedLong uEnd = UnsignedLong.fromLongBits(offset + length);
written.add(Range.closedOpen(uLoc, uEnd));
}
@ -150,6 +151,62 @@ public class TraceCachedWriteBytesPcodeExecutorState
return data;
}
protected AddressRange addrRng(Range<UnsignedLong> rng) {
Address start = space.getAddress(lower(rng));
Address end = space.getAddress(upper(rng));
return new AddressRangeImpl(start, end);
}
protected AddressSet addrSet(RangeSet<UnsignedLong> set) {
AddressSet result = new AddressSet();
for (Range<UnsignedLong> rng : set.asRanges()) {
result.add(addrRng(rng));
}
return result;
}
protected Set<Register> getRegs(AddressSet set) {
// TODO: Should pass in language instead?
Language language = source.getTrace().getBaseLanguage();
Set<Register> regs = new TreeSet<>();
for (AddressRange rng : set) {
Register r = language.getRegister(rng.getMinAddress(), (int) rng.getLength());
if (r != null) {
regs.add(r);
}
else {
regs.addAll(Arrays.asList(language.getRegisters(rng.getMinAddress())));
}
}
return regs;
}
protected void warnState(AddressSet set, String message) {
Set<Register> regs = getRegs(set);
if (regs.isEmpty()) {
Msg.warn(this, message + ": " + set);
}
else {
Msg.warn(this, message + ": " + set + " (registers " + regs + ")");
}
}
protected void warnUninit(RangeSet<UnsignedLong> uninit) {
AddressSet uninitialized = addrSet(uninit);
Set<Register> regs = getRegs(uninitialized);
if (regs.isEmpty()) {
Msg.warn(this, "Emulator read from uninitialized state: " + uninit);
}
Msg.warn(this, "Emulator read from uninitialized state: " + uninit +
" (includes registers: " + regs + ")");
}
protected void warnUnknown(AddressSet unknown) {
Set<Register> regs = getRegs(unknown);
Msg.warn(this, "Emulator state initialized from UNKNOWN: " + unknown +
"(includes registers: " + regs + ")");
}
public byte[] read(long offset, int size) {
if (source != null) {
// TODO: Warn or bail when reading UNKNOWN bytes
@ -157,6 +214,10 @@ public class TraceCachedWriteBytesPcodeExecutorState
// NOTE: Cannot write those gaps, though!!!
readUninitializedFromSource(cache.getUninitialized(offset, offset + size - 1));
}
RangeSet<UnsignedLong> stillUninit = cache.getUninitialized(offset, offset + size - 1);
if (!stillUninit.isEmpty()) {
warnUninit(stillUninit);
}
return readCached(offset, size);
}
@ -251,7 +312,7 @@ public class TraceCachedWriteBytesPcodeExecutorState
@Override
protected void setInSpace(CachedSpace space, long offset, int size, byte[] val) {
assert size == val.length;
space.write(offset, val);
space.write(offset, val, 0, val.length);
}
@Override

View file

@ -19,7 +19,6 @@ import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Objects;
import java.util.function.BiConsumer;

View file

@ -15,16 +15,10 @@
*/
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;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.mem.MemoryBlock;
public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramViewMemoryBlock {

View file

@ -120,7 +120,7 @@ public class DBTraceProgramViewRootModule implements ProgramModule {
try (LockHold hold = LockHold.lock(program.trace.getReadWriteLock().readLock())) {
program.memory.forVisibleRegions(region -> names.add(region.getName()));
}
return names.indexOf(names);
return names.indexOf(name);
}
@Override

View file

@ -15,8 +15,6 @@
*/
package ghidra.trace.database.program;
import ghidra.framework.model.DomainObject;
import ghidra.framework.model.DomainObjectChangeRecord;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.CodeUnit;
import ghidra.trace.database.DBTrace;

View file

@ -21,7 +21,6 @@ import java.util.Objects;
import db.DBRecord;
import ghidra.lifecycle.Internal;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;

View file

@ -61,6 +61,7 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject
private static final byte SOURCE_CLEAR = ~(SOURCE_MASK << SOURCE_SHIFT);
private static final byte PRIMARY_MASK = 0x10;
@SuppressWarnings("unused")
private static final int PRIMARY_CLEAR = ~PRIMARY_MASK;
static final String NAME_COLUMN_NAME = "Name";

View file

@ -87,6 +87,16 @@ public class SemisparseByteArrayTest {
assertEquals(HELLO_WORLD, new String(data));
}
@Test
public void testBoundaryAtUnsignedMax() {
SemisparseByteArray cache = new SemisparseByteArray();
cache.putData(-HW.length, HW);
byte[] data = new byte[HW.length];
cache.getData(-HW.length, data);
assertEquals(HELLO_WORLD, new String(data));
}
@Test
public void testLarge() {
Random rand = new Random();