Merge remote-tracking branch 'origin/GP-0_Dan_testFixes-20220627-1--SQUASHED'

This commit is contained in:
ghidra1 2022-06-27 14:33:06 -04:00
commit 22af19c500
10 changed files with 78 additions and 36 deletions

View File

@ -63,7 +63,8 @@ public abstract class AbstractTracePatchInstructionAction extends PatchInstructi
public void setAddress(Address address) { public void setAddress(Address address) {
super.setAddress(address); super.setAddress(address);
RegisterValue rv = getContextValue(getCodeUnit()); RegisterValue rv = getContextValue(getCodeUnit());
ctx = AssemblyPatternBlock.fromRegisterValue(rv).fillMask(); ctx = rv == null ? AssemblyPatternBlock.nop()
: AssemblyPatternBlock.fromRegisterValue(rv).fillMask();
} }
}; };
} }
@ -126,7 +127,9 @@ public abstract class AbstractTracePatchInstructionAction extends PatchInstructi
view.getMemory().setBytes(address, data); // This invalidates cu view.getMemory().setBytes(address, data); // This invalidates cu
AddressSetView set = new AddressSet(address, address.add(data.length - 1)); AddressSetView set = new AddressSet(address, address.add(data.length - 1));
TraceDisassembleCommand dis = new TraceDisassembleCommand(platform, address, set); TraceDisassembleCommand dis = new TraceDisassembleCommand(platform, address, set);
dis.setInitialContext(contextValue); if (contextValue != null) {
dis.setInitialContext(contextValue);
}
dis.run(tool, view); dis.run(tool, view);
} }

View File

@ -0,0 +1,27 @@
/* ###
* 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.disassemble;
import ghidra.app.plugin.core.assembler.AssemblerPluginTestHelper;
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.program.model.listing.Program;
public class DebuggerDisassemblerPluginTestHelper extends AssemblerPluginTestHelper {
public DebuggerDisassemblerPluginTestHelper(DebuggerDisassemblerPlugin disassemblerPlugin,
CodeViewerProvider provider, Program program) {
super(disassemblerPlugin.actionPatchInstruction, null, provider, program);
}
}

View File

@ -428,9 +428,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
new ProgramSelection(start, start.addWrap(1)), null); new ProgramSelection(start, start.addWrap(1)), null);
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext)); assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
AssemblerPluginTestHelper helper = DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null, disassemblerPlugin, listingProvider, tb.trace.getProgramView());
listingProvider, tb.trace.getProgramView());
Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr"); Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr");
assertArrayEquals(tb.arr(0x1e, 0xff, 0x2f, 0xe1), result.getBytes()); assertArrayEquals(tb.arr(0x1e, 0xff, 0x2f, 0xe1), result.getBytes());
@ -466,9 +465,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
new ProgramSelection(start, start.addWrap(1)), null); new ProgramSelection(start, start.addWrap(1)), null);
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext)); assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
AssemblerPluginTestHelper helper = DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null, disassemblerPlugin, listingProvider, tb.trace.getProgramView());
listingProvider, tb.trace.getProgramView());
Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr"); Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr");
assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes()); assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes());
@ -502,9 +500,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
new ProgramSelection(start, start.addWrap(1)), null); new ProgramSelection(start, start.addWrap(1)), null);
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext)); assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
AssemblerPluginTestHelper helper = DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null, disassemblerPlugin, listingProvider, tb.trace.getProgramView());
listingProvider, tb.trace.getProgramView());
Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr"); Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr");
assertArrayEquals(tb.arr(0x1e, 0xff, 0x2f, 0xe1), result.getBytes()); assertArrayEquals(tb.arr(0x1e, 0xff, 0x2f, 0xe1), result.getBytes());
@ -543,9 +540,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
new ProgramSelection(start, start.addWrap(1)), null); new ProgramSelection(start, start.addWrap(1)), null);
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext)); assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
AssemblerPluginTestHelper helper = DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null, disassemblerPlugin, listingProvider, tb.trace.getProgramView());
listingProvider, tb.trace.getProgramView());
Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr"); Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr");
assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes()); assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes());

View File

@ -33,6 +33,8 @@ import ghidra.app.plugin.core.assembler.AssemblerPlugin;
import ghidra.app.plugin.core.assembler.AssemblerPluginTestHelper; import ghidra.app.plugin.core.assembler.AssemblerPluginTestHelper;
import ghidra.app.plugin.core.clipboard.ClipboardPlugin; import ghidra.app.plugin.core.clipboard.ClipboardPlugin;
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.app.plugin.core.debug.disassemble.DebuggerDisassemblerPlugin;
import ghidra.app.plugin.core.debug.disassemble.DebuggerDisassemblerPluginTestHelper;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.services.DebuggerStateEditingService; import ghidra.app.services.DebuggerStateEditingService;
@ -43,6 +45,7 @@ import ghidra.program.util.ProgramLocation;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.program.TraceVariableSnapProgramView; import ghidra.trace.model.program.TraceVariableSnapProgramView;
import ghidra.util.Swing;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
/** /**
@ -58,7 +61,8 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
@Test @Test
public void testPatchInstructionActionInDynamicListingEmu() throws Throwable { public void testPatchInstructionActionInDynamicListingEmu() throws Throwable {
DebuggerListingPlugin listingPlugin = addPlugin(tool, DebuggerListingPlugin.class); DebuggerListingPlugin listingPlugin = addPlugin(tool, DebuggerListingPlugin.class);
AssemblerPlugin assemblerPlugin = addPlugin(tool, AssemblerPlugin.class); DebuggerDisassemblerPlugin disassemblerPlugin =
addPlugin(tool, DebuggerDisassemblerPlugin.class);
DebuggerStateEditingPlugin editingPlugin = DebuggerStateEditingPlugin editingPlugin =
addPlugin(tool, DebuggerStateEditingPlugin.class); addPlugin(tool, DebuggerStateEditingPlugin.class);
DebuggerStateEditingService editingService = DebuggerStateEditingService editingService =
@ -73,13 +77,17 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
tb.trace.getMemoryManager() tb.trace.getMemoryManager()
.createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000), .createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000),
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE));
// Dynamic Patch Instruction requires existing code unit for context
tb.addInstruction(0, tb.addr(0x00400123), tb.host);
} }
CodeViewerProvider listingProvider = listingPlugin.getProvider(); CodeViewerProvider listingProvider = listingPlugin.getProvider();
AssemblerPluginTestHelper helper = DebuggerDisassemblerPluginTestHelper helper =
new AssemblerPluginTestHelper(assemblerPlugin, listingProvider, view); new DebuggerDisassemblerPluginTestHelper(disassemblerPlugin, listingProvider, view);
traceManager.activateTrace(tb.trace); traceManager.activateTrace(tb.trace);
Swing.runNow(
() -> listingProvider.goTo(view, new ProgramLocation(view, tb.addr(0x00400123))));
waitForSwing(); waitForSwing();
assertTrue(editingPlugin.actionEditMode.isEnabled()); assertTrue(editingPlugin.actionEditMode.isEnabled());
@ -96,7 +104,8 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
assertTrue( assertTrue(
helper.patchInstructionAction.isAddToPopup(listingProvider.getActionContext(null))); helper.patchInstructionAction.isAddToPopup(listingProvider.getActionContext(null)));
Instruction ins = helper.patchInstructionAt(tb.addr(0x00400123), "", "imm r0,#1234"); Instruction ins =
helper.patchInstructionAt(tb.addr(0x00400123), "imm r0,#0x0", "imm r0,#1234");
assertEquals(2, ins.getLength()); assertEquals(2, ins.getLength());
long snap = traceManager.getCurrent().getViewSnap(); long snap = traceManager.getCurrent().getViewSnap();

View File

@ -719,14 +719,14 @@ public class AssemblyDualTextField {
* If text parses and assembles, then the completion set will include assembled instruction-byte * If text parses and assembles, then the completion set will include assembled instruction-byte
* entries. Note that there may still be valid textual completions to continue the instruction. * entries. Note that there may still be valid textual completions to continue the instruction.
* The suggestions yielded by all syntax errors are used to create textual completions. If the * The suggestions yielded by all syntax errors are used to create textual completions. If the
* suggestion is prefixed by the buffer where the syntax error ocurred, then, the tail of that * suggestion is prefixed by the buffer where the syntax error occurred, then, the tail of that
* suggestion is made into a completion entry. * suggestion is made into a completion entry.
* *
* @param text the prefix * @param text the prefix
* @return the collection of completion items * @return the collection of completion items
*/ */
protected Collection<AssemblyCompletion> computeCompletions(String text) { protected Collection<AssemblyCompletion> computeCompletions(String text) {
final AssemblyPatternBlock ctx = getContext(); final AssemblyPatternBlock ctx = Objects.requireNonNull(getContext());
Set<AssemblyCompletion> result = new TreeSet<>(); Set<AssemblyCompletion> result = new TreeSet<>();
Collection<AssemblyParseResult> parses = assembler.parseLine(text); Collection<AssemblyParseResult> parses = assembler.parseLine(text);
@ -748,7 +748,7 @@ public class AssemblyDualTextField {
for (AssemblyParseResult parse : parses) { for (AssemblyParseResult parse : parses) {
if (!parse.isError()) { if (!parse.isError()) {
AssemblyResolutionResults sems = AssemblyResolutionResults sems =
assembler.resolveTree(parse, address, getContext()); assembler.resolveTree(parse, address, ctx);
for (AssemblyResolution ar : sems) { for (AssemblyResolution ar : sems) {
if (ar.isError()) { if (ar.isError()) {
//result.add(new AssemblyError("", ar.toString())); //result.add(new AssemblyError("", ar.toString()));

View File

@ -45,8 +45,6 @@ public class PatchDataAction extends AbstractPatchAction {
/*test*/ final JTextField input = new JTextField(); /*test*/ final JTextField input = new JTextField();
private Data data;
public PatchDataAction(Plugin owner) { public PatchDataAction(Plugin owner) {
this(owner, "Patch Data"); this(owner, "Patch Data");
} }
@ -119,6 +117,7 @@ public class PatchDataAction extends AbstractPatchAction {
public void accept() { public void accept() {
Program program = getProgram(); Program program = getProgram();
Address address = getAddress(); Address address = getAddress();
Data data = getData();
DataType dt = data.getBaseDataType(); DataType dt = data.getBaseDataType();
/** /**
* Do as much outside the transaction as possible. The tool tends to steal focus away upon * Do as much outside the transaction as possible. The tool tends to steal focus away upon

View File

@ -82,7 +82,7 @@ public class AssemblerPluginTestHelper {
AbstractGenericTest.runSwing(() -> { AbstractGenericTest.runSwing(() -> {
instructionInput.setText(text); instructionInput.setText(text);
instructionInput.auto.startCompletion(instructionInput.getOperandsField()); instructionInput.auto.startCompletion(instructionInput.getOperandsField());
instructionInput.auto.flushUpdates(); instructionInput.auto.updateNow();
}); });
return AbstractGenericTest.waitForValue(() -> AbstractGenericTest.runSwing(() -> { return AbstractGenericTest.waitForValue(() -> AbstractGenericTest.runSwing(() -> {
List<AssemblyCompletion> suggestions = instructionInput.auto.getSuggestions(); List<AssemblyCompletion> suggestions = instructionInput.auto.getSuggestions();

View File

@ -755,6 +755,13 @@ public class TextFieldAutocompleter<T> {
updateManager.flush(); updateManager.flush();
} }
/**
* Update the completion list immediately
*/
public void updateNow() {
updateManager.updateNow();
}
/** /**
* Cause the suggestion at the given index to be selected * Cause the suggestion at the given index to be selected
* *

View File

@ -200,7 +200,8 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
*/ */
protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly, protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly,
long addr, String ctxstr) { long addr, String ctxstr) {
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefault() Address address = lang.getDefaultSpace().getAddress(addr);
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefaultAt(address)
: AssemblyPatternBlock.fromString(ctxstr)).fillMask(); : AssemblyPatternBlock.fromString(ctxstr)).fillMask();
dbg.println("Checking each: " + disassembly + " ctx:" + ctx); dbg.println("Checking each: " + disassembly + " ctx:" + ctx);
boolean gotOne = false; boolean gotOne = false;
@ -316,6 +317,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
protected void runTest(String assembly, String instr, Collection<String> disassembly, long addr, protected void runTest(String assembly, String instr, Collection<String> disassembly, long addr,
String ctxstr, boolean checkOneCompat, boolean checkAllExact, String ctxstr, boolean checkOneCompat, boolean checkAllExact,
boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) { boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) {
Address address = lang.getDefaultSpace().getAddress(addr);
// A sanity check, first // A sanity check, first
if (instr != null) { if (instr != null) {
@ -323,9 +325,8 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
if (!ins.isFullMask()) { if (!ins.isFullMask()) {
throw new RuntimeException("Desired instruction bytes should be fully-defined"); throw new RuntimeException("Desired instruction bytes should be fully-defined");
} }
final AssemblyPatternBlock ctx = final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefaultAt(address)
(ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr)) : AssemblyPatternBlock.fromString(ctxstr)).fillMask();
.fillMask();
try { try {
String disstr; String disstr;
PseudoInstruction psins = disassemble(addr, ins.getVals(), ctx.getVals()); PseudoInstruction psins = disassemble(addr, ins.getVals(), ctx.getVals());
@ -374,12 +375,11 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
try { try {
if (ctxstr == null) { if (ctxstr == null) {
assembler.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly); assembler.assembleLine(address, assembly);
} }
else { else {
SleighAssembler sas = (SleighAssembler) assembler; SleighAssembler sas = (SleighAssembler) assembler;
sas.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly, sas.assembleLine(address, assembly, AssemblyPatternBlock.fromString(ctxstr));
AssemblyPatternBlock.fromString(ctxstr));
} }
} }
catch (AssemblySemanticException e) { catch (AssemblySemanticException e) {

View File

@ -207,7 +207,8 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
*/ */
protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly, protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly,
long addr, String ctxstr) { long addr, String ctxstr) {
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefault() Address address = lang.getDefaultSpace().getAddress(addr);
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefaultAt(address)
: AssemblyPatternBlock.fromString(ctxstr)).fillMask(); : AssemblyPatternBlock.fromString(ctxstr)).fillMask();
dbg.println("Checking each: " + disassembly + " ctx:" + ctx); dbg.println("Checking each: " + disassembly + " ctx:" + ctx);
boolean gotOne = false; boolean gotOne = false;
@ -323,6 +324,7 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
protected void runTest(String assembly, String instr, Collection<String> disassembly, long addr, protected void runTest(String assembly, String instr, Collection<String> disassembly, long addr,
String ctxstr, boolean checkOneCompat, boolean checkAllExact, String ctxstr, boolean checkOneCompat, boolean checkAllExact,
boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) { boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) {
Address address = lang.getDefaultSpace().getAddress(addr);
// A sanity check, first // A sanity check, first
if (instr != null) { if (instr != null) {
@ -330,7 +332,7 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
if (!ins.isFullMask()) { if (!ins.isFullMask()) {
throw new RuntimeException("Desired instruction bytes should be fully-defined"); throw new RuntimeException("Desired instruction bytes should be fully-defined");
} }
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefault() final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefaultAt(address)
: AssemblyPatternBlock.fromString(ctxstr)).fillMask(); : AssemblyPatternBlock.fromString(ctxstr)).fillMask();
try { try {
String disstr; String disstr;
@ -380,12 +382,11 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
try { try {
if (ctxstr == null) { if (ctxstr == null) {
assembler.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly); assembler.assembleLine(address, assembly);
} }
else { else {
SleighAssembler sas = (SleighAssembler) assembler; SleighAssembler sas = (SleighAssembler) assembler;
sas.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly, sas.assembleLine(address, assembly, AssemblyPatternBlock.fromString(ctxstr));
AssemblyPatternBlock.fromString(ctxstr));
} }
} }
catch (AssemblySemanticException e) { catch (AssemblySemanticException e) {