mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch
'origin/GP-5164_Dan_addRegionManually--SQUASHED' (#7176)
This commit is contained in:
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 |
|
@ -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,6 +16,8 @@
|
||||||
package ghidra.app.plugin.core.debug.gui.memory;
|
package ghidra.app.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
@ -25,18 +27,21 @@ import docking.ReusableDialogComponentProvider;
|
||||||
import docking.widgets.model.GAddressRangeField;
|
import docking.widgets.model.GAddressRangeField;
|
||||||
import docking.widgets.model.GSpanField;
|
import docking.widgets.model.GSpanField;
|
||||||
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
|
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.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.memory.TraceOverlappedRegionException;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.trace.model.target.TraceObjectKeyPath;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
|
|
||||||
public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
private Trace trace;
|
private Trace trace;
|
||||||
|
|
||||||
private final JTextField fieldName = new JTextField();
|
private final JTextField fieldPath = new JTextField();
|
||||||
private final GAddressRangeField fieldRange = new GAddressRangeField();
|
private final GAddressRangeField fieldRange = new GAddressRangeField();
|
||||||
private final JTextField fieldLength = new JTextField();
|
private final JTextField fieldLength = new JTextField();
|
||||||
private final GSpanField fieldLifespan = new GSpanField();
|
private final GSpanField fieldLifespan = new GSpanField();
|
||||||
|
@ -53,8 +58,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
|
|
||||||
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
panel.add(new JLabel("Name: "));
|
panel.add(new JLabel("Path: "));
|
||||||
panel.add(fieldName);
|
panel.add(fieldPath);
|
||||||
|
|
||||||
panel.add(new JLabel("Range: "));
|
panel.add(new JLabel("Range: "));
|
||||||
panel.add(fieldRange);
|
panel.add(fieldRange);
|
||||||
|
@ -81,8 +86,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
return new AddressRangeImpl(min, min.addWrap(lengthMinus1));
|
return new AddressRangeImpl(min, min.addWrap(lengthMinus1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setPath(String path) {
|
||||||
fieldName.setText(name);
|
fieldPath.setText(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setFieldLength(long length) {
|
protected void setFieldLength(long length) {
|
||||||
|
@ -149,17 +154,33 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
addRegionAndClose();
|
addRegionAndClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setValues(Trace trace, Lifespan lifespan) {
|
protected String computeDefaultPath(DebuggerCoordinates current) {
|
||||||
this.trace = trace;
|
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();
|
AddressFactory af = trace.getBaseAddressFactory();
|
||||||
this.fieldRange.setAddressFactory(af);
|
this.fieldRange.setAddressFactory(af);
|
||||||
this.fieldRange.setRange(range(af.getDefaultAddressSpace().getAddress(0), 0));
|
this.fieldRange.setRange(range(af.getDefaultAddressSpace().getAddress(0), 0));
|
||||||
this.fieldLength.setText("0x1");
|
this.fieldLength.setText("0x1");
|
||||||
|
Lifespan lifespan = Lifespan.nowOn(current.getSnap());
|
||||||
this.fieldLifespan.setLifespan(lifespan);
|
this.fieldLifespan.setLifespan(lifespan);
|
||||||
|
this.fieldPath.setText(computeDefaultPath(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show(PluginTool tool, Trace trace, long snap) {
|
public void show(PluginTool tool, DebuggerCoordinates current) {
|
||||||
setValues(trace, Lifespan.nowOn(snap));
|
setValues(current);
|
||||||
tool.showDialog(this);
|
tool.showDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,13 +192,16 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addRegionAndClose() {
|
protected void addRegionAndClose() {
|
||||||
try (Transaction tx = trace.openTransaction("Add region: " + fieldName)) {
|
try (Transaction tx = trace.openTransaction("Add region: " + fieldPath)) {
|
||||||
trace.getMemoryManager()
|
trace.getMemoryManager()
|
||||||
.addRegion(fieldName.getText(), fieldLifespan.getLifespan(),
|
.addRegion(
|
||||||
fieldRange.getRange());
|
fieldPath.getText(),
|
||||||
|
fieldLifespan.getLifespan(), fieldRange.getRange(),
|
||||||
|
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.WRITE,
|
||||||
|
TraceMemoryFlag.EXECUTE));
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
catch (TraceOverlappedRegionException | DuplicateNameException e) {
|
catch (Exception e) {
|
||||||
setStatusText(e.getMessage());
|
setStatusText(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -467,7 +467,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
if (current.getTrace() == null) {
|
if (current.getTrace() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRegionDialog.show(tool, current.getTrace(), current.getSnap());
|
addRegionDialog.show(tool, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activatedDeleteRegions(ActionContext ctx) {
|
private void activatedDeleteRegions(ActionContext ctx) {
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -495,7 +495,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
||||||
performEnabledAction(provider, provider.actionAddRegion, false);
|
performEnabledAction(provider, provider.actionAddRegion, false);
|
||||||
DebuggerAddRegionDialog dialog = waitForDialogComponent(DebuggerAddRegionDialog.class);
|
DebuggerAddRegionDialog dialog = waitForDialogComponent(DebuggerAddRegionDialog.class);
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
dialog.setName("Memory[heap]");
|
dialog.setPath("Memory[heap]");
|
||||||
dialog.setFieldLength(0x1000);
|
dialog.setFieldLength(0x1000);
|
||||||
dialog.lengthChanged(); // simulate ENTER/focus-exited
|
dialog.lengthChanged(); // simulate ENTER/focus-exited
|
||||||
dialog.okCallback();
|
dialog.okCallback();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
* 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,
|
||||||
|
@ -893,12 +893,9 @@ public interface TargetObjectSchema {
|
||||||
List<TargetObjectSchema> schemas = getSuccessorSchemas(path);
|
List<TargetObjectSchema> schemas = getSuccessorSchemas(path);
|
||||||
for (; path != null; path = PathUtils.parent(path)) {
|
for (; path != null; path = PathUtils.parent(path)) {
|
||||||
TargetObjectSchema schema = schemas.get(path.size());
|
TargetObjectSchema schema = schemas.get(path.size());
|
||||||
if (!schema.isCanonicalContainer()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TargetObjectSchema deSchema =
|
TargetObjectSchema deSchema =
|
||||||
schema.getContext().getSchema(schema.getDefaultElementSchema());
|
schema.getContext().getSchema(schema.getDefaultElementSchema());
|
||||||
if (deSchema.getInterfaces().contains(type)) {
|
if (deSchema.getInterfaces().contains(type) && schema.isCanonicalContainer()) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
List<String> inAgg = Private.searchForSuitableContainerInAggregate(schema, type);
|
List<String> inAgg = Private.searchForSuitableContainerInAggregate(schema, type);
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -310,8 +310,7 @@ public class DBTraceObjectMemoryRegion implements TraceObjectMemoryRegion, DBTra
|
||||||
public void setFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
|
public void setFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
|
||||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||||
for (TraceMemoryFlag flag : TraceMemoryFlag.values()) {
|
for (TraceMemoryFlag flag : TraceMemoryFlag.values()) {
|
||||||
Boolean val = flags.contains(flag) ? true : null;
|
object.setValue(lifespan, keyForFlag(flag), flags.contains(flag));
|
||||||
object.setValue(lifespan, keyForFlag(flag), val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +328,7 @@ public class DBTraceObjectMemoryRegion implements TraceObjectMemoryRegion, DBTra
|
||||||
public void clearFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
|
public void clearFlags(Lifespan lifespan, Collection<TraceMemoryFlag> flags) {
|
||||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||||
for (TraceMemoryFlag flag : flags) {
|
for (TraceMemoryFlag flag : flags) {
|
||||||
object.setValue(lifespan, keyForFlag(flag), null);
|
object.setValue(lifespan, keyForFlag(flag), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -539,9 +539,9 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager
|
||||||
Class<? extends TargetObject> targetIf = TraceObjectInterfaceUtils.toTargetIf(iface);
|
Class<? extends TargetObject> targetIf = TraceObjectInterfaceUtils.toTargetIf(iface);
|
||||||
TargetObjectSchema schema = rootSchema.getSuccessorSchema(keyList);
|
TargetObjectSchema schema = rootSchema.getSuccessorSchema(keyList);
|
||||||
if (!schema.getInterfaces().contains(targetIf)) {
|
if (!schema.getInterfaces().contains(targetIf)) {
|
||||||
throw new IllegalStateException(
|
throw new BadSchemaException(
|
||||||
"Schema " + schema + " at " + PathUtils.toString(keyList) +
|
"Schema " + schema + " at '" + PathUtils.toString(keyList) +
|
||||||
" does not provide interface " + iface.getSimpleName());
|
"' does not provide interface " + iface.getSimpleName());
|
||||||
}
|
}
|
||||||
DBTraceObject obj = createObject(TraceObjectKeyPath.of(keyList));
|
DBTraceObject obj = createObject(TraceObjectKeyPath.of(keyList));
|
||||||
return obj.queryInterface(iface);
|
return obj.queryInterface(iface);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue