diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html index 24ebe105e7..a68e29113a 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html @@ -101,6 +101,17 @@ selects the region containing that cursor. If the dynamic listing has a selection, it selects all regions intersecting that selection.
+This action is available when a trace is active. It adds a new region to the memory map. It + should only be used for emulation or to correct or diagnose trace recording issues.
+ +This action is available when at least one region is selected. It deletes those regions. Use + this with caution, since recovering those regions could be difficult. In general, this should + only be used to remove regions that were manually added.
+This action is available when a trace is active. It forces all physical address spaces into
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
index f14a5ee3e3..7be4880d25 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
@@ -1878,22 +1878,6 @@ public interface DebuggerResources {
}
}
- interface ForceFullViewAction {
- String NAME = "Force Full View";
- String DESCRIPTION = "Ignore regions and fiew full address spaces";
- String GROUP = GROUP_GENERAL;
- String HELP_ANCHOR = "force_full_view";
-
- static ToggleActionBuilder builder(Plugin owner) {
- String ownerName = owner.getName();
- return new ToggleActionBuilder(NAME, ownerName)
- .description(DESCRIPTION)
- .menuGroup(GROUP_GENERAL)
- .menuPath(NAME)
- .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
- }
- }
-
interface CompareTimesAction {
String NAME = "Compare";
String DESCRIPTION = "Compare this point in time to another";
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java
new file mode 100644
index 0000000000..37fd5b948d
--- /dev/null
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java
@@ -0,0 +1,184 @@
+/* ###
+ * 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.plugin.core.debug.gui.memory;
+
+import java.awt.Font;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+
+import db.Transaction;
+import docking.ReusableDialogComponentProvider;
+import docking.widgets.model.GAddressRangeField;
+import docking.widgets.model.GSpanField;
+import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
+import ghidra.framework.plugintool.PluginTool;
+import ghidra.program.model.address.*;
+import ghidra.trace.model.Lifespan;
+import ghidra.trace.model.Trace;
+import ghidra.trace.model.memory.TraceOverlappedRegionException;
+import ghidra.util.exception.DuplicateNameException;
+import ghidra.util.layout.PairLayout;
+
+public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
+ private Trace trace;
+
+ private final JTextField fieldName = new JTextField();
+ private final GAddressRangeField fieldRange = new GAddressRangeField();
+ private final JTextField fieldLength = new JTextField();
+ private final GSpanField fieldLifespan = new GSpanField();
+ // NOTE: Flags can be toggled in table
+
+ public DebuggerAddRegionDialog() {
+ super("Add Region", true, true, true, false);
+
+ populateComponents();
+ }
+
+ protected void populateComponents() {
+ JPanel panel = new JPanel(new PairLayout(5, 5));
+
+ panel.setBorder(new EmptyBorder(10, 10, 10, 10));
+
+ panel.add(new JLabel("Name: "));
+ panel.add(fieldName);
+
+ panel.add(new JLabel("Range: "));
+ panel.add(fieldRange);
+
+ panel.add(new JLabel("Length: "));
+ fieldLength.setFont(Font.decode("monospaced"));
+ panel.add(fieldLength);
+
+ panel.add(new JLabel("Lifespan: "));
+ panel.add(fieldLifespan);
+
+ MiscellaneousUtils.rigFocusAndEnter(fieldRange, this::rangeChanged);
+ MiscellaneousUtils.rigFocusAndEnter(fieldLength, this::lengthChanged);
+
+ fieldLifespan.setLifespan(Lifespan.nowOn(0));
+
+ addWorkPanel(panel);
+
+ addOKButton();
+ addCancelButton();
+ }
+
+ protected static AddressRange range(Address min, long lengthMinus1) {
+ return new AddressRangeImpl(min, min.addWrap(lengthMinus1));
+ }
+
+ public void setName(String name) {
+ fieldName.setText(name);
+ }
+
+ protected void setFieldLength(long length) {
+ fieldLength.setText(MiscellaneousUtils.lengthToString(length));
+ }
+
+ public long getLength() {
+ return MiscellaneousUtils.parseLength(fieldLength.getText(), 1);
+ }
+
+ protected void revalidateLength() {
+ long length;
+ if (fieldLength.getText().trim().startsWith("-")) {
+ length = 1;
+ }
+ else {
+ length = getLength();
+ }
+ length = MiscellaneousUtils.revalidateLengthByRange(fieldRange.getRange(), length);
+ setFieldLength(length);
+ }
+
+ protected void adjustLengthToRange() {
+ AddressRange range = fieldRange.getRange();
+ if (range == null) {
+ return;
+ }
+ long length = range.getLength();
+ setFieldLength(length);
+ }
+
+ protected void adjustRangeToLength() {
+ AddressRange range = fieldRange.getRange();
+ if (range == null) {
+ return;
+ }
+ Address min = range.getMinAddress();
+ fieldRange.setRange(range(min, getLength() - 1));
+ }
+
+ protected void rangeChanged() {
+ adjustLengthToRange();
+ }
+
+ protected void lengthChanged() {
+ revalidateLength();
+ adjustRangeToLength();
+ }
+
+ @Override
+ protected void dialogShown() {
+ super.dialogShown();
+ setStatusText("");
+ }
+
+ @Override
+ protected void cancelCallback() {
+ setStatusText("");
+ super.cancelCallback();
+ }
+
+ @Override
+ protected void okCallback() {
+ addRegionAndClose();
+ }
+
+ protected void setValues(Trace trace, Lifespan lifespan) {
+ this.trace = trace;
+ AddressFactory af = trace.getBaseAddressFactory();
+ this.fieldRange.setAddressFactory(af);
+ this.fieldRange.setRange(range(af.getDefaultAddressSpace().getAddress(0), 0));
+ this.fieldLength.setText("0x1");
+ this.fieldLifespan.setLifespan(lifespan);
+ }
+
+ public void show(PluginTool tool, Trace trace, long snap) {
+ setValues(trace, Lifespan.nowOn(snap));
+ tool.showDialog(this);
+ }
+
+ @Override
+ public void close() {
+ trace = null;
+ fieldRange.setAddressFactory(null);
+ super.close();
+ }
+
+ protected void addRegionAndClose() {
+ try (Transaction tx = trace.openTransaction("Add region: " + fieldName)) {
+ trace.getMemoryManager()
+ .addRegion(fieldName.getText(), fieldLifespan.getLifespan(),
+ fieldRange.getRange());
+ close();
+ }
+ catch (TraceOverlappedRegionException | DuplicateNameException e) {
+ setStatusText(e.getMessage());
+ }
+ }
+}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java
index d11c6e6c5c..8764d66853 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProvider.java
@@ -24,15 +24,18 @@ import javax.swing.*;
import org.apache.commons.lang3.ArrayUtils;
+import db.Transaction;
import docking.ActionContext;
import docking.WindowPosition;
import docking.action.*;
import docking.action.builder.ActionBuilder;
+import docking.action.builder.ToggleActionBuilder;
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
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.AbstractSelectAddressesAction;
+import ghidra.app.plugin.core.debug.gui.DebuggerResources.SelectRowsAction;
import ghidra.app.plugin.core.debug.gui.model.DebuggerObjectActionContext;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider;
import ghidra.app.plugin.core.debug.service.modules.MapRegionsBackgroundCommand;
@@ -76,7 +79,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
- return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
+ return new ActionBuilder(NAME, ownerName)
+ .description(DESCRIPTION)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
@@ -91,7 +95,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
- return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
+ return new ActionBuilder(NAME_PREFIX, ownerName)
+ .description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
@@ -107,13 +112,62 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
- return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
+ return new ActionBuilder(NAME_PREFIX, ownerName)
+ .description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
+ interface AddRegionAction {
+ String NAME = "Add Region";
+ String DESCRIPTION = "Manually add a region to the memory map";
+ String GROUP = DebuggerResources.GROUP_MAINTENANCE;
+ String HELP_ANCHOR = "add_region";
+
+ static ActionBuilder builder(Plugin owner) {
+ String ownerName = owner.getName();
+ return new ActionBuilder(NAME, ownerName)
+ .description(DESCRIPTION)
+ .menuGroup(GROUP)
+ .menuPath(NAME)
+ .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
+ }
+ }
+
+ interface DeleteRegionsAction {
+ String NAME = "Delete Regions";
+ String DESCRIPTION = "Delete one or more regions from the memory map";
+ String GROUP = DebuggerResources.GROUP_MAINTENANCE;
+ String HELP_ANCHOR = "delete_regions";
+
+ static ActionBuilder builder(Plugin owner) {
+ String ownerName = owner.getName();
+ return new ActionBuilder(NAME, ownerName)
+ .description(DESCRIPTION)
+ .popupMenuGroup(GROUP)
+ .popupMenuPath(NAME, "Yes, really. Delete them!")
+ .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
+ }
+ }
+
+ interface ForceFullViewAction {
+ String NAME = "Force Full View";
+ String DESCRIPTION = "Ignore regions and fiew full address spaces";
+ String GROUP = DebuggerResources.GROUP_GENERAL;
+ String HELP_ANCHOR = "force_full_view";
+
+ static ToggleActionBuilder builder(Plugin owner) {
+ String ownerName = owner.getName();
+ return new ToggleActionBuilder(NAME, ownerName)
+ .description(DESCRIPTION)
+ .menuGroup(GROUP)
+ .menuPath(NAME)
+ .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
+ }
+ }
+
protected class SelectAddressesAction extends AbstractSelectAddressesAction {
public static final String GROUP = DebuggerResources.GROUP_GENERAL;
@@ -175,12 +229,16 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
// TODO: Lazy construction of these dialogs?
private final DebuggerBlockChooserDialog blockChooserDialog;
private final DebuggerRegionMapProposalDialog regionProposalDialog;
+ private final DebuggerAddRegionDialog addRegionDialog;
+
DockingAction actionMapRegions;
DockingAction actionMapRegionTo;
DockingAction actionMapRegionsTo;
SelectAddressesAction actionSelectAddresses;
DockingAction actionSelectRows;
+ DockingAction actionAddRegion;
+ DockingAction actionDeleteRegions;
ToggleDockingAction actionForceFullView;
public DebuggerRegionsProvider(DebuggerRegionsPlugin plugin) {
@@ -198,6 +256,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
blockChooserDialog = new DebuggerBlockChooserDialog(tool);
regionProposalDialog = new DebuggerRegionMapProposalDialog(this);
+ addRegionDialog = new DebuggerAddRegionDialog();
setDefaultWindowPosition(WindowPosition.BOTTOM);
setVisible(true);
@@ -237,6 +296,14 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
.enabledWhen(ctx -> current.getTrace() != null)
.onAction(this::activatedSelectCurrent)
.buildAndInstallLocal(this);
+ actionAddRegion = AddRegionAction.builder(plugin)
+ .enabledWhen(ctx -> current.getTrace() != null)
+ .onAction(this::activatedAddRegion)
+ .buildAndInstallLocal(this);
+ actionDeleteRegions = DeleteRegionsAction.builder(plugin)
+ .enabledWhen(this::isContextNonEmpty)
+ .onAction(this::activatedDeleteRegions)
+ .buildAndInstallLocal(this);
actionForceFullView = ForceFullViewAction.builder(plugin)
.enabledWhen(ctx -> current.getTrace() != null)
.onAction(this::activatedForceFullView)
@@ -385,6 +452,25 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
}
}
+ private void activatedAddRegion(ActionContext ignored) {
+ if (current.getTrace() == null) {
+ return;
+ }
+ addRegionDialog.show(tool, current.getTrace(), current.getSnap());
+ }
+
+ private void activatedDeleteRegions(ActionContext ctx) {
+ Set
- * Note that a returned value of 0 indicates 2 to the power 64, which is just 1 too high to fit
- * into a 64-bit long.
- *
- * @param text the text to parse
- * @param defaultVal the default value should parsing fail altogether
- * @return the length, where 0 indicates {@code 1 << 64}.
- */
- protected static long parseLength(String text, long defaultVal) {
- text = text.trim();
- String post;
- int radix;
- if (text.startsWith("-")) {
- return 0;
- }
- if (text.startsWith("0x")) {
- post = text.substring(2);
- radix = 16;
- }
- else {
- post = text;
- radix = 10;
- }
- BigInteger bi;
- try {
- bi = new BigInteger(post, radix);
- }
- catch (NumberFormatException e) {
- return defaultVal;
- }
- if (bi.equals(BigInteger.ZERO)) {
- return 1;
- }
- if (bi.bitLength() > 64) {
- return 0; // indicates 2**64, the max length
- }
- return bi.longValue(); // Do not use exact. It checks bitLength again, and considers sign.
- }
-
@Override
protected void dialogShown() {
super.dialogShown();
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java
index 618a38e4d4..874b849016 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java
@@ -16,17 +16,24 @@
package ghidra.app.plugin.core.debug.utils;
import java.awt.Component;
+import java.awt.event.*;
import java.beans.PropertyEditor;
+import java.math.BigInteger;
import java.util.Map;
import java.util.function.Function;
import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec;
import ghidra.framework.options.*;
+import ghidra.program.model.address.AddressRange;
+import ghidra.util.MathUtilities;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
public enum MiscellaneousUtils {
;
+
+ public static final String HEX_BIT64 = "0x" + BigInteger.ONE.shiftLeft(64).toString(16);
+
/**
* Obtain a swing component which may be used to edit the property.
*
@@ -63,6 +70,23 @@ public enum MiscellaneousUtils {
"Ghidra does not know how to use PropertyEditor: " + editor.getClass().getName());
}
+ public static void rigFocusAndEnter(Component c, Runnable runnable) {
+ c.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusLost(FocusEvent e) {
+ runnable.run();
+ }
+ });
+ c.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ runnable.run();
+ }
+ }
+ });
+ }
+
public static
+ * Note that a returned value of 0 indicates 2 to the power 64, which is just 1 too high to fit
+ * into a 64-bit long.
+ *
+ * @param text the text to parse
+ * @param defaultVal the default value should parsing fail altogether
+ * @return the length, where 0 indicates {@code 1 << 64}.
+ */
+ public static long parseLength(String text, long defaultVal) {
+ text = text.trim();
+ String post;
+ int radix;
+ if (text.startsWith("-")) {
+ return 0;
+ }
+ if (text.startsWith("0x")) {
+ post = text.substring(2);
+ radix = 16;
+ }
+ else {
+ post = text;
+ radix = 10;
+ }
+ BigInteger bi;
+ try {
+ bi = new BigInteger(post, radix);
+ }
+ catch (NumberFormatException e) {
+ return defaultVal;
+ }
+ if (bi.equals(BigInteger.ZERO)) {
+ return 1;
+ }
+ if (bi.bitLength() > 64) {
+ return 0; // indicates 2**64, the max length
+ }
+ return bi.longValue(); // Do not use exact. It checks bitLength again, and considers sign.
+ }
+
+ public static long revalidateLengthByRange(AddressRange range, long length) {
+ long maxLength =
+ range.getAddressSpace().getMaxAddress().subtract(range.getMinAddress()) + 1;
+ return MiscellaneousUtils.lengthMin(length, maxLength);
+ }
}
diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderLegacyTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderLegacyTest.java
index 618b6d2728..7908510505 100644
--- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderLegacyTest.java
+++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderLegacyTest.java
@@ -15,7 +15,8 @@
*/
package ghidra.app.plugin.core.debug.gui.memory;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import java.util.*;
@@ -354,6 +355,11 @@ public class DebuggerRegionsProviderLegacyTest extends AbstractGhidraHeadedDebug
new AddressSet(listing.getSelection())));
}
+ @Test
+ public void testActionAddRegion() throws Exception {
+ createAndOpenTrace();
+ }
+
@Test
public void testActionSelectRows() throws Exception {
addPlugin(tool, DebuggerListingPlugin.class);
diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java
index 6638f23661..db8a4f1981 100644
--- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java
+++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java
@@ -25,6 +25,7 @@ import org.junit.experimental.categories.Category;
import db.Transaction;
import docking.widgets.table.DynamicTableColumn;
+import generic.Unique;
import generic.test.category.NightlyCategory;
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
@@ -47,6 +48,7 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace;
+import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
import ghidra.trace.model.modules.TraceStaticMapping;
import ghidra.trace.model.target.*;
@@ -471,6 +473,25 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
new AddressSet(listing.getSelection())));
}
+ @Test
+ public void testActionAddRegion() throws Exception {
+ createAndOpenTrace();
+ traceManager.activateTrace(tb.trace);
+
+ performEnabledAction(provider, provider.actionAddRegion, false);
+ DebuggerAddRegionDialog dialog = waitForDialogComponent(DebuggerAddRegionDialog.class);
+ runSwing(() -> {
+ dialog.setName("Memory[heap]");
+ dialog.setFieldLength(0x1000);
+ dialog.lengthChanged(); // simulate ENTER/focus-exited
+ dialog.okCallback();
+ });
+ waitForSwing();
+
+ TraceMemoryRegion region = Unique.assertOne(tb.trace.getMemoryManager().getAllRegions());
+ assertEquals(tb.range(0, 0xfff), region.getRange());
+ }
+
@Test
public void testActionSelectRows() throws Exception {
addPlugin(tool, DebuggerListingPlugin.class);