mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-23 12:49:45 +00:00
GP-0: Fixed various Debugger and Assembler test issues
This commit is contained in:
parent
547a729feb
commit
8ab6690dff
@ -63,7 +63,8 @@ public abstract class AbstractTracePatchInstructionAction extends PatchInstructi
|
||||
public void setAddress(Address address) {
|
||||
super.setAddress(address);
|
||||
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
|
||||
AddressSetView set = new AddressSet(address, address.add(data.length - 1));
|
||||
TraceDisassembleCommand dis = new TraceDisassembleCommand(platform, address, set);
|
||||
dis.setInitialContext(contextValue);
|
||||
if (contextValue != null) {
|
||||
dis.setInitialContext(contextValue);
|
||||
}
|
||||
dis.run(tool, view);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -428,9 +428,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
new ProgramSelection(start, start.addWrap(1)), null);
|
||||
|
||||
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
|
||||
AssemblerPluginTestHelper helper =
|
||||
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null,
|
||||
listingProvider, tb.trace.getProgramView());
|
||||
DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
|
||||
disassemblerPlugin, listingProvider, tb.trace.getProgramView());
|
||||
Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr");
|
||||
|
||||
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);
|
||||
|
||||
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
|
||||
AssemblerPluginTestHelper helper =
|
||||
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null,
|
||||
listingProvider, tb.trace.getProgramView());
|
||||
DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
|
||||
disassemblerPlugin, listingProvider, tb.trace.getProgramView());
|
||||
Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr");
|
||||
|
||||
assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes());
|
||||
@ -502,9 +500,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
new ProgramSelection(start, start.addWrap(1)), null);
|
||||
|
||||
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
|
||||
AssemblerPluginTestHelper helper =
|
||||
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null,
|
||||
listingProvider, tb.trace.getProgramView());
|
||||
DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
|
||||
disassemblerPlugin, listingProvider, tb.trace.getProgramView());
|
||||
Instruction result = helper.patchInstructionAt(start, "andeq r0,r0,r0", "bx lr");
|
||||
|
||||
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);
|
||||
|
||||
assertTrue(disassemblerPlugin.actionPatchInstruction.isEnabledForContext(actionContext));
|
||||
AssemblerPluginTestHelper helper =
|
||||
new AssemblerPluginTestHelper(disassemblerPlugin.actionPatchInstruction, null,
|
||||
listingProvider, tb.trace.getProgramView());
|
||||
DebuggerDisassemblerPluginTestHelper helper = new DebuggerDisassemblerPluginTestHelper(
|
||||
disassemblerPlugin, listingProvider, tb.trace.getProgramView());
|
||||
Instruction result = helper.patchInstructionAt(start, "movs r0,r0", "bx lr");
|
||||
|
||||
assertArrayEquals(tb.arr(0x70, 0x47), result.getBytes());
|
||||
|
@ -33,6 +33,8 @@ import ghidra.app.plugin.core.assembler.AssemblerPlugin;
|
||||
import ghidra.app.plugin.core.assembler.AssemblerPluginTestHelper;
|
||||
import ghidra.app.plugin.core.clipboard.ClipboardPlugin;
|
||||
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.listing.DebuggerListingPlugin;
|
||||
import ghidra.app.services.DebuggerStateEditingService;
|
||||
@ -43,6 +45,7 @@ import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.program.TraceVariableSnapProgramView;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
/**
|
||||
@ -58,7 +61,8 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
|
||||
@Test
|
||||
public void testPatchInstructionActionInDynamicListingEmu() throws Throwable {
|
||||
DebuggerListingPlugin listingPlugin = addPlugin(tool, DebuggerListingPlugin.class);
|
||||
AssemblerPlugin assemblerPlugin = addPlugin(tool, AssemblerPlugin.class);
|
||||
DebuggerDisassemblerPlugin disassemblerPlugin =
|
||||
addPlugin(tool, DebuggerDisassemblerPlugin.class);
|
||||
DebuggerStateEditingPlugin editingPlugin =
|
||||
addPlugin(tool, DebuggerStateEditingPlugin.class);
|
||||
DebuggerStateEditingService editingService =
|
||||
@ -73,13 +77,17 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
|
||||
tb.trace.getMemoryManager()
|
||||
.createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000),
|
||||
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();
|
||||
AssemblerPluginTestHelper helper =
|
||||
new AssemblerPluginTestHelper(assemblerPlugin, listingProvider, view);
|
||||
DebuggerDisassemblerPluginTestHelper helper =
|
||||
new DebuggerDisassemblerPluginTestHelper(disassemblerPlugin, listingProvider, view);
|
||||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
Swing.runNow(
|
||||
() -> listingProvider.goTo(view, new ProgramLocation(view, tb.addr(0x00400123))));
|
||||
waitForSwing();
|
||||
|
||||
assertTrue(editingPlugin.actionEditMode.isEnabled());
|
||||
@ -96,7 +104,8 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
|
||||
|
||||
assertTrue(
|
||||
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());
|
||||
|
||||
long snap = traceManager.getCurrent().getViewSnap();
|
||||
|
@ -719,14 +719,14 @@ public class AssemblyDualTextField {
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @param text the prefix
|
||||
* @return the collection of completion items
|
||||
*/
|
||||
protected Collection<AssemblyCompletion> computeCompletions(String text) {
|
||||
final AssemblyPatternBlock ctx = getContext();
|
||||
final AssemblyPatternBlock ctx = Objects.requireNonNull(getContext());
|
||||
|
||||
Set<AssemblyCompletion> result = new TreeSet<>();
|
||||
Collection<AssemblyParseResult> parses = assembler.parseLine(text);
|
||||
@ -748,7 +748,7 @@ public class AssemblyDualTextField {
|
||||
for (AssemblyParseResult parse : parses) {
|
||||
if (!parse.isError()) {
|
||||
AssemblyResolutionResults sems =
|
||||
assembler.resolveTree(parse, address, getContext());
|
||||
assembler.resolveTree(parse, address, ctx);
|
||||
for (AssemblyResolution ar : sems) {
|
||||
if (ar.isError()) {
|
||||
//result.add(new AssemblyError("", ar.toString()));
|
||||
|
@ -45,8 +45,6 @@ public class PatchDataAction extends AbstractPatchAction {
|
||||
|
||||
/*test*/ final JTextField input = new JTextField();
|
||||
|
||||
private Data data;
|
||||
|
||||
public PatchDataAction(Plugin owner) {
|
||||
this(owner, "Patch Data");
|
||||
}
|
||||
@ -119,6 +117,7 @@ public class PatchDataAction extends AbstractPatchAction {
|
||||
public void accept() {
|
||||
Program program = getProgram();
|
||||
Address address = getAddress();
|
||||
Data data = getData();
|
||||
DataType dt = data.getBaseDataType();
|
||||
/**
|
||||
* Do as much outside the transaction as possible. The tool tends to steal focus away upon
|
||||
|
@ -82,7 +82,7 @@ public class AssemblerPluginTestHelper {
|
||||
AbstractGenericTest.runSwing(() -> {
|
||||
instructionInput.setText(text);
|
||||
instructionInput.auto.startCompletion(instructionInput.getOperandsField());
|
||||
instructionInput.auto.flushUpdates();
|
||||
instructionInput.auto.updateNow();
|
||||
});
|
||||
return AbstractGenericTest.waitForValue(() -> AbstractGenericTest.runSwing(() -> {
|
||||
List<AssemblyCompletion> suggestions = instructionInput.auto.getSuggestions();
|
||||
|
@ -755,6 +755,13 @@ public class TextFieldAutocompleter<T> {
|
||||
updateManager.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the completion list immediately
|
||||
*/
|
||||
public void updateNow() {
|
||||
updateManager.updateNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cause the suggestion at the given index to be selected
|
||||
*
|
||||
|
@ -200,7 +200,8 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
|
||||
*/
|
||||
protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly,
|
||||
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();
|
||||
dbg.println("Checking each: " + disassembly + " ctx:" + ctx);
|
||||
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,
|
||||
String ctxstr, boolean checkOneCompat, boolean checkAllExact,
|
||||
boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) {
|
||||
Address address = lang.getDefaultSpace().getAddress(addr);
|
||||
|
||||
// A sanity check, first
|
||||
if (instr != null) {
|
||||
@ -323,9 +325,8 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
|
||||
if (!ins.isFullMask()) {
|
||||
throw new RuntimeException("Desired instruction bytes should be fully-defined");
|
||||
}
|
||||
final AssemblyPatternBlock ctx =
|
||||
(ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr))
|
||||
.fillMask();
|
||||
final AssemblyPatternBlock ctx = (ctxstr == null ? context.getDefaultAt(address)
|
||||
: AssemblyPatternBlock.fromString(ctxstr)).fillMask();
|
||||
try {
|
||||
String disstr;
|
||||
PseudoInstruction psins = disassemble(addr, ins.getVals(), ctx.getVals());
|
||||
@ -374,12 +375,11 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
|
||||
|
||||
try {
|
||||
if (ctxstr == null) {
|
||||
assembler.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly);
|
||||
assembler.assembleLine(address, assembly);
|
||||
}
|
||||
else {
|
||||
SleighAssembler sas = (SleighAssembler) assembler;
|
||||
sas.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly,
|
||||
AssemblyPatternBlock.fromString(ctxstr));
|
||||
sas.assembleLine(address, assembly, AssemblyPatternBlock.fromString(ctxstr));
|
||||
}
|
||||
}
|
||||
catch (AssemblySemanticException e) {
|
||||
|
@ -207,7 +207,8 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
|
||||
*/
|
||||
protected void checkAllExact(AssemblyResolutionResults rr, Collection<String> disassembly,
|
||||
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();
|
||||
dbg.println("Checking each: " + disassembly + " ctx:" + ctx);
|
||||
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,
|
||||
String ctxstr, boolean checkOneCompat, boolean checkAllExact,
|
||||
boolean checkAllSyntaxErrs, boolean checkAllSemanticErrs) {
|
||||
Address address = lang.getDefaultSpace().getAddress(addr);
|
||||
|
||||
// A sanity check, first
|
||||
if (instr != null) {
|
||||
@ -330,7 +332,7 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
|
||||
if (!ins.isFullMask()) {
|
||||
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();
|
||||
try {
|
||||
String disstr;
|
||||
@ -380,12 +382,11 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
|
||||
|
||||
try {
|
||||
if (ctxstr == null) {
|
||||
assembler.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly);
|
||||
assembler.assembleLine(address, assembly);
|
||||
}
|
||||
else {
|
||||
SleighAssembler sas = (SleighAssembler) assembler;
|
||||
sas.assembleLine(lang.getDefaultSpace().getAddress(addr), assembly,
|
||||
AssemblyPatternBlock.fromString(ctxstr));
|
||||
sas.assembleLine(address, assembly, AssemblyPatternBlock.fromString(ctxstr));
|
||||
}
|
||||
}
|
||||
catch (AssemblySemanticException e) {
|
||||
|
Loading…
Reference in New Issue
Block a user