diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java index 40d542c548..ea2fc17f73 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java @@ -93,6 +93,9 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint { @Override public String toString() { + // volatile reads + Bookmark eBookmark = this.eBookmark; + Bookmark dBookmark = this.dBookmark; if (eBookmark != null) { return String.format("", eBookmark.getTypeString(), eBookmark.getCategory(), eBookmark.getAddress(), program.getName()); @@ -127,6 +130,9 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint { } public void deleteFromProgram() { + // volatile reads + Bookmark eBookmark = this.eBookmark; + Bookmark dBookmark = this.dBookmark; try (UndoableTransaction tid = UndoableTransaction.start(program, "Clear breakpoint", false)) { BookmarkManager bookmarkManager = program.getBookmarkManager(); @@ -193,6 +199,7 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint { } public Bookmark getBookmark() { + Bookmark eBookmark = this.eBookmark; if (eBookmark != null) { return eBookmark; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java index 108018709a..baed266b62 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java @@ -81,6 +81,7 @@ public class DefaultTraceRecorder implements TraceRecorder { public DefaultTraceRecorder(DebuggerModelServicePlugin plugin, Trace trace, TargetObject target, DefaultDebuggerTargetTraceMapper mapper) { + trace.addConsumer(this); this.plugin = plugin; this.tool = plugin.getTool(); this.trace = trace; @@ -99,9 +100,6 @@ public class DefaultTraceRecorder implements TraceRecorder { this.symbolRecorder = new DefaultSymbolRecorder(this); this.timeRecorder = new DefaultTimeRecorder(this); this.objectManager = new TraceObjectManager(target, mapper, this); - - trace.addConsumer(this); - } /*---------------- OBJECT MANAGER METHODS -------------------*/ @@ -358,9 +356,14 @@ public class DefaultTraceRecorder implements TraceRecorder { } protected void invalidate() { - valid = false; objectManager.disposeModelListeners(); - trace.release(this); + synchronized (this) { + if (!valid) { + return; + } + valid = false; + trace.release(this); + } } /*---------------- FOCUS-SUPPORT METHODS -------------------*/ diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServicePlugin.java index eb280b413d..c301ed983d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServicePlugin.java @@ -213,11 +213,6 @@ public class DebuggerStaticMappingServicePlugin extends Plugin return new AddressRangeImpl(min, max); } - public Program openStaticProgram() { - return ProgramURLUtils.openHackedUpGhidraURL(programManager, tool.getProject(), - mapping.getStaticProgramURL(), ProgramManager.OPEN_VISIBLE); - } - public boolean isStaticProgramOpen() { return program != null; } @@ -389,31 +384,22 @@ public class DebuggerStaticMappingServicePlugin extends Plugin return Collections.unmodifiableMap(result); } - protected void openAndCollectPrograms(AddressRange rng, Range span, - Set result, Set failures) { + protected void collectMappedProgramURLsInView(AddressRange rng, Range span, + Set result) { TraceAddressSnapRange tatr = new ImmutableTraceAddressSnapRange(rng, span); for (Entry out : outbound.entrySet()) { if (!out.getKey().intersects(tatr)) { continue; } MappingEntry me = out.getValue(); - try { - result.add(me.openStaticProgram()); - } - catch (Exception e) { - if (failures == null) { - throw e; - } - failures.add(e); - } + result.add(me.getStaticProgramURL()); } } - public Set openMappedProgramsInView(AddressSetView set, Range span, - Set failures) { - Set result = new HashSet<>(); + public Set getMappedProgramURLsInView(AddressSetView set, Range span) { + Set result = new HashSet<>(); for (AddressRange rng : set) { - openAndCollectPrograms(rng, span, result, failures); + collectMappedProgramURLsInView(rng, span, result); } return Collections.unmodifiableSet(result); } @@ -847,20 +833,24 @@ public class DebuggerStaticMappingServicePlugin extends Plugin @Override public Set getOpenMappedProgramsAtSnap(Trace trace, long snap) { - InfoPerTrace info = requireTrackedInfo(trace); - if (info == null) { - return null; + synchronized (lock) { + InfoPerTrace info = requireTrackedInfo(trace); + if (info == null) { + return null; + } + return info.getOpenMappedProgramsAtSnap(snap); } - return info.getOpenMappedProgramsAtSnap(snap); } @Override public ProgramLocation getOpenMappedLocation(TraceLocation loc) { - InfoPerTrace info = requireTrackedInfo(loc.getTrace()); - if (info == null) { - return null; + synchronized (lock) { + InfoPerTrace info = requireTrackedInfo(loc.getTrace()); + if (info == null) { + return null; + } + return info.getOpenMappedLocations(loc.getAddress(), loc.getLifespan()); } - return info.getOpenMappedLocations(loc.getAddress(), loc.getLifespan()); } protected long getNonScratchSnap(TraceProgramView view) { @@ -869,75 +859,106 @@ public class DebuggerStaticMappingServicePlugin extends Plugin @Override public ProgramLocation getStaticLocationFromDynamic(ProgramLocation loc) { - loc = ProgramLocationUtils.fixLocation(loc, true); - TraceProgramView view = (TraceProgramView) loc.getProgram(); - Trace trace = view.getTrace(); - TraceLocation tloc = new DefaultTraceLocation(trace, null, - Range.singleton(getNonScratchSnap(view)), loc.getByteAddress()); - ProgramLocation mapped = getOpenMappedLocation(tloc); - if (mapped == null) { - return null; + synchronized (lock) { + loc = ProgramLocationUtils.fixLocation(loc, true); + TraceProgramView view = (TraceProgramView) loc.getProgram(); + Trace trace = view.getTrace(); + TraceLocation tloc = new DefaultTraceLocation(trace, null, + Range.singleton(getNonScratchSnap(view)), loc.getByteAddress()); + ProgramLocation mapped = getOpenMappedLocation(tloc); + if (mapped == null) { + return null; + } + return ProgramLocationUtils.replaceAddress(loc, mapped.getProgram(), + mapped.getByteAddress()); } - return ProgramLocationUtils.replaceAddress(loc, mapped.getProgram(), - mapped.getByteAddress()); } @Override public Set getOpenMappedLocations(ProgramLocation loc) { - InfoPerProgram info = requireTrackedInfo(loc.getProgram()); - if (info == null) { - return null; + synchronized (lock) { + InfoPerProgram info = requireTrackedInfo(loc.getProgram()); + if (info == null) { + return null; + } + return info.getOpenMappedTraceLocations(loc.getByteAddress()); } - return info.getOpenMappedTraceLocations(loc.getByteAddress()); } @Override public TraceLocation getOpenMappedLocation(Trace trace, ProgramLocation loc, long snap) { - InfoPerProgram info = requireTrackedInfo(loc.getProgram()); - if (info == null) { - return null; + synchronized (lock) { + InfoPerProgram info = requireTrackedInfo(loc.getProgram()); + if (info == null) { + return null; + } + return info.getOpenMappedTraceLocation(trace, loc.getByteAddress(), snap); } - return info.getOpenMappedTraceLocation(trace, loc.getByteAddress(), snap); } @Override public ProgramLocation getDynamicLocationFromStatic(TraceProgramView view, ProgramLocation loc) { - TraceLocation tloc = getOpenMappedLocation(view.getTrace(), loc, getNonScratchSnap(view)); - if (tloc == null) { - return null; + synchronized (lock) { + TraceLocation tloc = + getOpenMappedLocation(view.getTrace(), loc, getNonScratchSnap(view)); + if (tloc == null) { + return null; + } + return ProgramLocationUtils.replaceAddress(loc, view, tloc.getAddress()); } - return ProgramLocationUtils.replaceAddress(loc, view, tloc.getAddress()); } @Override public Map> getOpenMappedViews(Trace trace, AddressSetView set, long snap) { - InfoPerTrace info = requireTrackedInfo(trace); - if (info == null) { - return null; + synchronized (lock) { + InfoPerTrace info = requireTrackedInfo(trace); + if (info == null) { + return null; + } + return info.getOpenMappedViews(set, Range.singleton(snap)); } - return info.getOpenMappedViews(set, Range.singleton(snap)); } @Override public Map> getOpenMappedViews(Program program, AddressSetView set) { - InfoPerProgram info = requireTrackedInfo(program); - if (info == null) { - return null; + synchronized (lock) { + InfoPerProgram info = requireTrackedInfo(program); + if (info == null) { + return null; + } + return info.getOpenMappedViews(set); } - return info.getOpenMappedViews(set); } @Override public Set openMappedProgramsInView(Trace trace, AddressSetView set, long snap, Set failures) { - InfoPerTrace info = requireTrackedInfo(trace); - if (info == null) { - return null; + Set urls; + synchronized (lock) { + InfoPerTrace info = requireTrackedInfo(trace); + if (info == null) { + return null; + } + urls = info.getMappedProgramURLsInView(set, Range.singleton(snap)); } - return info.openMappedProgramsInView(set, Range.singleton(snap), failures); + Set result = new HashSet<>(); + for (URL url : urls) { + try { + Program program = ProgramURLUtils.openHackedUpGhidraURL(programManager, + tool.getProject(), url, ProgramManager.OPEN_VISIBLE); + result.add(program); + } + catch (Exception e) { + if (failures == null) { + throw e; + } + failures.add(e); + } + } + return result; } protected Collection orderCurrentFirst( diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/UndoableTransaction.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/UndoableTransaction.java index 9ba290dfb7..b6fc85dc52 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/UndoableTransaction.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/UndoableTransaction.java @@ -79,6 +79,7 @@ public interface UndoableTransaction extends AutoCloseable { @Override public void close() { if (open) { + open = false; endTransaction(commit); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectDBTransaction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectDBTransaction.java index a7fc529b9e..123d93c4be 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectDBTransaction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectDBTransaction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,8 @@ */ package ghidra.framework.data; +import java.util.*; + import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; import ghidra.util.Msg; @@ -23,8 +24,6 @@ import ghidra.util.SystemUtilities; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; -import java.util.*; - /** * DomainObjectDBTransaction represents an atomic undoable operation performed * on a single domain object. @@ -145,7 +144,7 @@ class DomainObjectDBTransaction implements Transaction { try { entry = list.get(transactionID - baseId); } - catch (ArrayIndexOutOfBoundsException e) { + catch (IndexOutOfBoundsException e) { throw new IllegalStateException("Transaction not found"); } if (entry.status != NOT_DONE) {