mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 21:15:32 +08:00
GP-6586: Allow wb-cache bypass. Update TenetLoader.
This commit is contained in:
+31
-45
@@ -52,6 +52,7 @@ import ghidra.trace.model.stack.TraceStackFrame;
|
|||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectManager;
|
import ghidra.trace.model.target.TraceObjectManager;
|
||||||
|
import ghidra.trace.model.target.TraceObjectManager.BypassWriteCache;
|
||||||
import ghidra.trace.model.target.path.KeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.target.schema.*;
|
import ghidra.trace.model.target.schema.*;
|
||||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
@@ -151,10 +152,10 @@ public class TenetLoader implements Loader {
|
|||||||
TENET_SESSION_SCHEMA = SAMPLE_CTX.getSchema(new SchemaName("TenetSession"));
|
TENET_SESSION_SCHEMA = SAMPLE_CTX.getSchema(new SchemaName("TenetSession"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AddressSpace defaultSpace;
|
private AddressSpace defaultSpace;
|
||||||
private static Program program;
|
private Program program;
|
||||||
|
|
||||||
private static boolean STORE_REG_ATTRS = false;
|
private static final boolean STORE_REG_ATTRS = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an address in the processor's default space.
|
* Create an address in the processor's default space.
|
||||||
@@ -162,7 +163,7 @@ public class TenetLoader implements Loader {
|
|||||||
* @param offset the byte offset
|
* @param offset the byte offset
|
||||||
* @return the address
|
* @return the address
|
||||||
*/
|
*/
|
||||||
private static Address addr(final long offset) {
|
private Address addr(final long offset) {
|
||||||
return defaultSpace.getAddress(offset);
|
return defaultSpace.getAddress(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,11 +206,11 @@ public class TenetLoader implements Loader {
|
|||||||
* @param max the maximum (inclusive) byte offset
|
* @param max the maximum (inclusive) byte offset
|
||||||
* @return the range
|
* @return the range
|
||||||
*/
|
*/
|
||||||
private static AddressRange rng(final long min, final long max) {
|
private AddressRange rng(final long min, final long max) {
|
||||||
return new AddressRangeImpl(addr(min), addr(max));
|
return new AddressRangeImpl(addr(min), addr(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Address toAddr(final String addressString) {
|
private Address toAddr(final String addressString) {
|
||||||
return AddressEvaluator.evaluate(program, addressString);
|
return AddressEvaluator.evaluate(program, addressString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,14 +322,16 @@ public class TenetLoader implements Loader {
|
|||||||
final Object consumer, final MessageLog log, final TaskMonitor monitor)
|
final Object consumer, final MessageLog log, final TaskMonitor monitor)
|
||||||
throws LanguageNotFoundException, IOException, CancelledException {
|
throws LanguageNotFoundException, IOException, CancelledException {
|
||||||
|
|
||||||
TenetLoader.program = program;
|
this.program = program;
|
||||||
final Language lang = program.getLanguage();
|
final Language lang = program.getLanguage();
|
||||||
TenetLoader.defaultSpace = lang.getAddressFactory().getDefaultAddressSpace();
|
this.defaultSpace = lang.getAddressFactory().getDefaultAddressSpace();
|
||||||
|
|
||||||
final Trace trace = new DBTrace(name, program.getCompilerSpec(), consumer);
|
final Trace trace = new DBTrace(name, program.getCompilerSpec(), consumer);
|
||||||
|
final TraceObjectManager om = trace.getObjectManager();
|
||||||
|
|
||||||
|
try (Transaction tx = trace.openTransaction("Import Tenet Trace: %s".formatted(name));
|
||||||
|
BypassWriteCache bypass = om.withoutWriteCache()) {
|
||||||
|
|
||||||
try (Transaction tx = trace.openTransaction("Import Tenet Trace: %s".formatted(name))) {
|
|
||||||
final TraceObjectManager om = trace.getObjectManager();
|
|
||||||
om.createRootObject(TENET_SESSION_SCHEMA);
|
om.createRootObject(TENET_SESSION_SCHEMA);
|
||||||
|
|
||||||
final TraceThread traceThread =
|
final TraceThread traceThread =
|
||||||
@@ -364,8 +367,9 @@ public class TenetLoader implements Loader {
|
|||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
final TraceSnapshot snapshot =
|
TraceSnapshot snapshot =
|
||||||
trace.getTimeManager().createSnapshot("Snapshot %d".formatted(snapNumber));
|
trace.getTimeManager().createSnapshot("Snapshot %d".formatted(snapNumber));
|
||||||
|
snapshot.setEventThread(traceThread);
|
||||||
long snap = snapshot.getKey();
|
long snap = snapshot.getKey();
|
||||||
|
|
||||||
snapNumber++;
|
snapNumber++;
|
||||||
@@ -381,51 +385,33 @@ public class TenetLoader implements Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Matcher ipMatcher = ipPattern.matcher(line);
|
final Matcher ipMatcher = ipPattern.matcher(line);
|
||||||
if (!ipMatcher.find()) {
|
if (ipMatcher.find()) {
|
||||||
|
curIp = Long.parseLong(ipMatcher.group(1), 16);
|
||||||
|
|
||||||
|
if (parseRegisterOperations(snap, curIp, line, lineNumber, traceThread,
|
||||||
|
trace, log, monitor)) {
|
||||||
|
parseMemoryOperations(snap, curIp, line, trace, monitor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
log.appendMsg(
|
log.appendMsg(
|
||||||
"Line %d: Unable to find PC, skipping...".formatted(lineNumber));
|
"Line %d: Unable to find PC, skipping...".formatted(lineNumber));
|
||||||
errorCount++;
|
errorCount++;
|
||||||
lineNumber++;
|
|
||||||
monitor.setProgress(lineNumber);
|
|
||||||
|
|
||||||
line = reader.readLine();
|
|
||||||
if (line != null) {
|
|
||||||
snap = trace.getTimeManager()
|
|
||||||
.createSnapshot("Snapshot %d".formatted(snapNumber))
|
|
||||||
.getKey();
|
|
||||||
snapNumber++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
curIp = Long.parseLong(ipMatcher.group(1), 16);
|
|
||||||
|
|
||||||
if (!parseRegisterOperations(snap, curIp, line, lineNumber, traceThread,
|
|
||||||
trace, log, monitor)) {
|
|
||||||
errorCount++;
|
|
||||||
lineNumber++;
|
|
||||||
monitor.setProgress(lineNumber);
|
|
||||||
|
|
||||||
line = reader.readLine();
|
|
||||||
if (line != null) {
|
|
||||||
snap = trace.getTimeManager()
|
|
||||||
.createSnapshot("Snapshot %d".formatted(snapNumber))
|
|
||||||
.getKey();
|
|
||||||
snapNumber++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parseMemoryOperations(snap, curIp, line, trace, monitor);
|
|
||||||
|
|
||||||
lineNumber++;
|
lineNumber++;
|
||||||
monitor.setProgress(lineNumber);
|
monitor.setProgress(lineNumber);
|
||||||
|
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
if (line != null) {
|
if (line != null) {
|
||||||
snap = trace.getTimeManager()
|
snapshot = trace.getTimeManager()
|
||||||
.createSnapshot("Snapshot %d".formatted(snapNumber))
|
.createSnapshot("Snapshot %d".formatted(snapNumber));
|
||||||
.getKey();
|
snap = snapshot.getKey();
|
||||||
|
snapshot.setEventThread(traceThread);
|
||||||
snapNumber++;
|
snapNumber++;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -189,6 +189,7 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
|
|||||||
protected final DBTraceObjectValueRStarTree valueTree;
|
protected final DBTraceObjectValueRStarTree valueTree;
|
||||||
protected final DBTraceObjectValueMap valueMap;
|
protected final DBTraceObjectValueMap valueMap;
|
||||||
protected final DBTraceObjectValueWriteBehindCache valueWbCache;
|
protected final DBTraceObjectValueWriteBehindCache valueWbCache;
|
||||||
|
protected boolean wbCacheDisabled;
|
||||||
|
|
||||||
protected final DBCachedObjectIndex<KeyPath, DBTraceObject> objectsByPath;
|
protected final DBCachedObjectIndex<KeyPath, DBTraceObject> objectsByPath;
|
||||||
|
|
||||||
@@ -331,9 +332,10 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
|
|||||||
protected DBTraceObjectValue doCreateValue(Lifespan lifespan, DBTraceObject parent, String key,
|
protected DBTraceObjectValue doCreateValue(Lifespan lifespan, DBTraceObject parent, String key,
|
||||||
Object value) {
|
Object value) {
|
||||||
// Root is never in write-behind cache
|
// Root is never in write-behind cache
|
||||||
DBTraceObjectValue entry =
|
boolean skipWb = wbCacheDisabled || parent == null;
|
||||||
parent == null ? doCreateValueData(lifespan, parent, key, value).getWrapper()
|
DBTraceObjectValue entry = skipWb
|
||||||
: valueWbCache.doCreateValue(lifespan, parent, key, value).getWrapper();
|
? doCreateValueData(lifespan, parent, key, value).getWrapper()
|
||||||
|
: valueWbCache.doCreateValue(lifespan, parent, key, value).getWrapper();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.notifyValueCreated(entry);
|
parent.notifyValueCreated(entry);
|
||||||
}
|
}
|
||||||
@@ -867,4 +869,15 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
|
|||||||
public void waitWbWorkers() {
|
public void waitWbWorkers() {
|
||||||
valueWbCache.waitWorkers();
|
valueWbCache.waitWorkers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BypassWriteCache withoutWriteCache() {
|
||||||
|
wbCacheDisabled = true;
|
||||||
|
return new BypassWriteCache() {
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
wbCacheDisabled = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -196,4 +196,26 @@ public interface TraceObjectManager {
|
|||||||
* database permits schema modification, but requires that the entire model be replaced.
|
* database permits schema modification, but requires that the entire model be replaced.
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A handle to automatically re-enable the write cache
|
||||||
|
*/
|
||||||
|
interface BypassWriteCache extends AutoCloseable {
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bypass the write cache, usually for an import operation.
|
||||||
|
* <p>
|
||||||
|
* For live sessions, we typically want to complete object writes as promptly as possible, so we
|
||||||
|
* don't tie up the connection and/or the remote debugger. However, for import operations, we'd
|
||||||
|
* rather just have object writes go straight to the database. The importer will want to save,
|
||||||
|
* which requires flushing the cache anyway. Disabling the cache gives more honest progress
|
||||||
|
* reporting and assures any crashes or diagnostics occur during the import rather than during
|
||||||
|
* the flush.
|
||||||
|
*
|
||||||
|
* @return a handle to automatically re-enable the write cache
|
||||||
|
*/
|
||||||
|
BypassWriteCache withoutWriteCache();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user