diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerStaticMappingService.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerStaticMappingService.java index a02b83d021..fc3f2ed339 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerStaticMappingService.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerStaticMappingService.java @@ -31,25 +31,21 @@ import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.modules.*; -import ghidra.trace.model.program.TraceProgramView; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; /** * A service for consuming and mutating trace static mappings, i.e., relocations - * *

* This service consumes and tracks all open traces' mappings, tracks when the destination programs * are opened and closed, notifies listeners of changes in the tool's overall mapping picture, and * provides for addition and validation of new mappings. - * *

* Note, the relation of trace locations to program locations is many-to-one. - * *

* This service also provides methods for proposing and adding mappings. */ -public interface DebuggerStaticMappingService { +public interface DebuggerStaticMappingService extends DebuggerAddressTranslator { /** * Add a static mapping (relocation) from the given trace to the given program @@ -84,12 +80,10 @@ public interface DebuggerStaticMappingService { /** * Add several static mappings (relocations) - * *

* This will group the entries by trace and add each's entries in a single transaction. If any * entry fails, including due to conflicts, that failure is logged but ignored, and the * remaining entries are processed. - * *

* Any entries indicated for memorization will have their module paths added to the destination * program's metadata. @@ -107,7 +101,6 @@ public interface DebuggerStaticMappingService { /** * Add several static mappings (relocations) - * *

* This will group the entries by trace and add each's entries in a single transaction. If any * entry fails, including due to conflicts, that failure is logged but ignored, and the @@ -124,7 +117,6 @@ public interface DebuggerStaticMappingService { /** * Add several static mappings (relocations) - * *

* This will group the entries by trace and add each's entries in a single transaction. If any * entry fails, including due to conflicts, that failure is logged but ignored, and the @@ -139,97 +131,16 @@ public interface DebuggerStaticMappingService { void addRegionMappings(Collection entries, TaskMonitor monitor, boolean truncateExisting) throws CancelledException; - /** - * Collect all the open destination programs relevant for the given trace and snap - * - * @param trace the trace - * @param snap the snap - * @return the set of open destination programs - */ - Set getOpenMappedProgramsAtSnap(Trace trace, long snap); - - /** - * Map the given trace location to a program location, if the destination is open - * - * @param loc the source location - * @return the destination location, or {@code null} if not mapped, or not open - */ - ProgramLocation getOpenMappedLocation(TraceLocation loc); - - /** - * Similar to {@link #getOpenMappedLocation(TraceLocation)} but preserves details - * - *

- * The given location's {@link ProgramLocation#getProgram()} method must return a - * {@link TraceProgramView}. It derives the trace and snap from that view. Additionally, this - * will attempt to map over other "location" details, e.g., field, row, column. - * - * @param loc a location within a trace view - * @return a mapped location in a program, or {@code null} - */ - ProgramLocation getStaticLocationFromDynamic(ProgramLocation loc); - - /** - * Map the given program location back to open source trace locations - * - * @param loc the program location - * @return the, possibly empty, set of trace locations - */ - Set getOpenMappedLocations(ProgramLocation loc); - - /** - * Map the given program location back to a source trace and snap - * - * @param trace the source trace, to which we are mapping back - * @param loc the destination location, from which we are mapping back - * @param snap the source snap, to which we are mapping back - * @return the source of the found mapping, or {@code null} if not mapped - */ - TraceLocation getOpenMappedLocation(Trace trace, ProgramLocation loc, long snap); - - /** - * Similar to {@link #getOpenMappedLocation(Trace, ProgramLocation, long)} but preserves details - * - *

- * This method derives the source trace and snap from the given view. Additinoally, this will - * attempt to map over other "location" details, e.g., field, row, column. - * - * @param view the view, specifying the source trace and snap, to which we are mapping back - * @param loc the destination location, from which we are mapping back. - * @return the destination of the found mapping, or {@code null} if not mapped - */ - ProgramLocation getDynamicLocationFromStatic(TraceProgramView view, ProgramLocation loc); - - /** - * Find/compute all destination address sets given a source trace address set - * - * @param trace the source trace - * @param set the source address set - * @param snap the source snap - * @return a map of destination programs to corresponding computed destination address ranges - */ - Map> getOpenMappedViews(Trace trace, - AddressSetView set, long snap); - - /** - * Find/compute all source address sets given a destination program address set - * - * @param program the destination program, from which we are mapping back - * @param set the destination address set, from which we are mapping back - * @return a map of source traces to corresponding computed source address ranges - */ - Map> getOpenMappedViews(Program program, - AddressSetView set); - /** * Open all destination programs in mappings intersecting the given source trace, address set, * and snap - * + *

+ * This essentially calls {@link #getMappedProgramUrlsInView(Trace, AddressSetView, long)} and + * then tries to open each one. *

* Note, because the trace's mapping table contains {@link Program} URLs, it's possible the * destination program(s) do not exist, and/or that there may be errors opening the destinations * program(s). - * *

* Note, the caller to this method should not expect the relevant mappings to be immediately * loaded by the manager implementation. Instead, it should listen for the expected changes in @@ -265,7 +176,6 @@ public interface DebuggerStaticMappingService { /** * Get a future which completes when pending changes have all settled - * *

* The returned future completes after all change listeners have been invoked. * @@ -275,7 +185,6 @@ public interface DebuggerStaticMappingService { /** * Find the best match among programs in the project for the given trace module - * *

* The service maintains an index of likely module names to domain files in the active project. * This will search that index for the module's full file path. Failing that, it will search @@ -295,7 +204,6 @@ public interface DebuggerStaticMappingService { /** * Propose a module map for the given module to the given program - * *

* Note, no sanity check is performed on the given parameters. This will simply propose the * given module-program pair. It is strongly advised to use @@ -312,14 +220,12 @@ public interface DebuggerStaticMappingService { /** * Compute the best-scored module map for the given module and programs - * *

* Note, no sanity check is performed on any given module-program pair. Instead, the * highest-scoring proposal is selected from the possible module-program pairs. In particular, * the names of the programs vs. the module name may not be examined by the implementation. * * @see ModuleMapProposal#computeScore() - * * @param module the module to consider * @param snap the source snapshot key * @param programs a set of proposed destination programs @@ -331,7 +237,6 @@ public interface DebuggerStaticMappingService { /** * Compute the "best" map of trace module to program for each given module given a collection of * proposed programs. - * *

* Note, this method will first examine module and program names in order to cull unlikely * pairs. It then takes the best-scored proposal for each module. If a module has no likely @@ -349,7 +254,6 @@ public interface DebuggerStaticMappingService { /** * Propose a singleton section map from the given section to the given program memory block - * *

* Note, no sanity check is performed on the given parameters. This will simply give a singleton * map of the given entry. It is strongly advised to use @@ -368,7 +272,6 @@ public interface DebuggerStaticMappingService { /** * Propose a section map for the given module to the given program - * *

* Note, no sanity check is performed on the given parameters. This will do its best to map * sections from the given module to memory blocks in the given program. It is strongly advised @@ -385,14 +288,12 @@ public interface DebuggerStaticMappingService { /** * Proposed the best-scored section map for the given module and programs - * *

* Note, no sanity check is performed on any given module-program pair. Instead, the * highest-scoring proposal is selected from the possible module-program pairs. In particular, * the names of the programs vs. the module name may not be examined by the implementation. * * @see SectionMapProposal#computeScore() - * * @param module the module whose sections to map * @param snap the source snapshot key * @param programs a set of proposed destination programs @@ -404,7 +305,6 @@ public interface DebuggerStaticMappingService { /** * Propose the best-scored maps of trace sections to program memory blocks for each given module * given a collection of proposed programs. - * *

* Note, this method will first examine module and program names in order to cull unlikely * pairs. It then takes the best-scored proposal for each module. If a module has no likely @@ -422,7 +322,6 @@ public interface DebuggerStaticMappingService { /** * Propose a singleton region map from the given region to the given program memory block - * *

* Note, no sanity check is performed on the given parameters. This will simply give a singleton * map of the given entry. It is strongly advised to use @@ -441,7 +340,6 @@ public interface DebuggerStaticMappingService { /** * Propose a region map for the given regions to the given program - * *

* Note, no sanity check is performed on the given parameters. This will do its best to map * regions to memory blocks in the given program. For the best results, regions should all @@ -462,7 +360,6 @@ public interface DebuggerStaticMappingService { /** * Propose the best-scored maps of trace regions to program memory blocks for each given * "module" given a collection of proposed programs. - * *

* Note, this method will first group regions into likely modules by parsing their names, then * compare to program names in order to cull unlikely pairs. It then takes the best-scored diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/modules/DebuggerAddressTranslator.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/modules/DebuggerAddressTranslator.java new file mode 100644 index 0000000000..c3a2d2b257 --- /dev/null +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/modules/DebuggerAddressTranslator.java @@ -0,0 +1,123 @@ +/* ### + * 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.debug.api.modules; + +import java.net.URL; +import java.util.*; + +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.listing.Program; +import ghidra.program.util.ProgramLocation; +import ghidra.trace.model.*; +import ghidra.trace.model.program.TraceProgramView; + +/** + * This interface provides a mechanism for translating static address to dynamic and vice versa, + * with respect to each trace's "Static Mappings" table. + */ +public interface DebuggerAddressTranslator { + + /** + * Collect all the open destination programs relevant for the given trace and snap + * + * @param trace the trace + * @param snap the snap + * @return the set of open destination programs + */ + Set getOpenMappedProgramsAtSnap(Trace trace, long snap); + + /** + * Map the given trace location to a program location, if the destination is open + * + * @param loc the source location + * @return the destination location, or {@code null} if not mapped, or not open + */ + ProgramLocation getOpenMappedLocation(TraceLocation loc); + + /** + * Similar to {@link #getOpenMappedLocation(TraceLocation)} but preserves details + *

+ * The given location's {@link ProgramLocation#getProgram()} method must return a + * {@link TraceProgramView}. It derives the trace and snap from that view. Additionally, this + * will attempt to map over other "location" details, e.g., field, row, column. + * + * @param loc a location within a trace view + * @return a mapped location in a program, or {@code null} + */ + ProgramLocation getStaticLocationFromDynamic(ProgramLocation loc); + + /** + * Map the given program location back to open source trace locations + * + * @param loc the program location + * @return the, possibly empty, set of trace locations + */ + Set getOpenMappedLocations(ProgramLocation loc); + + /** + * Map the given program location back to a source trace and snap + * + * @param trace the source trace, to which we are mapping back + * @param loc the destination location, from which we are mapping back + * @param snap the source snap, to which we are mapping back + * @return the source of the found mapping, or {@code null} if not mapped + */ + TraceLocation getOpenMappedLocation(Trace trace, ProgramLocation loc, long snap); + + /** + * Similar to {@link #getOpenMappedLocation(Trace, ProgramLocation, long)} but preserves details + *

+ * This method derives the source trace and snap from the given view. Additinoally, this will + * attempt to map over other "location" details, e.g., field, row, column. + * + * @param view the view, specifying the source trace and snap, to which we are mapping back + * @param loc the destination location, from which we are mapping back. + * @return the destination of the found mapping, or {@code null} if not mapped + */ + ProgramLocation getDynamicLocationFromStatic(TraceProgramView view, ProgramLocation loc); + + /** + * Find/compute all destination address sets given a source trace address set + * + * @param trace the source trace + * @param set the source address set + * @param snap the source snap + * @return a map of destination programs to corresponding computed destination address ranges + */ + Map> getOpenMappedViews(Trace trace, + AddressSetView set, long snap); + + /** + * Find/compute all source address sets given a destination program address set + * + * @param program the destination program, from which we are mapping back + * @param set the destination address set, from which we are mapping back + * @return a map of source traces to corresponding computed source address ranges + */ + Map> getOpenMappedViews(Program program, + AddressSetView set); + + /** + * Get all destination program URLs in mappings intersecting the given source trace, address + * set, and snap + * + * @param trace the source trace + * @param set the source address set + * @param snap the source snap + * @return the set of destination URLs + */ + Set getMappedProgramUrlsInView(Trace trace, AddressSetView set, long snap); +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingContext.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingContext.java index 3507c43778..af28f96c6a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingContext.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingContext.java @@ -22,8 +22,7 @@ import java.util.stream.Collectors; import ghidra.app.plugin.core.debug.utils.ProgramLocationUtils; import ghidra.async.AsyncUtils; -import ghidra.debug.api.modules.DebuggerStaticMappingChangeListener; -import ghidra.debug.api.modules.MappedAddressRange; +import ghidra.debug.api.modules.*; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; @@ -32,7 +31,7 @@ import ghidra.trace.model.program.TraceProgramView; import ghidra.util.Msg; import ghidra.util.datastruct.ListenerSet; -public class DebuggerStaticMappingContext { +public class DebuggerStaticMappingContext implements DebuggerAddressTranslator { record ChangeCollector(DebuggerStaticMappingContext ctx, Set traces, Set programs) implements AutoCloseable { @@ -237,6 +236,7 @@ public class DebuggerStaticMappingContext { return info; } + @Override public Set getOpenMappedProgramsAtSnap(Trace trace, long snap) { synchronized (lock) { InfoPerTrace info = requireTrackedInfo(trace); @@ -247,6 +247,7 @@ public class DebuggerStaticMappingContext { } } + @Override public ProgramLocation getOpenMappedLocation(TraceLocation loc) { synchronized (lock) { InfoPerTrace info = requireTrackedInfo(loc.getTrace()); @@ -261,6 +262,7 @@ public class DebuggerStaticMappingContext { return view.getViewport().getTop(s -> s >= 0 ? s : null); } + @Override public ProgramLocation getStaticLocationFromDynamic(ProgramLocation loc) { synchronized (lock) { loc = ProgramLocationUtils.fixLocation(loc, true); @@ -277,6 +279,7 @@ public class DebuggerStaticMappingContext { } } + @Override public Set getOpenMappedLocations(ProgramLocation loc) { synchronized (lock) { InfoPerProgram info = requireTrackedInfo(loc.getProgram()); @@ -287,6 +290,7 @@ public class DebuggerStaticMappingContext { } } + @Override public TraceLocation getOpenMappedLocation(Trace trace, ProgramLocation loc, long snap) { synchronized (lock) { InfoPerProgram info = requireTrackedInfo(loc.getProgram()); @@ -297,6 +301,7 @@ public class DebuggerStaticMappingContext { } } + @Override public ProgramLocation getDynamicLocationFromStatic(TraceProgramView view, ProgramLocation loc) { synchronized (lock) { @@ -309,6 +314,7 @@ public class DebuggerStaticMappingContext { } } + @Override public Map> getOpenMappedViews(Trace trace, AddressSetView set, long snap) { synchronized (lock) { @@ -320,6 +326,7 @@ public class DebuggerStaticMappingContext { } } + @Override public Map> getOpenMappedViews(Program program, AddressSetView set) { synchronized (lock) { @@ -331,6 +338,7 @@ public class DebuggerStaticMappingContext { } } + @Override public Set getMappedProgramUrlsInView(Trace trace, AddressSetView set, long snap) { synchronized (lock) { InfoPerTrace info = requireTrackedInfo(trace); 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 54340411c8..0220075812 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 @@ -254,6 +254,11 @@ public class DebuggerStaticMappingServicePlugin extends Plugin addMappings(entries, monitor, truncateExisting, "Add regions mappings"); } + @Override + public Set getMappedProgramUrlsInView(Trace trace, AddressSetView set, long snap) { + return context.getMappedProgramUrlsInView(trace, set, snap); + } + @Override public Set openMappedProgramsInView(Trace trace, AddressSetView set, long snap, Set failures) {