mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-23 20:59:58 +00:00
GP-4713: Launch mapping uses AutoMapSpec. Fix StaticMappingService.
This commit is contained in:
parent
ebb4027d8b
commit
d95200b166
@ -0,0 +1,42 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.app.services;
|
||||||
|
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
|
import ghidra.framework.plugintool.ServiceInfo;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service to query auto-map settings
|
||||||
|
*/
|
||||||
|
@ServiceInfo(defaultProviderName = "ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesPlugin")
|
||||||
|
public interface DebuggerAutoMappingService {
|
||||||
|
/**
|
||||||
|
* Get the auto-map setting currently active in the Modules provider
|
||||||
|
*
|
||||||
|
* @return the current setting
|
||||||
|
*/
|
||||||
|
AutoMapSpec getAutoMapSpec();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current auto-map setting for the given trace
|
||||||
|
*
|
||||||
|
* @param trace the trace
|
||||||
|
* @return the auto-map setting for the trace, or the setting in the Modules provider, if the
|
||||||
|
* trace does not have its own setting.
|
||||||
|
*/
|
||||||
|
AutoMapSpec getAutoMapSpec(Trace trace);
|
||||||
|
}
|
@ -4,16 +4,16 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.action;
|
package ghidra.debug.api.action;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -21,15 +21,15 @@ import javax.swing.Icon;
|
|||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
|
||||||
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
|
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
@ -50,7 +50,7 @@ public interface AutoMapSpec extends ExtensionPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void classesChanged(ChangeEvent evt) {
|
private synchronized void classesChanged(ChangeEvent evt) {
|
||||||
MiscellaneousUtils.collectUniqueInstances(AutoMapSpec.class, specsByName,
|
InstanceUtils.collectUniqueInstances(AutoMapSpec.class, specsByName,
|
||||||
AutoMapSpec::getConfigName);
|
AutoMapSpec::getConfigName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,12 +87,18 @@ public interface AutoMapSpec extends ExtensionPoint {
|
|||||||
|
|
||||||
String getMenuName();
|
String getMenuName();
|
||||||
|
|
||||||
default Icon getMenuIcon() {
|
Icon getMenuIcon();
|
||||||
return DebuggerResources.ICON_CONFIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<TraceEvent<?, ?>> getChangeTypes();
|
Collection<TraceEvent<?, ?>> getChangeTypes();
|
||||||
|
|
||||||
|
boolean objectHasType(TraceObjectValue value);
|
||||||
|
|
||||||
|
String getInfoForObjects(Trace trace);
|
||||||
|
|
||||||
|
default boolean hasTask() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default String getTaskTitle() {
|
default String getTaskTitle() {
|
||||||
return getMenuName();
|
return getMenuName();
|
||||||
}
|
}
|
||||||
@ -119,6 +125,33 @@ public interface AutoMapSpec extends ExtensionPoint {
|
|||||||
tool.executeBackgroundCommand(cmd, trace);
|
tool.executeBackgroundCommand(cmd, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
List<Program> programs(ProgramManager programManager);
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException;
|
|
||||||
|
/**
|
||||||
|
* Perform the actual mapping
|
||||||
|
*
|
||||||
|
* @param mappingService the mapping service
|
||||||
|
* @param trace the trace
|
||||||
|
* @param programs the programs to consider
|
||||||
|
* @param monitor a task monitor
|
||||||
|
* @return true if any mappings were added
|
||||||
|
* @throws CancelledException if the task monitor cancelled the task
|
||||||
|
*/
|
||||||
|
boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
List<Program> programs, TaskMonitor monitor) throws CancelledException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the actual mapping
|
||||||
|
*
|
||||||
|
* @param mappingService the mapping service
|
||||||
|
* @param trace the trace
|
||||||
|
* @param programManager the program manager
|
||||||
|
* @param monitor a task monitor
|
||||||
|
* @return true if any mappings were added
|
||||||
|
* @throws CancelledException if the task monitor cancelled the task
|
||||||
|
*/
|
||||||
|
default boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
||||||
|
return performMapping(mappingService, trace, programs(programManager), monitor);
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.action;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
|
|
||||||
|
public class InstanceUtils {
|
||||||
|
public static <T> void collectUniqueInstances(Class<T> cls, Map<String, T> map,
|
||||||
|
Function<T, String> keyFunc) {
|
||||||
|
// This is wasteful. Existing instances will be re-instantiated and thrown away
|
||||||
|
for (T t : ClassSearcher.getInstances(cls)) {
|
||||||
|
String key = keyFunc.apply(t);
|
||||||
|
T exists = map.get(key);
|
||||||
|
if (exists != null) {
|
||||||
|
if (exists.getClass().equals(t.getClass())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Msg.error(LocationTrackingSpec.class,
|
||||||
|
cls.getSimpleName() + " conflict over key: " + key);
|
||||||
|
}
|
||||||
|
map.put(key, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -38,8 +38,9 @@ import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
|||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||||
import ghidra.dbg.util.ShellUtils;
|
import ghidra.dbg.util.ShellUtils;
|
||||||
import ghidra.debug.api.modules.*;
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.DebuggerMissingProgramActionContext;
|
||||||
|
import ghidra.debug.api.modules.DebuggerStaticMappingChangeListener;
|
||||||
import ghidra.debug.api.tracermi.*;
|
import ghidra.debug.api.tracermi.*;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.*;
|
import ghidra.framework.plugintool.AutoConfigState.*;
|
||||||
@ -50,7 +51,6 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.pty.*;
|
import ghidra.pty.*;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.TraceLocation;
|
import ghidra.trace.model.TraceLocation;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.Task;
|
import ghidra.util.task.Task;
|
||||||
@ -185,16 +185,31 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Collection<ModuleMapEntry> invokeMapper(TaskMonitor monitor,
|
protected boolean invokeMapper(TaskMonitor monitor, DebuggerStaticMappingService mappingService,
|
||||||
DebuggerStaticMappingService mappingService, Trace trace) throws CancelledException {
|
TraceRmiConnection connection, Trace trace, AutoMapSpec spec)
|
||||||
|
throws CancelledException {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
return List.of();
|
return false;
|
||||||
}
|
}
|
||||||
Map<TraceModule, ModuleMapProposal> map = mappingService
|
|
||||||
.proposeModuleMaps(trace.getModuleManager().getAllModules(), List.of(program));
|
if (spec.performMapping(mappingService, trace, List.of(program), monitor)) {
|
||||||
Collection<ModuleMapEntry> proposal = MapProposal.flatten(map.values());
|
return true;
|
||||||
mappingService.addModuleMappings(proposal, monitor, true);
|
}
|
||||||
return proposal;
|
|
||||||
|
try {
|
||||||
|
mappingService.changesSettled().get(1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
// Whatever, just check for the mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
Address probeAddress = getMappingProbeAddress();
|
||||||
|
if (probeAddress == null) {
|
||||||
|
return true; // Probably shouldn't happen, but if it does, say "success"
|
||||||
|
}
|
||||||
|
ProgramLocation probe = new ProgramLocation(program, probeAddress);
|
||||||
|
long snap = connection.getLastSnapshot(trace);
|
||||||
|
return mappingService.getOpenMappedLocation(trace, probe, snap) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SaveState saveLauncherArgsToState(Map<String, ?> args,
|
protected SaveState saveLauncherArgsToState(Map<String, ?> args,
|
||||||
@ -543,7 +558,9 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void initializeMonitor(TaskMonitor monitor) {
|
protected void initializeMonitor(TaskMonitor monitor) {
|
||||||
if (requiresImage()) {
|
DebuggerAutoMappingService auto = tool.getService(DebuggerAutoMappingService.class);
|
||||||
|
AutoMapSpec spec = auto.getAutoMapSpec();
|
||||||
|
if (requiresImage() && spec.hasTask()) {
|
||||||
monitor.setMaximum(6);
|
monitor.setMaximum(6);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -557,6 +574,11 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
|||||||
if (!requiresImage()) {
|
if (!requiresImage()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
DebuggerAutoMappingService auto = tool.getService(DebuggerAutoMappingService.class);
|
||||||
|
AutoMapSpec spec = auto.getAutoMapSpec(trace);
|
||||||
|
if (!spec.hasTask()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
DebuggerStaticMappingService mappingService =
|
DebuggerStaticMappingService mappingService =
|
||||||
tool.getService(DebuggerStaticMappingService.class);
|
tool.getService(DebuggerStaticMappingService.class);
|
||||||
monitor.setMessage("Waiting for module mapping");
|
monitor.setMessage("Waiting for module mapping");
|
||||||
@ -567,14 +589,14 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
|||||||
catch (TimeoutException e) {
|
catch (TimeoutException e) {
|
||||||
monitor.setMessage(
|
monitor.setMessage(
|
||||||
"Timed out waiting for module mapping. Invoking the mapper.");
|
"Timed out waiting for module mapping. Invoking the mapper.");
|
||||||
Collection<ModuleMapEntry> mapped;
|
boolean mapped;
|
||||||
try {
|
try {
|
||||||
mapped = invokeMapper(monitor, mappingService, trace);
|
mapped = invokeMapper(monitor, mappingService, connection, trace, spec);
|
||||||
}
|
}
|
||||||
catch (CancelledException ce) {
|
catch (CancelledException ce) {
|
||||||
throw new CancellationException(e.getMessage());
|
throw new CancellationException(e.getMessage());
|
||||||
}
|
}
|
||||||
if (mapped.isEmpty()) {
|
if (!mapped) {
|
||||||
throw new NoStaticMappingException(
|
throw new NoStaticMappingException(
|
||||||
"The resulting target process has no mapping to the static image.");
|
"The resulting target process has no mapping to the static image.");
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -25,7 +25,7 @@ import javax.swing.event.ChangeEvent;
|
|||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.gui.control.TargetActionTask;
|
import ghidra.app.plugin.core.debug.gui.control.TargetActionTask;
|
||||||
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
|
import ghidra.debug.api.action.InstanceUtils;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
||||||
@ -49,7 +49,7 @@ public interface AutoReadMemorySpec extends ExtensionPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void classesChanged(ChangeEvent evt) {
|
private synchronized void classesChanged(ChangeEvent evt) {
|
||||||
MiscellaneousUtils.collectUniqueInstances(AutoReadMemorySpec.class, specsByName,
|
InstanceUtils.collectUniqueInstances(AutoReadMemorySpec.class, specsByName,
|
||||||
AutoReadMemorySpec::getConfigName);
|
AutoReadMemorySpec::getConfigName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -16,14 +16,22 @@
|
|||||||
package ghidra.app.plugin.core.debug.gui.action;
|
package ghidra.app.plugin.core.debug.gui.action;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.MapProposal;
|
import ghidra.debug.api.modules.MapProposal;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal;
|
import ghidra.debug.api.modules.ModuleMapProposal;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
|
import ghidra.trace.model.modules.TraceObjectModule;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.trace.util.TraceEvents;
|
import ghidra.trace.util.TraceEvents;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@ -42,6 +50,11 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
|
|||||||
return "Auto-Map by Module";
|
return "Auto-Map by Module";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getMenuIcon() {
|
||||||
|
return DebuggerResources.ICON_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
||||||
return List.of(
|
return List.of(
|
||||||
@ -50,13 +63,36 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
public boolean objectHasType(TraceObjectValue value) {
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
return value.getParent().queryInterface(TraceObjectModule.class) != null ||
|
||||||
List<Program> programs = Arrays.asList(programManager.getAllOpenPrograms());
|
value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInfoForObjects(Trace trace) {
|
||||||
|
String modPart = trace.getModuleManager()
|
||||||
|
.getAllModules()
|
||||||
|
.stream()
|
||||||
|
.map(m -> m.getName() + ":" + m.getBase())
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
String regPart = ByRegionAutoMapSpec.getInfoForRegions(trace);
|
||||||
|
return modPart + ";" + regPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Program> programs(ProgramManager programManager) {
|
||||||
|
return Arrays.asList(programManager.getAllOpenPrograms());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
List<Program> programs, TaskMonitor monitor) throws CancelledException {
|
||||||
Map<?, ModuleMapProposal> maps = mappingService
|
Map<?, ModuleMapProposal> maps = mappingService
|
||||||
.proposeModuleMaps(trace.getModuleManager().getAllModules(), programs);
|
.proposeModuleMaps(trace.getModuleManager().getAllModules(), programs);
|
||||||
Collection<ModuleMapEntry> entries = MapProposal.flatten(maps.values());
|
Collection<ModuleMapEntry> entries = MapProposal.flatten(maps.values());
|
||||||
entries = MapProposal.removeOverlapping(entries);
|
entries = MapProposal.removeOverlapping(entries);
|
||||||
mappingService.addModuleMappings(entries, monitor, false);
|
mappingService.addModuleMappings(entries, monitor, false);
|
||||||
|
return !entries.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -16,14 +16,21 @@
|
|||||||
package ghidra.app.plugin.core.debug.gui.action;
|
package ghidra.app.plugin.core.debug.gui.action;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.MapProposal;
|
import ghidra.debug.api.modules.MapProposal;
|
||||||
import ghidra.debug.api.modules.RegionMapProposal;
|
import ghidra.debug.api.modules.RegionMapProposal;
|
||||||
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.trace.util.TraceEvents;
|
import ghidra.trace.util.TraceEvents;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@ -42,19 +49,48 @@ public class ByRegionAutoMapSpec implements AutoMapSpec {
|
|||||||
return "Auto-Map by Region";
|
return "Auto-Map by Region";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getMenuIcon() {
|
||||||
|
return DebuggerResources.ICON_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
||||||
return List.of(TraceEvents.REGION_ADDED);
|
return List.of(TraceEvents.REGION_ADDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
public boolean objectHasType(TraceObjectValue value) {
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
return value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null;
|
||||||
List<Program> programs = Arrays.asList(programManager.getAllOpenPrograms());
|
}
|
||||||
|
|
||||||
|
static String getInfoForRegions(Trace trace) {
|
||||||
|
return trace.getMemoryManager()
|
||||||
|
.getAllRegions()
|
||||||
|
.stream()
|
||||||
|
.map(r -> r.getName() + ":" + r.getMinAddress())
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInfoForObjects(Trace trace) {
|
||||||
|
return getInfoForRegions(trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Program> programs(ProgramManager programManager) {
|
||||||
|
return Arrays.asList(programManager.getAllOpenPrograms());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
List<Program> programs, TaskMonitor monitor) throws CancelledException {
|
||||||
Map<?, RegionMapProposal> maps = mappingService
|
Map<?, RegionMapProposal> maps = mappingService
|
||||||
.proposeRegionMaps(trace.getMemoryManager().getAllRegions(), programs);
|
.proposeRegionMaps(trace.getMemoryManager().getAllRegions(), programs);
|
||||||
Collection<RegionMapEntry> entries = MapProposal.flatten(maps.values());
|
Collection<RegionMapEntry> entries = MapProposal.flatten(maps.values());
|
||||||
entries = MapProposal.removeOverlapping(entries);
|
entries = MapProposal.removeOverlapping(entries);
|
||||||
mappingService.addRegionMappings(entries, monitor, false);
|
mappingService.addRegionMappings(entries, monitor, false);
|
||||||
|
return !entries.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -16,14 +16,21 @@
|
|||||||
package ghidra.app.plugin.core.debug.gui.action;
|
package ghidra.app.plugin.core.debug.gui.action;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.MapProposal;
|
import ghidra.debug.api.modules.MapProposal;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal;
|
import ghidra.debug.api.modules.SectionMapProposal;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.trace.database.module.TraceObjectSection;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.trace.util.TraceEvents;
|
import ghidra.trace.util.TraceEvents;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@ -42,19 +49,44 @@ public class BySectionAutoMapSpec implements AutoMapSpec {
|
|||||||
return "Auto-Map by Section";
|
return "Auto-Map by Section";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getMenuIcon() {
|
||||||
|
return DebuggerResources.ICON_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
||||||
return List.of(TraceEvents.SECTION_ADDED);
|
return List.of(TraceEvents.SECTION_ADDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
public boolean objectHasType(TraceObjectValue value) {
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
return value.getParent().queryInterface(TraceObjectSection.class) != null;
|
||||||
List<Program> programs = Arrays.asList(programManager.getAllOpenPrograms());
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInfoForObjects(Trace trace) {
|
||||||
|
return trace.getModuleManager()
|
||||||
|
.getAllSections()
|
||||||
|
.stream()
|
||||||
|
.map(s -> s.getName() + ":" + s.getStart())
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Program> programs(ProgramManager programManager) {
|
||||||
|
return Arrays.asList(programManager.getAllOpenPrograms());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
List<Program> programs, TaskMonitor monitor) throws CancelledException {
|
||||||
Map<?, SectionMapProposal> maps = mappingService
|
Map<?, SectionMapProposal> maps = mappingService
|
||||||
.proposeSectionMaps(trace.getModuleManager().getAllModules(), programs);
|
.proposeSectionMaps(trace.getModuleManager().getAllModules(), programs);
|
||||||
Collection<SectionMapEntry> entries = MapProposal.flatten(maps.values());
|
Collection<SectionMapEntry> entries = MapProposal.flatten(maps.values());
|
||||||
entries = MapProposal.removeOverlapping(entries);
|
entries = MapProposal.removeOverlapping(entries);
|
||||||
mappingService.addSectionMappings(entries, monitor, false);
|
mappingService.addSectionMappings(entries, monitor, false);
|
||||||
|
return !entries.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -18,10 +18,16 @@ package ghidra.app.plugin.core.debug.gui.action;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@ -39,18 +45,44 @@ public class NoneAutoMapSpec implements AutoMapSpec {
|
|||||||
return "Do Not Auto-Map";
|
return "Do Not Auto-Map";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getMenuIcon() {
|
||||||
|
return DebuggerResources.ICON_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean objectHasType(TraceObjectValue value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInfoForObjects(Trace trace) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTask() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runTask(PluginTool tool, Trace trace) {
|
public void runTask(PluginTool tool, Trace trace) {
|
||||||
// Don't bother launching a task that does nothing
|
// Don't bother launching a task that does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
public List<Program> programs(ProgramManager programManager) {
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
|
List<Program> programs, TaskMonitor monitor) throws CancelledException {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -18,12 +18,17 @@ package ghidra.app.plugin.core.debug.gui.action;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.modules.TraceConflictedMappingException;
|
import ghidra.trace.model.modules.TraceConflictedMappingException;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@ -41,24 +46,49 @@ public class OneToOneAutoMapSpec implements AutoMapSpec {
|
|||||||
return "Auto-Map Identically (1-to-1)";
|
return "Auto-Map Identically (1-to-1)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getMenuIcon() {
|
||||||
|
return DebuggerResources.ICON_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
public Collection<TraceEvent<?, ?>> getChangeTypes() {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
public boolean objectHasType(TraceObjectValue value) {
|
||||||
ProgramManager programManager, TaskMonitor monitor) throws CancelledException {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInfoForObjects(Trace trace) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Program> programs(ProgramManager programManager) {
|
||||||
Program program = programManager.getCurrentProgram();
|
Program program = programManager.getCurrentProgram();
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
return;
|
return List.of();
|
||||||
}
|
}
|
||||||
try {
|
return List.of(program);
|
||||||
mappingService.addIdentityMapping(trace, program,
|
}
|
||||||
Lifespan.nowOn(trace.getProgramView().getSnap()), false);
|
|
||||||
}
|
@Override
|
||||||
catch (TraceConflictedMappingException e) {
|
public boolean performMapping(DebuggerStaticMappingService mappingService, Trace trace,
|
||||||
// aww well
|
List<Program> programs, TaskMonitor monitor) throws CancelledException {
|
||||||
|
boolean result = false;
|
||||||
|
for (Program program : programs) {
|
||||||
|
try {
|
||||||
|
mappingService.addIdentityMapping(trace, program,
|
||||||
|
Lifespan.nowOn(trace.getProgramView().getSnap()), false);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
catch (TraceConflictedMappingException e) {
|
||||||
|
// aww well
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -19,11 +19,11 @@ import ghidra.app.events.*;
|
|||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.core.debug.AbstractDebuggerPlugin;
|
import ghidra.app.plugin.core.debug.AbstractDebuggerPlugin;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||||
import ghidra.app.plugin.core.debug.event.TraceActivatedPluginEvent;
|
import ghidra.app.plugin.core.debug.event.*;
|
||||||
import ghidra.app.plugin.core.debug.event.TraceClosedPluginEvent;
|
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
|
import ghidra.framework.plugintool.annotation.AutoServiceProvided;
|
||||||
import ghidra.framework.plugintool.util.PluginStatus;
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
|
|
||||||
@PluginInfo(
|
@PluginInfo(
|
||||||
@ -37,6 +37,7 @@ import ghidra.framework.plugintool.util.PluginStatus;
|
|||||||
ProgramActivatedPluginEvent.class,
|
ProgramActivatedPluginEvent.class,
|
||||||
ProgramLocationPluginEvent.class,
|
ProgramLocationPluginEvent.class,
|
||||||
ProgramClosedPluginEvent.class,
|
ProgramClosedPluginEvent.class,
|
||||||
|
TraceOpenedPluginEvent.class,
|
||||||
TraceActivatedPluginEvent.class,
|
TraceActivatedPluginEvent.class,
|
||||||
TraceClosedPluginEvent.class,
|
TraceClosedPluginEvent.class,
|
||||||
},
|
},
|
||||||
@ -44,8 +45,13 @@ import ghidra.framework.plugintool.util.PluginStatus;
|
|||||||
DebuggerStaticMappingService.class,
|
DebuggerStaticMappingService.class,
|
||||||
DebuggerTraceManagerService.class,
|
DebuggerTraceManagerService.class,
|
||||||
ProgramManager.class,
|
ProgramManager.class,
|
||||||
|
},
|
||||||
|
servicesProvided = {
|
||||||
|
DebuggerAutoMappingService.class,
|
||||||
})
|
})
|
||||||
public class DebuggerModulesPlugin extends AbstractDebuggerPlugin {
|
public class DebuggerModulesPlugin extends AbstractDebuggerPlugin {
|
||||||
|
|
||||||
|
@AutoServiceProvided(iface = DebuggerAutoMappingService.class)
|
||||||
protected DebuggerModulesProvider provider;
|
protected DebuggerModulesProvider provider;
|
||||||
|
|
||||||
public DebuggerModulesPlugin(PluginTool tool) {
|
public DebuggerModulesPlugin(PluginTool tool) {
|
||||||
@ -68,23 +74,17 @@ public class DebuggerModulesPlugin extends AbstractDebuggerPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void processEvent(PluginEvent event) {
|
public void processEvent(PluginEvent event) {
|
||||||
super.processEvent(event);
|
super.processEvent(event);
|
||||||
if (event instanceof ProgramOpenedPluginEvent ev) {
|
switch (event) {
|
||||||
provider.programOpened(ev.getProgram());
|
case ProgramOpenedPluginEvent ev -> provider.programOpened(ev.getProgram());
|
||||||
}
|
case ProgramActivatedPluginEvent ev -> provider.setProgram(ev.getActiveProgram());
|
||||||
else if (event instanceof ProgramActivatedPluginEvent ev) {
|
case ProgramLocationPluginEvent ev -> provider.setLocation(ev.getLocation());
|
||||||
provider.setProgram(ev.getActiveProgram());
|
case ProgramClosedPluginEvent ev -> provider.programClosed(ev.getProgram());
|
||||||
}
|
case TraceOpenedPluginEvent ev -> provider.traceOpened(ev.getTrace());
|
||||||
else if (event instanceof ProgramLocationPluginEvent ev) {
|
case TraceActivatedPluginEvent ev -> provider
|
||||||
provider.setLocation(ev.getLocation());
|
.coordinatesActivated(ev.getActiveCoordinates());
|
||||||
}
|
case TraceClosedPluginEvent ev -> provider.traceClosed(ev.getTrace());
|
||||||
else if (event instanceof ProgramClosedPluginEvent ev) {
|
default -> {
|
||||||
provider.programClosed(ev.getProgram());
|
}
|
||||||
}
|
|
||||||
else if (event instanceof TraceActivatedPluginEvent ev) {
|
|
||||||
provider.coordinatesActivated(ev.getActiveCoordinates());
|
|
||||||
}
|
|
||||||
else if (event instanceof TraceClosedPluginEvent ev) {
|
|
||||||
provider.traceClosed(ev.getTrace());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.modules;
|
package ghidra.app.plugin.core.debug.gui.modules;
|
||||||
|
|
||||||
import static ghidra.framework.main.DataTreeDialogType.*;
|
import static ghidra.framework.main.DataTreeDialogType.OPEN;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -40,18 +40,18 @@ import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
|||||||
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog;
|
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||||
import ghidra.app.plugin.core.debug.gui.action.AutoMapSpec;
|
|
||||||
import ghidra.app.plugin.core.debug.gui.action.AutoMapSpec.AutoMapSpecConfigFieldCodec;
|
|
||||||
import ghidra.app.plugin.core.debug.gui.action.ByModuleAutoMapSpec;
|
import ghidra.app.plugin.core.debug.gui.action.ByModuleAutoMapSpec;
|
||||||
import ghidra.app.plugin.core.debug.service.model.TraceRecorderTarget;
|
|
||||||
import ghidra.app.plugin.core.debug.service.modules.MapModulesBackgroundCommand;
|
import ghidra.app.plugin.core.debug.service.modules.MapModulesBackgroundCommand;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.MapSectionsBackgroundCommand;
|
import ghidra.app.plugin.core.debug.service.modules.MapSectionsBackgroundCommand;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec.AutoMapSpecConfigFieldCodec;
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.debug.api.modules.*;
|
import ghidra.debug.api.modules.*;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
|
import ghidra.framework.data.DomainObjectAdapterDB;
|
||||||
import ghidra.framework.main.AppInfo;
|
import ghidra.framework.main.AppInfo;
|
||||||
import ghidra.framework.main.DataTreeDialog;
|
import ghidra.framework.main.DataTreeDialog;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
@ -68,11 +68,14 @@ import ghidra.program.util.ProgramSelection;
|
|||||||
import ghidra.trace.model.*;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.modules.*;
|
import ghidra.trace.model.modules.*;
|
||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.util.TraceEvent;
|
import ghidra.trace.util.TraceEvent;
|
||||||
import ghidra.trace.util.TraceEvents;
|
import ghidra.trace.util.TraceEvents;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
|
||||||
public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
public class DebuggerModulesProvider extends ComponentProviderAdapter
|
||||||
|
implements DebuggerAutoMappingService {
|
||||||
|
|
||||||
protected static final AutoConfigState.ClassHandler<DebuggerModulesProvider> CONFIG_STATE_HANDLER =
|
protected static final AutoConfigState.ClassHandler<DebuggerModulesProvider> CONFIG_STATE_HANDLER =
|
||||||
AutoConfigState.wireHandler(DebuggerModulesProvider.class, MethodHandles.lookup());
|
AutoConfigState.wireHandler(DebuggerModulesProvider.class, MethodHandles.lookup());
|
||||||
|
|
||||||
@ -336,27 +339,82 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class ForMappingTraceListener extends TraceDomainObjectListener {
|
protected static class AutoMapState extends TraceDomainObjectListener
|
||||||
public ForMappingTraceListener(AutoMapSpec spec) {
|
implements TransactionListener {
|
||||||
|
|
||||||
|
private final PluginTool tool;
|
||||||
|
private final Trace trace;
|
||||||
|
private final AutoMapSpec spec;
|
||||||
|
private volatile boolean couldHaveChanged = true;
|
||||||
|
private volatile String infosLastTime = "";
|
||||||
|
|
||||||
|
public AutoMapState(PluginTool tool, Trace trace, AutoMapSpec spec) {
|
||||||
|
this.tool = tool;
|
||||||
|
this.trace = trace;
|
||||||
|
this.spec = spec;
|
||||||
for (TraceEvent<?, ?> type : spec.getChangeTypes()) {
|
for (TraceEvent<?, ?> type : spec.getChangeTypes()) {
|
||||||
listenFor(type, this::changed);
|
listenFor(type, this::changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete this if/when TraceRecorderTarget is removed
|
listenFor(TraceEvents.VALUE_CREATED, this::valueCreated);
|
||||||
listenFor(TraceEvents.BYTES_CHANGED, this::memoryChanged);
|
listenForUntyped(DomainObjectEvent.RESTORED, this::objectRestored);
|
||||||
|
|
||||||
|
trace.addListener(this);
|
||||||
|
trace.addTransactionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
trace.removeListener(this);
|
||||||
|
trace.removeTransactionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changed() {
|
private void changed() {
|
||||||
cueAutoMap = true;
|
couldHaveChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void memoryChanged(TraceAddressSnapRange range) {
|
private void valueCreated(TraceObjectValue value) {
|
||||||
if (range.getRange().getAddressSpace().isRegisterSpace()) {
|
couldHaveChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void objectRestored(DomainObjectChangeRecord rec) {
|
||||||
|
couldHaveChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transactionStarted(DomainObjectAdapterDB domainObj, TransactionInfo tx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transactionEnded(DomainObjectAdapterDB domainObj) {
|
||||||
|
checkAutoMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoStackChanged(DomainObjectAdapterDB domainObj) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoRedoOccurred(DomainObjectAdapterDB domainObj) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAutoMap() {
|
||||||
|
if (!couldHaveChanged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (current.getTarget() instanceof TraceRecorderTarget) {
|
couldHaveChanged = false;
|
||||||
doCuedAutoMap();
|
String infosThisTime = spec.getInfoForObjects(trace);
|
||||||
|
if (Objects.equals(infosThisTime, infosLastTime)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
infosLastTime = infosThisTime;
|
||||||
|
|
||||||
|
spec.runTask(tool, trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceMap() {
|
||||||
|
couldHaveChanged = true;
|
||||||
|
infosLastTime = "";
|
||||||
|
checkAutoMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,8 +592,8 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
@AutoConfigStateField
|
@AutoConfigStateField
|
||||||
boolean filterSectionsByModules = false;
|
boolean filterSectionsByModules = false;
|
||||||
|
|
||||||
boolean cueAutoMap;
|
private final Map<Trace, AutoMapState> autoMapStateByTrace = new WeakHashMap<>();
|
||||||
private ForMappingTraceListener forMappingListener;
|
private AutoMapState forMappingListener;
|
||||||
|
|
||||||
DockingAction actionImportMissingModule;
|
DockingAction actionImportMissingModule;
|
||||||
DockingAction actionMapMissingModule;
|
DockingAction actionMapMissingModule;
|
||||||
@ -612,6 +670,10 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void dispose() {
|
protected void dispose() {
|
||||||
|
for (AutoMapState state : autoMapStateByTrace.values()) {
|
||||||
|
state.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
if (consoleService != null) {
|
if (consoleService != null) {
|
||||||
removeResolutionActionMaybe(consoleService, actionImportMissingModule);
|
removeResolutionActionMaybe(consoleService, actionImportMissingModule);
|
||||||
removeResolutionActionMaybe(consoleService, actionMapMissingModule);
|
removeResolutionActionMaybe(consoleService, actionMapMissingModule);
|
||||||
@ -885,12 +947,20 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doSetAutoMapSpec(AutoMapSpec autoMapSpec) {
|
private void doSetAutoMapSpec(AutoMapSpec autoMapSpec) {
|
||||||
if (this.autoMapSpec == autoMapSpec) {
|
this.autoMapSpec = autoMapSpec;
|
||||||
|
|
||||||
|
Trace trace = current.getTrace();
|
||||||
|
if (trace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeOldTraceListener();
|
AutoMapState state = autoMapStateByTrace.remove(trace);
|
||||||
this.autoMapSpec = autoMapSpec;
|
if (state != null && state.spec.equals(autoMapSpec)) {
|
||||||
addNewTraceListener();
|
autoMapStateByTrace.put(trace, state);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state.dispose();
|
||||||
|
autoMapStateByTrace.put(trace, new AutoMapState(tool, trace, autoMapSpec));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activatedImportMissingModule(DebuggerMissingModuleActionContext context) {
|
private void activatedImportMissingModule(DebuggerMissingModuleActionContext context) {
|
||||||
@ -1256,9 +1326,14 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void programOpened(Program program) {
|
public void programOpened(Program program) {
|
||||||
|
AutoMapState mapState = autoMapStateByTrace.get(current.getTrace());
|
||||||
|
// TODO: All open traces, or just the current one?
|
||||||
|
if (mapState == null) {
|
||||||
|
// Could be, e.g., current is NOWHERE
|
||||||
|
return;
|
||||||
|
}
|
||||||
// TODO: Debounce this?
|
// TODO: Debounce this?
|
||||||
cueAutoMap = true;
|
mapState.forceMap();
|
||||||
doCuedAutoMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void programClosed(Program program) {
|
public void programClosed(Program program) {
|
||||||
@ -1268,43 +1343,38 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
cleanMissingProgramMessages(null, program);
|
cleanMissingProgramMessages(null, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void traceOpened(Trace trace) {
|
||||||
|
autoMapStateByTrace.computeIfAbsent(trace, t -> new AutoMapState(tool, trace, autoMapSpec));
|
||||||
|
}
|
||||||
|
|
||||||
public void traceClosed(Trace trace) {
|
public void traceClosed(Trace trace) {
|
||||||
|
AutoMapState state = autoMapStateByTrace.remove(trace);
|
||||||
|
if (state != null) {
|
||||||
|
state.dispose();
|
||||||
|
}
|
||||||
cleanMissingProgramMessages(trace, null);
|
cleanMissingProgramMessages(trace, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addNewTraceListener() {
|
|
||||||
if (current.getTrace() != null && autoMapSpec != null) {
|
|
||||||
forMappingListener = new ForMappingTraceListener(autoMapSpec);
|
|
||||||
current.getTrace().addListener(forMappingListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeOldTraceListener() {
|
|
||||||
if (forMappingListener != null) {
|
|
||||||
if (current.getTrace() != null) {
|
|
||||||
current.getTrace().removeListener(forMappingListener);
|
|
||||||
}
|
|
||||||
forMappingListener = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void coordinatesActivated(DebuggerCoordinates coordinates) {
|
public void coordinatesActivated(DebuggerCoordinates coordinates) {
|
||||||
if (sameCoordinates(current, coordinates)) {
|
if (sameCoordinates(current, coordinates)) {
|
||||||
current = coordinates;
|
current = coordinates;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean changeTrace = current.getTrace() != coordinates.getTrace();
|
Trace newTrace = coordinates.getTrace();
|
||||||
|
boolean changeTrace = current.getTrace() != newTrace;
|
||||||
if (changeTrace) {
|
if (changeTrace) {
|
||||||
myActionContext = null;
|
myActionContext = null;
|
||||||
removeOldTraceListener();
|
|
||||||
}
|
}
|
||||||
current = coordinates;
|
current = coordinates;
|
||||||
if (changeTrace) {
|
|
||||||
addNewTraceListener();
|
AutoMapState amState = autoMapStateByTrace.get(newTrace);
|
||||||
|
if (amState != null) {
|
||||||
|
// Can't just set field directly. Want GUI update.
|
||||||
|
setAutoMapSpec(amState.spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Trace.isLegacy(coordinates.getTrace())) {
|
if (Trace.isLegacy(newTrace)) {
|
||||||
modulesPanel.coordinatesActivated(DebuggerCoordinates.NOWHERE);
|
modulesPanel.coordinatesActivated(DebuggerCoordinates.NOWHERE);
|
||||||
sectionsPanel.coordinatesActivated(DebuggerCoordinates.NOWHERE);
|
sectionsPanel.coordinatesActivated(DebuggerCoordinates.NOWHERE);
|
||||||
legacyModulesPanel.coordinatesActivated(coordinates);
|
legacyModulesPanel.coordinatesActivated(coordinates);
|
||||||
@ -1332,22 +1402,6 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contextChanged();
|
contextChanged();
|
||||||
|
|
||||||
if (coordinates.getTarget() instanceof TraceRecorderTarget) {
|
|
||||||
// HACK while TraceRecorderTarget is still around
|
|
||||||
cueAutoMap = true;
|
|
||||||
}
|
|
||||||
doCuedAutoMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCuedAutoMap() {
|
|
||||||
if (cueAutoMap) {
|
|
||||||
cueAutoMap = false;
|
|
||||||
Trace trace = current.getTrace();
|
|
||||||
if (autoMapSpec != null && trace != null) {
|
|
||||||
autoMapSpec.runTask(tool, trace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedModules(Set<TraceModule> sel) {
|
public void setSelectedModules(Set<TraceModule> sel) {
|
||||||
@ -1398,10 +1452,17 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
actionAutoMap.setCurrentActionStateByUserData(spec);
|
actionAutoMap.setCurrentActionStateByUserData(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AutoMapSpec getAutoMapSpec() {
|
public AutoMapSpec getAutoMapSpec() {
|
||||||
return autoMapSpec;
|
return autoMapSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AutoMapSpec getAutoMapSpec(Trace trace) {
|
||||||
|
AutoMapState state = autoMapStateByTrace.get(trace);
|
||||||
|
return state == null ? autoMapSpec : state.spec;
|
||||||
|
}
|
||||||
|
|
||||||
public void writeConfigState(SaveState saveState) {
|
public void writeConfigState(SaveState saveState) {
|
||||||
CONFIG_STATE_HANDLER.writeConfigState(this, saveState);
|
CONFIG_STATE_HANDLER.writeConfigState(this, saveState);
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -253,12 +253,15 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
|
|
||||||
private void objectRestored() {
|
private void objectRestored() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
Set<Program> fromClosure = collectAffectedByTrace(trace);
|
||||||
var old = Map.copyOf(outbound);
|
var old = Map.copyOf(outbound);
|
||||||
outbound.clear();
|
clearOutboundEntries();
|
||||||
loadOutboundEntries(); // Also places/updates corresponding inbound entries
|
loadOutboundEntries(); // Also places corresponding inbound entries
|
||||||
if (!old.equals(outbound)) {
|
if (!old.equals(outbound)) {
|
||||||
// TODO: What about removed corresponding inbound entries?
|
if (!fromClosure.isEmpty()) {
|
||||||
doAffectedByTraceClosed(trace);
|
traceAffected(trace);
|
||||||
|
}
|
||||||
|
programsAffected(fromClosure);
|
||||||
doAffectedByTraceOpened(trace);
|
doAffectedByTraceOpened(trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,9 +312,7 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
destInfo.inbound.put(me, me.getStaticAddress());
|
destInfo.inbound.put(me, me.getStaticAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeOutboundAndInboundEntries(MappingEntry me) {
|
protected void removeInboundEntryFor(MappingEntry me) {
|
||||||
outbound.remove(me.getTraceAddressSnapRange());
|
|
||||||
|
|
||||||
InfoPerProgram destInfo = trackedProgramInfo.get(me.getStaticProgramURL());
|
InfoPerProgram destInfo = trackedProgramInfo.get(me.getStaticProgramURL());
|
||||||
if (destInfo == null) {
|
if (destInfo == null) {
|
||||||
return; // Not opened
|
return; // Not opened
|
||||||
@ -319,6 +320,11 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
destInfo.inbound.remove(me);
|
destInfo.inbound.remove(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeOutboundAndInboundEntries(MappingEntry me) {
|
||||||
|
outbound.remove(me.getTraceAddressSnapRange());
|
||||||
|
removeInboundEntryFor(me);
|
||||||
|
}
|
||||||
|
|
||||||
protected void loadOutboundEntries() {
|
protected void loadOutboundEntries() {
|
||||||
TraceStaticMappingManager manager = trace.getStaticMappingManager();
|
TraceStaticMappingManager manager = trace.getStaticMappingManager();
|
||||||
for (TraceStaticMapping mapping : manager.getAllEntries()) {
|
for (TraceStaticMapping mapping : manager.getAllEntries()) {
|
||||||
@ -326,6 +332,13 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void clearOutboundEntries() {
|
||||||
|
for (MappingEntry me : outbound.values()) {
|
||||||
|
removeInboundEntryFor(me);
|
||||||
|
}
|
||||||
|
outbound.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean programOpened(Program other, InfoPerProgram otherInfo) {
|
public boolean programOpened(Program other, InfoPerProgram otherInfo) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
for (MappingEntry me : outbound.values()) {
|
for (MappingEntry me : outbound.values()) {
|
||||||
@ -347,8 +360,14 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
|
|
||||||
public Set<Program> getOpenMappedProgramsAtSnap(long snap) {
|
public Set<Program> getOpenMappedProgramsAtSnap(long snap) {
|
||||||
Set<Program> result = new HashSet<>();
|
Set<Program> result = new HashSet<>();
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
||||||
MappingEntry me = out.getValue();
|
MappingEntry me = out.getValue();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!me.isStaticProgramOpen()) {
|
if (!me.isStaticProgramOpen()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -357,27 +376,42 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
result.add(me.program);
|
result.add(me.program);
|
||||||
}
|
}
|
||||||
|
outbound.values().removeAll(toClean);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramLocation getOpenMappedLocations(Address address, Lifespan span) {
|
public ProgramLocation getOpenMappedLocations(Address address, Lifespan span) {
|
||||||
TraceAddressSnapRange at = new ImmutableTraceAddressSnapRange(address, span);
|
TraceAddressSnapRange at = new ImmutableTraceAddressSnapRange(address, span);
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
||||||
if (out.getKey().intersects(at)) {
|
if (out.getKey().intersects(at)) {
|
||||||
MappingEntry me = out.getValue();
|
MappingEntry me = out.getValue();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (me.isStaticProgramOpen()) {
|
if (me.isStaticProgramOpen()) {
|
||||||
|
outbound.values().removeAll(toClean);
|
||||||
return me.mapTraceAddressToProgramLocation(address);
|
return me.mapTraceAddressToProgramLocation(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
outbound.values().removeAll(toClean);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void collectOpenMappedPrograms(AddressRange rng, Lifespan span,
|
protected void collectOpenMappedPrograms(AddressRange rng, Lifespan span,
|
||||||
Map<Program, Collection<MappedAddressRange>> result) {
|
Map<Program, Collection<MappedAddressRange>> result) {
|
||||||
TraceAddressSnapRange tatr = new ImmutableTraceAddressSnapRange(rng, span);
|
TraceAddressSnapRange tatr = new ImmutableTraceAddressSnapRange(rng, span);
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
||||||
MappingEntry me = out.getValue();
|
MappingEntry me = out.getValue();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (me.program == null) {
|
if (me.program == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -389,6 +423,7 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
result.computeIfAbsent(me.program, p -> new TreeSet<>())
|
result.computeIfAbsent(me.program, p -> new TreeSet<>())
|
||||||
.add(new MappedAddressRange(srcRng, dstRng));
|
.add(new MappedAddressRange(srcRng, dstRng));
|
||||||
}
|
}
|
||||||
|
outbound.values().removeAll(toClean);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Program, Collection<MappedAddressRange>> getOpenMappedViews(AddressSetView set,
|
public Map<Program, Collection<MappedAddressRange>> getOpenMappedViews(AddressSetView set,
|
||||||
@ -402,14 +437,21 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
|
|
||||||
protected void collectMappedProgramURLsInView(AddressRange rng, Lifespan span,
|
protected void collectMappedProgramURLsInView(AddressRange rng, Lifespan span,
|
||||||
Set<URL> result) {
|
Set<URL> result) {
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
TraceAddressSnapRange tatr = new ImmutableTraceAddressSnapRange(rng, span);
|
TraceAddressSnapRange tatr = new ImmutableTraceAddressSnapRange(rng, span);
|
||||||
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
for (Entry<TraceAddressSnapRange, MappingEntry> out : outbound.entrySet()) {
|
||||||
|
MappingEntry me = out.getValue();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!out.getKey().intersects(tatr)) {
|
if (!out.getKey().intersects(tatr)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MappingEntry me = out.getValue();
|
|
||||||
result.add(me.getStaticProgramURL());
|
result.add(me.getStaticProgramURL());
|
||||||
}
|
}
|
||||||
|
outbound.values().removeAll(toClean);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<URL> getMappedProgramURLsInView(AddressSetView set, Lifespan span) {
|
public Set<URL> getMappedProgramURLsInView(AddressSetView set, Lifespan span) {
|
||||||
@ -455,11 +497,19 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMappedInTrace(Trace trace) {
|
public boolean isMappedInTrace(Trace trace) {
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (MappingEntry me : inbound.keySet()) {
|
for (MappingEntry me : inbound.keySet()) {
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (Objects.equals(trace, me.getTrace())) {
|
if (Objects.equals(trace, me.getTrace())) {
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,30 +526,43 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
|
|
||||||
public Set<TraceLocation> getOpenMappedTraceLocations(Address address) {
|
public Set<TraceLocation> getOpenMappedTraceLocations(Address address) {
|
||||||
Set<TraceLocation> result = new HashSet<>();
|
Set<TraceLocation> result = new HashSet<>();
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<MappingEntry, Address> inPreceding : inbound.headMapByValue(address, true)
|
for (Entry<MappingEntry, Address> inPreceding : inbound.headMapByValue(address, true)
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
|
MappingEntry me = inPreceding.getKey();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Address start = inPreceding.getValue();
|
Address start = inPreceding.getValue();
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MappingEntry me = inPreceding.getKey();
|
|
||||||
if (!me.isInProgramRange(address)) {
|
if (!me.isInProgramRange(address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.add(me.mapProgramAddressToTraceLocation(address));
|
result.add(me.mapProgramAddressToTraceLocation(address));
|
||||||
}
|
}
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceLocation getOpenMappedTraceLocation(Trace trace, Address address, long snap) {
|
public TraceLocation getOpenMappedTraceLocation(Trace trace, Address address, long snap) {
|
||||||
// TODO: Map by trace?
|
// TODO: Map by trace?
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<MappingEntry, Address> inPreceding : inbound.headMapByValue(address, true)
|
for (Entry<MappingEntry, Address> inPreceding : inbound.headMapByValue(address, true)
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
|
MappingEntry me = inPreceding.getKey();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Address start = inPreceding.getValue();
|
Address start = inPreceding.getValue();
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MappingEntry me = inPreceding.getKey();
|
|
||||||
if (me.getTrace() != trace) {
|
if (me.getTrace() != trace) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -509,21 +572,29 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
if (!me.isInTraceLifespan(snap)) {
|
if (!me.isInTraceLifespan(snap)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
return me.mapProgramAddressToTraceLocation(address);
|
return me.mapProgramAddressToTraceLocation(address);
|
||||||
}
|
}
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void collectOpenMappedViews(AddressRange rng,
|
protected void collectOpenMappedViews(AddressRange rng,
|
||||||
Map<TraceSpan, Collection<MappedAddressRange>> result) {
|
Map<TraceSpan, Collection<MappedAddressRange>> result) {
|
||||||
|
Set<MappingEntry> toClean = new HashSet<>();
|
||||||
for (Entry<MappingEntry, Address> inPreceeding : inbound
|
for (Entry<MappingEntry, Address> inPreceeding : inbound
|
||||||
.headMapByValue(rng.getMaxAddress(), true)
|
.headMapByValue(rng.getMaxAddress(), true)
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
|
MappingEntry me = inPreceeding.getKey();
|
||||||
|
if (me.mapping.isDeleted()) {
|
||||||
|
Msg.warn(this, "Encountered deleted mapping: " + me.mapping);
|
||||||
|
toClean.add(me);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Address start = inPreceeding.getValue();
|
Address start = inPreceeding.getValue();
|
||||||
if (start == null) {
|
if (start == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MappingEntry me = inPreceeding.getKey();
|
|
||||||
if (!me.isInProgramRange(rng)) {
|
if (!me.isInProgramRange(rng)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -533,6 +604,7 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
result.computeIfAbsent(me.getTraceSpan(), p -> new TreeSet<>())
|
result.computeIfAbsent(me.getTraceSpan(), p -> new TreeSet<>())
|
||||||
.add(new MappedAddressRange(srcRange, dstRange));
|
.add(new MappedAddressRange(srcRange, dstRange));
|
||||||
}
|
}
|
||||||
|
inbound.keySet().removeAll(toClean);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<TraceSpan, Collection<MappedAddressRange>> getOpenMappedViews(
|
public Map<TraceSpan, Collection<MappedAddressRange>> getOpenMappedViews(
|
||||||
@ -609,6 +681,13 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void programsAffected(Collection<Program> programs) {
|
||||||
|
synchronized (affectedTraces) {
|
||||||
|
affectedPrograms.addAll(programs);
|
||||||
|
changeDebouncer.contact(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addChangeListener(DebuggerStaticMappingChangeListener l) {
|
public void addChangeListener(DebuggerStaticMappingChangeListener l) {
|
||||||
changeListeners.add(l);
|
changeListeners.add(l);
|
||||||
@ -706,13 +785,22 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doAffectedByTraceOpened(Trace trace) {
|
private Set<Program> collectAffectedByTrace(Trace trace) {
|
||||||
|
Set<Program> set = new HashSet<>();
|
||||||
for (InfoPerProgram info : trackedProgramInfo.values()) {
|
for (InfoPerProgram info : trackedProgramInfo.values()) {
|
||||||
if (info.isMappedInTrace(trace)) {
|
if (info.isMappedInTrace(trace)) {
|
||||||
traceAffected(trace);
|
set.add(info.program);
|
||||||
programAffected(info.program);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doAffectedByTraceOpened(Trace trace) {
|
||||||
|
Set<Program> set = collectAffectedByTrace(trace);
|
||||||
|
if (!set.isEmpty()) {
|
||||||
|
traceAffected(trace);
|
||||||
|
programsAffected(set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void traceOpened(Trace trace) {
|
private void traceOpened(Trace trace) {
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -19,15 +19,10 @@ import java.awt.Component;
|
|||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.beans.PropertyEditor;
|
import java.beans.PropertyEditor;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import ghidra.debug.api.action.LocationTrackingSpec;
|
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.util.MathUtilities;
|
import ghidra.util.MathUtilities;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
|
||||||
|
|
||||||
public enum MiscellaneousUtils {
|
public enum MiscellaneousUtils {
|
||||||
;
|
;
|
||||||
@ -87,23 +82,6 @@ public enum MiscellaneousUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void collectUniqueInstances(Class<T> cls, Map<String, T> map,
|
|
||||||
Function<T, String> keyFunc) {
|
|
||||||
// This is wasteful. Existing instances will be re-instantiated and thrown away
|
|
||||||
for (T t : ClassSearcher.getInstances(cls)) {
|
|
||||||
String key = keyFunc.apply(t);
|
|
||||||
T exists = map.get(key);
|
|
||||||
if (exists != null) {
|
|
||||||
if (exists.getClass().equals(t.getClass())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Msg.error(LocationTrackingSpec.class,
|
|
||||||
cls.getSimpleName() + " conflict over key: " + key);
|
|
||||||
}
|
|
||||||
map.put(key, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long lengthMin(long a, long b) {
|
public static long lengthMin(long a, long b) {
|
||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
return b;
|
return b;
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -32,7 +32,6 @@ import ghidra.app.plugin.core.debug.gui.*;
|
|||||||
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog.MemoryBlockRow;
|
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog.MemoryBlockRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractImportFromFileSystemAction;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractImportFromFileSystemAction;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
|
||||||
import ghidra.app.plugin.core.debug.gui.action.AutoMapSpec;
|
|
||||||
import ghidra.app.plugin.core.debug.gui.action.NoneAutoMapSpec;
|
import ghidra.app.plugin.core.debug.gui.action.NoneAutoMapSpec;
|
||||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
||||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
|
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
|
||||||
@ -42,6 +41,7 @@ import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider.MapSecti
|
|||||||
import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns;
|
import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns;
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
||||||
import ghidra.app.services.DebuggerListingService;
|
import ghidra.app.services.DebuggerListingService;
|
||||||
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||||
import ghidra.framework.main.DataTreeDialog;
|
import ghidra.framework.main.DataTreeDialog;
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -148,8 +148,7 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
record ObjectsContainingKey(long snap, Address address, String key,
|
record ObjectsContainingKey(long snap, Address address, String key,
|
||||||
Class<? extends TraceObjectInterface> iface) {
|
Class<? extends TraceObjectInterface> iface) {}
|
||||||
}
|
|
||||||
|
|
||||||
protected final ReadWriteLock lock;
|
protected final ReadWriteLock lock;
|
||||||
protected final DBTrace trace;
|
protected final DBTrace trace;
|
||||||
|
Loading…
Reference in New Issue
Block a user