Merge remote-tracking branch

'origin/GP-5164_Dan_addRegionManually--SQUASHED' (#7176)
This commit is contained in:
Ryan Kurtz 2024-12-04 11:03:21 -05:00
commit ce1e6bccdc
8 changed files with 84 additions and 34 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before After
Before After

View file

@ -4,9 +4,9 @@
* 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.
@ -16,6 +16,8 @@
package ghidra.app.plugin.core.debug.gui.memory;
import java.awt.Font;
import java.util.List;
import java.util.Set;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@ -25,18 +27,21 @@ import docking.ReusableDialogComponentProvider;
import docking.widgets.model.GAddressRangeField;
import docking.widgets.model.GSpanField;
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
import ghidra.dbg.target.TargetMemoryRegion;
import ghidra.dbg.target.schema.TargetObjectSchema;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
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.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.target.TraceObjectKeyPath;
import ghidra.util.layout.PairLayout;
public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
private Trace trace;
private final JTextField fieldName = new JTextField();
private final JTextField fieldPath = new JTextField();
private final GAddressRangeField fieldRange = new GAddressRangeField();
private final JTextField fieldLength = new JTextField();
private final GSpanField fieldLifespan = new GSpanField();
@ -53,8 +58,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.add(new JLabel("Name: "));
panel.add(fieldName);
panel.add(new JLabel("Path: "));
panel.add(fieldPath);
panel.add(new JLabel("Range: "));
panel.add(fieldRange);
@ -81,8 +86,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
return new AddressRangeImpl(min, min.addWrap(lengthMinus1));
}
public void setName(String name) {
fieldName.setText(name);
public void setPath(String path) {
fieldPath.setText(path);
}
protected void setFieldLength(long length) {
@ -149,17 +154,33 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
addRegionAndClose();
}
protected void setValues(Trace trace, Lifespan lifespan) {
this.trace = trace;
protected String computeDefaultPath(DebuggerCoordinates current) {
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
if (rootSchema == null) {
return "";
}
List<String> suitable = rootSchema.searchForSuitableContainer(TargetMemoryRegion.class,
current.getPath().getKeyList());
if (suitable == null) {
return "";
}
return TraceObjectKeyPath.of(suitable).index("New").toString();
}
protected void setValues(DebuggerCoordinates current) {
this.trace = current.getTrace();
AddressFactory af = trace.getBaseAddressFactory();
this.fieldRange.setAddressFactory(af);
this.fieldRange.setRange(range(af.getDefaultAddressSpace().getAddress(0), 0));
this.fieldLength.setText("0x1");
Lifespan lifespan = Lifespan.nowOn(current.getSnap());
this.fieldLifespan.setLifespan(lifespan);
this.fieldPath.setText(computeDefaultPath(current));
}
public void show(PluginTool tool, Trace trace, long snap) {
setValues(trace, Lifespan.nowOn(snap));
public void show(PluginTool tool, DebuggerCoordinates current) {
setValues(current);
tool.showDialog(this);
}
@ -171,13 +192,16 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
}
protected void addRegionAndClose() {
try (Transaction tx = trace.openTransaction("Add region: " + fieldName)) {
try (Transaction tx = trace.openTransaction("Add region: " + fieldPath)) {
trace.getMemoryManager()
.addRegion(fieldName.getText(), fieldLifespan.getLifespan(),
fieldRange.getRange());
.addRegion(
fieldPath.getText(),
fieldLifespan.getLifespan(), fieldRange.getRange(),
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.WRITE,
TraceMemoryFlag.EXECUTE));
close();
}
catch (TraceOverlappedRegionException | DuplicateNameException e) {
catch (Exception e) {
setStatusText(e.getMessage());
}
}

View file

@ -467,7 +467,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
if (current.getTrace() == null) {
return;
}
addRegionDialog.show(tool, current.getTrace(), current.getSnap());
addRegionDialog.show(tool, current);
}
private void activatedDeleteRegions(ActionContext ctx) {

View file

@ -4,9 +4,9 @@
* 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.
@ -495,7 +495,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
performEnabledAction(provider, provider.actionAddRegion, false);
DebuggerAddRegionDialog dialog = waitForDialogComponent(DebuggerAddRegionDialog.class);
runSwing(() -> {
dialog.setName("Memory[heap]");
dialog.setPath("Memory[heap]");
dialog.setFieldLength(0x1000);
dialog.lengthChanged(); // simulate ENTER/focus-exited
dialog.okCallback();

View file

@ -0,0 +1,30 @@
/* ###
* 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.dbg.target.schema;
/**
* An exception that indicates a path or object does not provide a required interface.
*/
public class BadSchemaException extends IllegalStateException {
/**
* Construct an exception with a human-readable message.
*
* @param message the message
*/
public BadSchemaException(String message) {
super(message);
}
}

View file

@ -5,7 +5,7 @@
* 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
* 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,
@ -893,12 +893,9 @@ public interface TargetObjectSchema {
List<TargetObjectSchema> schemas = getSuccessorSchemas(path);
for (; path != null; path = PathUtils.parent(path)) {
TargetObjectSchema schema = schemas.get(path.size());
if (!schema.isCanonicalContainer()) {
continue;
}
TargetObjectSchema deSchema =
schema.getContext().getSchema(schema.getDefaultElementSchema());
if (deSchema.getInterfaces().contains(type)) {
if (deSchema.getInterfaces().contains(type) && schema.isCanonicalContainer()) {
return path;
}
List<String> inAgg = Private.searchForSuitableContainerInAggregate(schema, type);

View file

@ -4,9 +4,9 @@
* 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.
@ -310,8 +310,7 @@ public class DBTraceObjectMemoryRegion implements TraceObjectMemoryRegion, DBTra
public void setFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
try (LockHold hold = object.getTrace().lockWrite()) {
for (TraceMemoryFlag flag : TraceMemoryFlag.values()) {
Boolean val = flags.contains(flag) ? true : null;
object.setValue(lifespan, keyForFlag(flag), val);
object.setValue(lifespan, keyForFlag(flag), flags.contains(flag));
}
}
}
@ -329,7 +328,7 @@ public class DBTraceObjectMemoryRegion implements TraceObjectMemoryRegion, DBTra
public void clearFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
try (LockHold hold = object.getTrace().lockWrite()) {
for (TraceMemoryFlag flag : flags) {
object.setValue(lifespan, keyForFlag(flag), null);
object.setValue(lifespan, keyForFlag(flag), false);
}
}
}

View file

@ -539,9 +539,9 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
Class<? extends TargetObject> targetIf = TraceObjectInterfaceUtils.toTargetIf(iface);
TargetObjectSchema schema = rootSchema.getSuccessorSchema(keyList);
if (!schema.getInterfaces().contains(targetIf)) {
throw new IllegalStateException(
"Schema " + schema + " at " + PathUtils.toString(keyList) +
" does not provide interface " + iface.getSimpleName());
throw new BadSchemaException(
"Schema " + schema + " at '" + PathUtils.toString(keyList) +
"' does not provide interface " + iface.getSimpleName());
}
DBTraceObject obj = createObject(TraceObjectKeyPath.of(keyList));
return obj.queryInterface(iface);