mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
5ef4b269a1
26 changed files with 193 additions and 137 deletions
|
@ -75,11 +75,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||||
//modulesByName.remove(name);
|
//modulesByName.remove(name);
|
||||||
module = getTargetModule(name);
|
module = getTargetModule(name);
|
||||||
}
|
}
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(getManager().getEventThread());
|
|
||||||
changeElements(List.of(), List.of(module), Map.of(), "Loaded");
|
changeElements(List.of(), List.of(module), Map.of(), "Loaded");
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + name + " loaded", List.of(module));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,10 +83,6 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||||
public void libraryUnloaded(String name) {
|
public void libraryUnloaded(String name) {
|
||||||
DbgModelTargetModule targetModule = getTargetModule(name);
|
DbgModelTargetModule targetModule = getTargetModule(name);
|
||||||
if (targetModule != null) {
|
if (targetModule != null) {
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(getManager().getEventThread());
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + name + " unloaded", List.of(targetModule));
|
|
||||||
DbgModelImpl impl = (DbgModelImpl) model;
|
DbgModelImpl impl = (DbgModelImpl) model;
|
||||||
impl.deleteModelObject(targetModule.getDbgModule());
|
impl.deleteModelObject(targetModule.getDbgModule());
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,9 +181,8 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||||
|
|
||||||
public void objectSelected(Object object) {
|
public void objectSelected(Object object) {
|
||||||
List<String> objPath = findObject(object);
|
List<String> objPath = findObject(object);
|
||||||
model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT).thenAccept(obj ->
|
model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT)
|
||||||
update(obj)
|
.thenAccept(obj -> update(obj));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -241,11 +240,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||||
if (mod == null) {
|
if (mod == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getObject(getManager().getEventThread()).thenAccept(t -> {
|
|
||||||
TargetThread eventThread = (TargetThread) t;
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + info.getModuleName() + " loaded", List.of(mod));
|
|
||||||
});
|
|
||||||
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
||||||
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
|
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
|
||||||
DbgModel2TargetObjectImpl memory =
|
DbgModel2TargetObjectImpl memory =
|
||||||
|
@ -262,11 +256,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||||
if (mod == null) {
|
if (mod == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getObject(getManager().getEventThread()).thenAccept(t -> {
|
|
||||||
TargetThread eventThread = (TargetThread) t;
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + info.getModuleName() + " unloaded", List.of(mod));
|
|
||||||
});
|
|
||||||
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
||||||
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
|
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
|
||||||
DbgModel2TargetObjectImpl memory =
|
DbgModel2TargetObjectImpl memory =
|
||||||
|
|
|
@ -69,12 +69,7 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||||
Msg.error(this, "Module " + info.getModuleName(index) + " not found!");
|
Msg.error(this, "Module " + info.getModuleName(index) + " not found!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FridaThread thread = getManager().getCurrentThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,11 +86,6 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||||
FridaCause cause) {
|
FridaCause cause) {
|
||||||
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
||||||
if (targetModule != null) {
|
if (targetModule != null) {
|
||||||
FridaThread thread = getManager().getCurrentThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
|
||||||
FridaModelImpl impl = (FridaModelImpl) model;
|
FridaModelImpl impl = (FridaModelImpl) model;
|
||||||
impl.deleteModelObject(targetModule.getModule());
|
impl.deleteModelObject(targetModule.getModule());
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,7 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||||
Msg.error(this, "Module " + info.getModuleName(index) + " not found!");
|
Msg.error(this, "Module " + info.getModuleName(index) + " not found!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FridaThread thread = getManager().getCurrentThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,11 +104,6 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||||
FridaCause cause) {
|
FridaCause cause) {
|
||||||
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
||||||
if (targetModule != null) {
|
if (targetModule != null) {
|
||||||
FridaThread thread = getManager().getCurrentThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
|
||||||
FridaModelImpl impl = (FridaModelImpl) model;
|
FridaModelImpl impl = (FridaModelImpl) model;
|
||||||
impl.deleteModelObject(targetModule.getModule());
|
impl.deleteModelObject(targetModule.getModule());
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,17 +107,12 @@ public class GdbModelTargetInferiorContainer
|
||||||
@Override
|
@Override
|
||||||
public void libraryLoaded(GdbInferior inf, String name, GdbCause cause) {
|
public void libraryLoaded(GdbInferior inf, String name, GdbCause cause) {
|
||||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||||
GdbModelTargetModule module = inferior.modules.libraryLoaded(name);
|
inferior.modules.libraryLoaded(name);
|
||||||
broadcast().event(parent, null, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + name + " loaded", List.of(module));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void libraryUnloaded(GdbInferior inf, String name, GdbCause cause) {
|
public void libraryUnloaded(GdbInferior inf, String name, GdbCause cause) {
|
||||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||||
GdbModelTargetModule module = inferior.modules.getTargetModuleIfPresent(name);
|
|
||||||
broadcast().event(parent, null, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + name + " unloaded", List.of(module));
|
|
||||||
inferior.modules.libraryUnloaded(name);
|
inferior.modules.libraryUnloaded(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,11 @@ public class GdbModelTargetModuleContainer
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
public GdbModelTargetModule libraryLoaded(String name) {
|
public GdbModelTargetModule libraryLoaded(String name) {
|
||||||
GdbModule mod = Objects.requireNonNull(inferior.getKnownModules().get(name));
|
GdbModule mod = inferior.getKnownModules().get(name);
|
||||||
|
if (mod == null) {
|
||||||
|
// We'll catch it the next time around.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
GdbModelTargetModule module = getTargetModule(mod);
|
GdbModelTargetModule module = getTargetModule(mod);
|
||||||
changeElements(List.of(), List.of(module), "Loaded");
|
changeElements(List.of(), List.of(module), "Loaded");
|
||||||
return module;
|
return module;
|
||||||
|
|
|
@ -69,12 +69,7 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp
|
||||||
System.err.println("Module " + info.getModuleName(index) + " not found!");
|
System.err.println("Module " + info.getModuleName(index) + " not found!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SBThread thread = getManager().getEventThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,11 +77,6 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp
|
||||||
public void libraryUnloaded(DebugModuleInfo info, int index) {
|
public void libraryUnloaded(DebugModuleInfo info, int index) {
|
||||||
LldbModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
LldbModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
||||||
if (targetModule != null) {
|
if (targetModule != null) {
|
||||||
SBThread thread = getManager().getEventThread();
|
|
||||||
TargetThread eventThread =
|
|
||||||
(TargetThread) getModel().getModelObject(thread);
|
|
||||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
|
||||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
|
||||||
LldbModelImpl impl = (LldbModelImpl) model;
|
LldbModelImpl impl = (LldbModelImpl) model;
|
||||||
impl.deleteModelObject(targetModule.getModule());
|
impl.deleteModelObject(targetModule.getModule());
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,10 +234,6 @@ public enum GadpValueUtils {
|
||||||
return TargetEventType.THREAD_CREATED;
|
return TargetEventType.THREAD_CREATED;
|
||||||
case EV_THREAD_EXITED:
|
case EV_THREAD_EXITED:
|
||||||
return TargetEventType.THREAD_EXITED;
|
return TargetEventType.THREAD_EXITED;
|
||||||
case EV_MODULE_LOADED:
|
|
||||||
return TargetEventType.MODULE_LOADED;
|
|
||||||
case EV_MODULE_UNLOADED:
|
|
||||||
return TargetEventType.MODULE_UNLOADED;
|
|
||||||
case EV_BREAKPOINT_HIT:
|
case EV_BREAKPOINT_HIT:
|
||||||
return TargetEventType.BREAKPOINT_HIT;
|
return TargetEventType.BREAKPOINT_HIT;
|
||||||
case EV_STEP_COMPLETED:
|
case EV_STEP_COMPLETED:
|
||||||
|
@ -264,10 +260,6 @@ public enum GadpValueUtils {
|
||||||
return Gadp.TargetEventType.EV_THREAD_CREATED;
|
return Gadp.TargetEventType.EV_THREAD_CREATED;
|
||||||
case THREAD_EXITED:
|
case THREAD_EXITED:
|
||||||
return Gadp.TargetEventType.EV_THREAD_EXITED;
|
return Gadp.TargetEventType.EV_THREAD_EXITED;
|
||||||
case MODULE_LOADED:
|
|
||||||
return Gadp.TargetEventType.EV_MODULE_LOADED;
|
|
||||||
case MODULE_UNLOADED:
|
|
||||||
return Gadp.TargetEventType.EV_MODULE_UNLOADED;
|
|
||||||
case BREAKPOINT_HIT:
|
case BREAKPOINT_HIT:
|
||||||
return Gadp.TargetEventType.EV_BREAKPOINT_HIT;
|
return Gadp.TargetEventType.EV_BREAKPOINT_HIT;
|
||||||
case STEP_COMPLETED:
|
case STEP_COMPLETED:
|
||||||
|
|
|
@ -484,8 +484,6 @@ enum TargetEventType {
|
||||||
EV_PROCESS_EXITED = 3;
|
EV_PROCESS_EXITED = 3;
|
||||||
EV_THREAD_CREATED = 4;
|
EV_THREAD_CREATED = 4;
|
||||||
EV_THREAD_EXITED = 5;
|
EV_THREAD_EXITED = 5;
|
||||||
EV_MODULE_LOADED = 6;
|
|
||||||
EV_MODULE_UNLOADED = 7;
|
|
||||||
EV_BREAKPOINT_HIT = 8;
|
EV_BREAKPOINT_HIT = 8;
|
||||||
EV_STEP_COMPLETED = 9;
|
EV_STEP_COMPLETED = 9;
|
||||||
EV_EXCEPTION = 10;
|
EV_EXCEPTION = 10;
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.action;
|
package ghidra.app.plugin.core.debug.gui.action;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
@ -34,7 +33,7 @@ import ghidra.util.classfinder.ExtensionPoint;
|
||||||
|
|
||||||
public interface AutoReadMemorySpec extends ExtensionPoint {
|
public interface AutoReadMemorySpec extends ExtensionPoint {
|
||||||
class Private {
|
class Private {
|
||||||
private final Map<String, AutoReadMemorySpec> specsByName = new TreeMap<>();
|
private final Map<String, AutoReadMemorySpec> specsByName = new HashMap<>();
|
||||||
private final ChangeListener classListener = this::classesChanged;
|
private final ChangeListener classListener = this::classesChanged;
|
||||||
|
|
||||||
private Private() {
|
private Private() {
|
||||||
|
@ -72,7 +71,7 @@ public interface AutoReadMemorySpec extends ExtensionPoint {
|
||||||
|
|
||||||
static Map<String, AutoReadMemorySpec> allSpecs() {
|
static Map<String, AutoReadMemorySpec> allSpecs() {
|
||||||
synchronized (PRIVATE) {
|
synchronized (PRIVATE) {
|
||||||
return Map.copyOf(PRIVATE.specsByName);
|
return new TreeMap<>(PRIVATE.specsByName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ package ghidra.app.plugin.core.debug.gui.listing;
|
||||||
|
|
||||||
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.ICON_REGISTER_MARKER;
|
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.ICON_REGISTER_MARKER;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
@ -26,8 +26,8 @@ import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.swing.Box;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
@ -336,11 +336,9 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
||||||
|
|
||||||
addDisplayListener(readsMemTrait.getDisplayListener());
|
addDisplayListener(readsMemTrait.getDisplayListener());
|
||||||
|
|
||||||
Box northPanel = Box.createHorizontalBox();
|
JPanel northPanel = new JPanel(new BorderLayout());
|
||||||
northPanel.add(locationLabel);
|
northPanel.add(locationLabel);
|
||||||
locationLabel.setMinimumSize(new Dimension(0, 0));
|
northPanel.add(trackingLabel, BorderLayout.EAST);
|
||||||
northPanel.add(Box.createGlue());
|
|
||||||
northPanel.add(trackingLabel);
|
|
||||||
this.setNorthComponent(northPanel);
|
this.setNorthComponent(northPanel);
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
setTitle(DebuggerResources.TITLE_PROVIDER_LISTING);
|
setTitle(DebuggerResources.TITLE_PROVIDER_LISTING);
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
package ghidra.app.plugin.core.debug.gui.memory;
|
package ghidra.app.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
@ -207,11 +207,9 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
||||||
createActions();
|
createActions();
|
||||||
addDisplayListener(readsMemTrait.getDisplayListener());
|
addDisplayListener(readsMemTrait.getDisplayListener());
|
||||||
|
|
||||||
Box northPanel = Box.createHorizontalBox();
|
JPanel northPanel = new JPanel(new BorderLayout());
|
||||||
northPanel.add(locationLabel);
|
northPanel.add(locationLabel);
|
||||||
locationLabel.setMinimumSize(new Dimension(0, 0));
|
northPanel.add(trackingLabel, BorderLayout.EAST);
|
||||||
northPanel.add(Box.createGlue());
|
|
||||||
northPanel.add(trackingLabel);
|
|
||||||
decorationComponent.add(northPanel, BorderLayout.NORTH);
|
decorationComponent.add(northPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
goToTrait.goToCoordinates(current);
|
goToTrait.goToCoordinates(current);
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class DebuggerLegacyModulesPanel extends JPanel {
|
||||||
MAX("Max Address", Address.class, ModuleRow::getMaxAddress),
|
MAX("Max Address", Address.class, ModuleRow::getMaxAddress),
|
||||||
SHORT_NAME("Name", String.class, ModuleRow::getShortName),
|
SHORT_NAME("Name", String.class, ModuleRow::getShortName),
|
||||||
NAME("Module Name", String.class, ModuleRow::getName, ModuleRow::setName),
|
NAME("Module Name", String.class, ModuleRow::getName, ModuleRow::setName),
|
||||||
|
MAPPING("Mapping", String.class, ModuleRow::getMapping),
|
||||||
LIFESPAN("Lifespan", Lifespan.class, ModuleRow::getLifespan),
|
LIFESPAN("Lifespan", Lifespan.class, ModuleRow::getLifespan),
|
||||||
LENGTH("Length", Long.class, ModuleRow::getLength);
|
LENGTH("Length", Long.class, ModuleRow::getLength);
|
||||||
|
|
||||||
|
@ -144,9 +145,9 @@ public class DebuggerLegacyModulesPanel extends JPanel {
|
||||||
extends DebouncedRowWrappedEnumeratedColumnTableModel< //
|
extends DebouncedRowWrappedEnumeratedColumnTableModel< //
|
||||||
ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> {
|
ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> {
|
||||||
|
|
||||||
public ModuleTableModel(PluginTool tool) {
|
public ModuleTableModel(PluginTool tool, DebuggerModulesProvider provider) {
|
||||||
super(tool, "Modules", ModuleTableColumns.class, TraceModule::getObjectKey,
|
super(tool, "Modules", ModuleTableColumns.class, TraceModule::getObjectKey,
|
||||||
ModuleRow::new, ModuleRow::getModule);
|
mod -> new ModuleRow(provider, mod), ModuleRow::getModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -197,7 +198,7 @@ public class DebuggerLegacyModulesPanel extends JPanel {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
moduleTableModel = new ModuleTableModel(provider.getTool());
|
moduleTableModel = new ModuleTableModel(provider.getTool(), provider);
|
||||||
moduleTable = new GhidraTable(moduleTableModel);
|
moduleTable = new GhidraTable(moduleTableModel);
|
||||||
moduleTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
moduleTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
add(new JScrollPane(moduleTable));
|
add(new JScrollPane(moduleTable));
|
||||||
|
|
|
@ -21,8 +21,10 @@ import javax.swing.event.ListSelectionEvent;
|
||||||
|
|
||||||
import docking.widgets.table.TableColumnDescriptor;
|
import docking.widgets.table.TableColumnDescriptor;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.*;
|
import ghidra.app.plugin.core.debug.gui.model.*;
|
||||||
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueAttribute;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.dbg.target.TargetModule;
|
import ghidra.dbg.target.TargetModule;
|
||||||
import ghidra.dbg.target.TargetProcess;
|
import ghidra.dbg.target.TargetProcess;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||||
|
@ -81,6 +83,31 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ModuleMappingColumn extends TraceValueKeyColumn {
|
||||||
|
@Override
|
||||||
|
public String getColumnName() {
|
||||||
|
return "Mapping";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue(ValueRow rowObject, Settings settings, Trace data,
|
||||||
|
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||||
|
ValueAttribute<AddressRange> attr =
|
||||||
|
rowObject.getAttribute(TargetModule.RANGE_ATTRIBUTE_NAME, AddressRange.class);
|
||||||
|
if (attr == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
AddressRange range = attr.getValue();
|
||||||
|
|
||||||
|
// TODO: Cache this? Would flush on:
|
||||||
|
// 1. Mapping changes
|
||||||
|
// 2. Range/Life changes to this module
|
||||||
|
// 3. Snapshot navigation
|
||||||
|
return DebuggerStaticMappingUtils.computeMappedFiles(data, rowObject.currentSnap(),
|
||||||
|
range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ModulePathColumn extends TraceValueKeyColumn {
|
private static class ModulePathColumn extends TraceValueKeyColumn {
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
|
@ -117,6 +144,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
||||||
descriptor.addVisibleColumn(new ModuleBaseColumn(), 1, true);
|
descriptor.addVisibleColumn(new ModuleBaseColumn(), 1, true);
|
||||||
descriptor.addVisibleColumn(new ModuleMaxColumn());
|
descriptor.addVisibleColumn(new ModuleMaxColumn());
|
||||||
descriptor.addVisibleColumn(new ModuleNameColumn());
|
descriptor.addVisibleColumn(new ModuleNameColumn());
|
||||||
|
descriptor.addVisibleColumn(new ModuleMappingColumn());
|
||||||
descriptor.addVisibleColumn(new ModuleLengthColumn());
|
descriptor.addVisibleColumn(new ModuleLengthColumn());
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,7 +419,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
private final DebuggerModuleMapProposalDialog moduleProposalDialog;
|
private final DebuggerModuleMapProposalDialog moduleProposalDialog;
|
||||||
private final DebuggerSectionMapProposalDialog sectionProposalDialog;
|
private final DebuggerSectionMapProposalDialog sectionProposalDialog;
|
||||||
|
|
||||||
private DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||||
private Program currentProgram;
|
private Program currentProgram;
|
||||||
private ProgramLocation currentLocation;
|
private ProgramLocation currentLocation;
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,17 @@
|
||||||
package ghidra.app.plugin.core.debug.gui.modules;
|
package ghidra.app.plugin.core.debug.gui.modules;
|
||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
import ghidra.trace.model.modules.TraceModule;
|
||||||
|
|
||||||
public class ModuleRow {
|
public class ModuleRow {
|
||||||
|
private final DebuggerModulesProvider provider;
|
||||||
private final TraceModule module;
|
private final TraceModule module;
|
||||||
|
|
||||||
public ModuleRow(TraceModule module) {
|
public ModuleRow(DebuggerModulesProvider provider, TraceModule module) {
|
||||||
|
this.provider = provider;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +57,15 @@ public class ModuleRow {
|
||||||
return module.getName();
|
return module.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMapping() {
|
||||||
|
// TODO: Cache this? Would flush on:
|
||||||
|
// 1. Mapping changes
|
||||||
|
// 2. Range/Life changes to this module
|
||||||
|
// 3. Snapshot navigation
|
||||||
|
return DebuggerStaticMappingUtils.computeMappedFiles(module.getTrace(),
|
||||||
|
provider.current.getSnap(), module.getRange());
|
||||||
|
}
|
||||||
|
|
||||||
public Address getBase() {
|
public Address getBase() {
|
||||||
return module.getBase();
|
return module.getBase();
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,9 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter
|
||||||
if (dataType == null) {
|
if (dataType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (currentTrace == null) {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
try (Transaction tx = currentTrace.openTransaction("Resolve DataType")) {
|
try (Transaction tx = currentTrace.openTransaction("Resolve DataType")) {
|
||||||
return currentTrace.getDataTypeManager().resolve(dataType, null);
|
return currentTrace.getDataTypeManager().resolve(dataType, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,9 @@ import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||||
import ghidra.trace.model.memory.TraceMemoryState;
|
import ghidra.trace.model.memory.TraceMemoryState;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.TimedMsg;
|
import ghidra.util.TimedMsg;
|
||||||
import ghidra.util.datastruct.PrivatelyQueuedListener;
|
import ghidra.util.datastruct.PrivatelyQueuedListener;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
|
||||||
|
|
||||||
public class TraceEventListener extends AnnotatedDebuggerAttributeListener {
|
public class TraceEventListener extends AnnotatedDebuggerAttributeListener {
|
||||||
|
|
||||||
|
@ -143,28 +141,6 @@ public class TraceEventListener extends AnnotatedDebuggerAttributeListener {
|
||||||
ManagedThreadRecorder rec = recorder.getThreadRecorder(eventThread);
|
ManagedThreadRecorder rec = recorder.getThreadRecorder(eventThread);
|
||||||
recorder.createSnapshot(description, rec == null ? null : rec.getTraceThread(), null);
|
recorder.createSnapshot(description, rec == null ? null : rec.getTraceThread(), null);
|
||||||
ignoreInvalidation = false;
|
ignoreInvalidation = false;
|
||||||
|
|
||||||
if (type == TargetEventType.MODULE_LOADED) {
|
|
||||||
long snap = recorder.getSnap();
|
|
||||||
Object p0 = parameters.get(0);
|
|
||||||
if (!(p0 instanceof TargetModule)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TargetModule mod = (TargetModule) p0;
|
|
||||||
String modPath = mod.getJoinedPath(".");
|
|
||||||
recorder.parTx.execute("Adjust module load: " + modPath, () -> {
|
|
||||||
TraceModule traceModule = recorder.getTraceModule(mod);
|
|
||||||
if (traceModule == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
traceModule.setLoadedSnap(snap);
|
|
||||||
}
|
|
||||||
catch (DuplicateNameException e) {
|
|
||||||
Msg.error(this, "Could not set module loaded snap", e);
|
|
||||||
}
|
|
||||||
}, modPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeCallback(TargetExecutionStateful.STATE_ATTRIBUTE_NAME)
|
@AttributeCallback(TargetExecutionStateful.STATE_ATTRIBUTE_NAME)
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.service.model.launch;
|
package ghidra.app.plugin.core.debug.service.model.launch;
|
||||||
|
|
||||||
import static ghidra.async.AsyncUtils.*;
|
import static ghidra.async.AsyncUtils.loop;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -275,7 +275,8 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
|
||||||
for (Entry<String, ParameterDescription<?>> entry : params.entrySet()) {
|
for (Entry<String, ParameterDescription<?>> entry : params.entrySet()) {
|
||||||
map.put(entry.getKey(), entry.getValue().defaultValue);
|
map.put(entry.getKey(), entry.getValue().defaultValue);
|
||||||
}
|
}
|
||||||
map.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
|
map.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME,
|
||||||
|
TargetCmdLineLauncher.quoteImagePathIfSpaces(program.getExecutablePath()));
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.plugin.core.debug.service.modules;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
|
import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
|
||||||
import ghidra.app.services.MapEntry;
|
import ghidra.app.services.MapEntry;
|
||||||
|
@ -238,4 +239,66 @@ public enum DebuggerStaticMappingUtils {
|
||||||
}
|
}
|
||||||
return new AddressRangeImpl(space.getAddress(min), space.getAddress(max));
|
return new AddressRangeImpl(space.getAddress(min), space.getAddress(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the final file name from the given URL.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This is used when listing the "image" name for mappings, since displaying a full URL would
|
||||||
|
* probably clutter the table. This generally matches the "program name," but in certain cases
|
||||||
|
* may not.
|
||||||
|
*
|
||||||
|
* @param staticProgramURL the URL of the static program image
|
||||||
|
* @return the piece after the final "/"
|
||||||
|
*/
|
||||||
|
public static String getImageName(URL staticProgramURL) {
|
||||||
|
String[] parts = staticProgramURL.toExternalForm().split("/");
|
||||||
|
return parts[parts.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a string suitable for displaying the mapped module names for a given range
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Ideally, the entire range is covered by a single mapping entry. In that case, the "image
|
||||||
|
* name" (see {@link #getImageName(URL)}) for that one mapping is returned. If a single mapping
|
||||||
|
* is found, but it only partially covers the given range, an asterisk is appended. If no
|
||||||
|
* mappings are found, the empty string is returned. If multiple mappings are found, they are
|
||||||
|
* each listed alphabetically. No asterisk is displayed in the case of multiple images, since
|
||||||
|
* it's implied that none cover the entire range.
|
||||||
|
*
|
||||||
|
* @param trace the trace whose mappings to query
|
||||||
|
* @param snap the relevant snapshot
|
||||||
|
* @param range the address range to consider
|
||||||
|
* @return the names of any mapped images
|
||||||
|
*/
|
||||||
|
public static String computeMappedFiles(Trace trace, long snap, AddressRange range) {
|
||||||
|
List<TraceStaticMapping> mappings = List.copyOf(
|
||||||
|
trace.getStaticMappingManager().findAllOverlapping(range, Lifespan.at(snap)));
|
||||||
|
if (mappings.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (mappings.size() == 1) {
|
||||||
|
TraceStaticMapping single = mappings.get(0);
|
||||||
|
AddressRange mappedRange = single.getTraceAddressRange();
|
||||||
|
if (mappedRange.contains(range.getMinAddress()) &&
|
||||||
|
mappedRange.contains(range.getMaxAddress())) {
|
||||||
|
return getImageName(single.getStaticProgramURL());
|
||||||
|
}
|
||||||
|
return getImageName(single.getStaticProgramURL()) + "*";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Its possible multiple mappings to the same image are at play. This would happen if the
|
||||||
|
* user is mapping by sections instead of modules.
|
||||||
|
*/
|
||||||
|
List<String> names = mappings.stream()
|
||||||
|
.map(m -> getImageName(m.getStaticProgramURL()))
|
||||||
|
.sorted()
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
if (names.size() == 1) {
|
||||||
|
return names.get(0) + "*";
|
||||||
|
}
|
||||||
|
return names.stream().collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,17 +64,6 @@ public interface TargetEventScope extends TargetObject {
|
||||||
* A target thread in this session has exited
|
* A target thread in this session has exited
|
||||||
*/
|
*/
|
||||||
THREAD_EXITED(false),
|
THREAD_EXITED(false),
|
||||||
/**
|
|
||||||
* A new module has been loaded by this session
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The new module must be passed as a parameter.
|
|
||||||
*/
|
|
||||||
MODULE_LOADED(false),
|
|
||||||
/**
|
|
||||||
* A module has been unloaded by this session
|
|
||||||
*/
|
|
||||||
MODULE_UNLOADED(false),
|
|
||||||
/**
|
/**
|
||||||
* The session has stopped, because one if its targets was trapped by a breakpoint
|
* The session has stopped, because one if its targets was trapped by a breakpoint
|
||||||
*
|
*
|
||||||
|
|
|
@ -60,6 +60,25 @@ public interface TargetLauncher extends TargetObject {
|
||||||
*/
|
*/
|
||||||
TargetParameterMap PARAMETERS = TargetMethod.makeParameters(PARAMETER_CMDLINE_ARGS);
|
TargetParameterMap PARAMETERS = TargetMethod.makeParameters(PARAMETER_CMDLINE_ARGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given image path contains spaces, and surround it in double quotes
|
||||||
|
* ({@code "}) if necessary.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Without the quotes the launcher will likely confuse the spaces for separating arguments.
|
||||||
|
* When constructing the command-line to launch a program, this method must be used, even if
|
||||||
|
* the image is the only "argument."
|
||||||
|
*
|
||||||
|
* @param imagePath the path to the image on the target platform.
|
||||||
|
* @return the path, possibly surrounded in quotes.
|
||||||
|
*/
|
||||||
|
static String quoteImagePathIfSpaces(String imagePath) {
|
||||||
|
if (imagePath.contains(" ")) {
|
||||||
|
return '"' + imagePath + '"';
|
||||||
|
}
|
||||||
|
return imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default public TargetParameterMap getParameters() {
|
default public TargetParameterMap getParameters() {
|
||||||
return PARAMETERS;
|
return PARAMETERS;
|
||||||
|
|
|
@ -907,7 +907,9 @@ public interface TargetObjectSchema {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AttributeSchema schema = getAttributeSchema(key);
|
AttributeSchema schema = getAttributeSchema(key);
|
||||||
if (schema == AttributeSchema.DEFAULT_ANY || schema == AttributeSchema.DEFAULT_OBJECT) {
|
if (schema == AttributeSchema.DEFAULT_ANY ||
|
||||||
|
schema == AttributeSchema.DEFAULT_OBJECT ||
|
||||||
|
schema == AttributeSchema.DEFAULT_VOID) {
|
||||||
// FIXME: Remove this hack once we stop depending on this prefix
|
// FIXME: Remove this hack once we stop depending on this prefix
|
||||||
return key.startsWith(TargetObject.PREFIX_INVISIBLE);
|
return key.startsWith(TargetObject.PREFIX_INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,12 +203,6 @@ public class EventValidator
|
||||||
case THREAD_EXITED:
|
case THREAD_EXITED:
|
||||||
validateDestroyed(type.name(), TargetThread.class, threads, parameters);
|
validateDestroyed(type.name(), TargetThread.class, threads, parameters);
|
||||||
break;
|
break;
|
||||||
case MODULE_LOADED:
|
|
||||||
validateCreated(type.name(), TargetModule.class, modules, parameters);
|
|
||||||
break;
|
|
||||||
case MODULE_UNLOADED:
|
|
||||||
validateDestroyed(type.name(), TargetModule.class, modules, parameters);
|
|
||||||
break;
|
|
||||||
case STOPPED:
|
case STOPPED:
|
||||||
case RUNNING:
|
case RUNNING:
|
||||||
case BREAKPOINT_HIT:
|
case BREAKPOINT_HIT:
|
||||||
|
|
|
@ -46,6 +46,7 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
|
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
|
||||||
<attribute name='curTarget' schema='Target' />
|
<attribute name='curTarget' schema='Target' />
|
||||||
<attribute name='Targets' schema='TargetContainer' />
|
<attribute name='Targets' schema='TargetContainer' />
|
||||||
|
<attribute schema='VOID' />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name='TargetContainer' canonical='yes' elementResync='NEVER'
|
<schema name='TargetContainer' canonical='yes' elementResync='NEVER'
|
||||||
attributeResync='ONCE'>
|
attributeResync='ONCE'>
|
||||||
|
@ -1063,4 +1064,33 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
assertFalse(split.isDeleted()); // Other values not affected
|
assertFalse(split.isDeleted()); // Other values not affected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAttributeDefaultVisibility() {
|
||||||
|
try (Transaction tx = b.startTransaction()) {
|
||||||
|
TraceObjectValue rootVal =
|
||||||
|
manager.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
root = rootVal.getChild();
|
||||||
|
|
||||||
|
TraceObject object = manager.createObject(TraceObjectKeyPath.parse("OutsideSchema"));
|
||||||
|
object.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
|
assertFalse(object.getCanonicalParent(0).isHidden());
|
||||||
|
|
||||||
|
TraceObject elemOutside =
|
||||||
|
manager.createObject(TraceObjectKeyPath.parse("OutsideSchema[0]"));
|
||||||
|
elemOutside.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
|
assertFalse(elemOutside.getCanonicalParent(0).isHidden());
|
||||||
|
|
||||||
|
TraceObject attrOutside =
|
||||||
|
manager.createObject(TraceObjectKeyPath.parse("OutsideSchema.Attr"));
|
||||||
|
attrOutside.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
|
assertFalse(attrOutside.getCanonicalParent(0).isHidden());
|
||||||
|
|
||||||
|
// TODO: This underscore convention is deprecated, but still in use
|
||||||
|
TraceObject hiddenOutside =
|
||||||
|
manager.createObject(TraceObjectKeyPath.parse("OutsideSchema._Attr"));
|
||||||
|
hiddenOutside.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
|
assertTrue(hiddenOutside.getCanonicalParent(0).isHidden());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,9 +308,12 @@ public enum SleighUtils {
|
||||||
match(tree, SleighParser.OP_DEREFERENCE, onSize, onOffset);
|
match(tree, SleighParser.OP_DEREFERENCE, onSize, onOffset);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
throw new AssertionError(
|
matchTree(tree, SleighParser.OP_DEREFERENCE, children -> {
|
||||||
"OP_DEREFERENCE with 2 children where child[0] is " +
|
throw new AssertionError(
|
||||||
SleighParser.tokenNames[child0.getType()]);
|
"OP_DEREFERENCE with 2 children where child[0] is " +
|
||||||
|
SleighParser.tokenNames[child0.getType()]);
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
match(tree, SleighParser.OP_DEREFERENCE, onOffset);
|
match(tree, SleighParser.OP_DEREFERENCE, onOffset);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue