Added XGate/HCS12 Disassemble Action command.

This commit is contained in:
ghidorahrex 2019-08-13 07:49:38 -04:00
parent b107aa233b
commit d7934eaafc
3 changed files with 255 additions and 0 deletions

View file

@ -0,0 +1,141 @@
/* ###
* 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.cmd.disassemble;
import ghidra.framework.model.DomainObject;
import ghidra.program.disassemble.DisassemblerContextImpl;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.math.BigInteger;
/**
* Command object for performing HCS12/XGate disassembly
*/
public class Hcs12DisassembleCommand extends DisassembleCommand {
private boolean xgMode;
/**
* Constructor for Hcs12DisassembleCommand.
* @param startSet set of addresses to be the start of a disassembly. The
* Command object will attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled.
* a null set implies no restrictions
* @param xgMode pass true if the disassembling in XGATE Mode
*/
public Hcs12DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
boolean xgMode) {
super("Disassemble " + (xgMode ? "XGate" : "HCS12"), startSet, restrictedSet, true);
this.xgMode = xgMode;
}
/**
* Constructor for DisassembleCommand.
* @param startSet set of addresses to be the start of a disassembly. The
* Command object will attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled.
* a null set implies no restrictions
* @param xgMode pass true if the disassembling in XGATE Mode
*/
public Hcs12DisassembleCommand(Address start, AddressSetView restrictedSet, boolean xgMode) {
this(new AddressSet(start, start), restrictedSet, xgMode);
useDefaultRepeatPatternBehavior = true;
}
@Override
public void setSeedContext(DisassemblerContextImpl seedContext) {
throw new UnsupportedOperationException();
}
@Override
public void setInitialContext(RegisterValue initialContextValue) {
throw new UnsupportedOperationException();
}
/**
*
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
*/
@Override
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
Program program = (Program) obj;
disassemblyPerformed = false;
unalignedStart = false;
// get the XGATE mode register and set accordingly
Register xgmodeReg = program.getProgramContext().getRegister("XGATE");
RegisterValue xgmodeValue = null;
// if doing xgate, and have no XGmode reg, no way to do disassemble in xgate
if (xgmodeReg == null) {
if (xgMode) {
return false;
}
}
else {
xgmodeValue = new RegisterValue(xgmodeReg, BigInteger.valueOf(xgMode ? 0x1 : 0x0));
super.setInitialContext(xgmodeValue);
}
int alignment = 1;
// Set XGate Mode context on undefined code units only
try {
if (startSet != null) {
// Align startSet so that context only affected at possible instruction starts
AddressSet alignedSet = new AddressSet();
for (AddressRange range : startSet) {
Address min = range.getMinAddress();
long minOfffset = min.getOffset();
if (minOfffset != min.getOffset()) {
min = min.getNewAddress(minOfffset);
}
Address max = range.getMaxAddress();
long maxOffset = max.getOffset();
if (maxOffset < minOfffset) {
// skip short unaligned range
continue;
}
if (maxOffset != max.getOffset()) {
max = max.getNewAddress(maxOffset);
}
alignedSet.addRange(min, max);
}
if (alignedSet.isEmpty()) {
unalignedStart = true;
return false; // alignedSet does not contain any aligned starts
}
startSet = program.getListing().getUndefinedRanges(alignedSet, true, monitor);
if (startSet.isEmpty()) {
return true; // startSet does not contain any aligned undefined starts
}
}
}
catch (CancelledException e) {
return true;
}
return doDisassembly(monitor, program, alignment);
}
}

View file

@ -83,6 +83,8 @@ public class DisassemblerPlugin extends Plugin {
private DockingAction contextAction; private DockingAction contextAction;
private DockingAction armDisassembleAction; private DockingAction armDisassembleAction;
private DockingAction armThumbDisassembleAction; private DockingAction armThumbDisassembleAction;
private DockingAction hcs12DisassembleAction;
private DockingAction xgateDisassembleAction;
private DockingAction mipsDisassembleAction; private DockingAction mipsDisassembleAction;
private DockingAction mips16DisassembleAction; private DockingAction mips16DisassembleAction;
private DockingAction ppcDisassembleAction; private DockingAction ppcDisassembleAction;
@ -172,6 +174,8 @@ public class DisassemblerPlugin extends Plugin {
contextAction = new ContextAction(this, GROUP_NAME); contextAction = new ContextAction(this, GROUP_NAME);
armDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, false); armDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, false);
armThumbDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, true); armThumbDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, true);
hcs12DisassembleAction = new Hcs12DisassembleAction(this, GROUP_NAME, false);
xgateDisassembleAction = new Hcs12DisassembleAction(this, GROUP_NAME, true);
mipsDisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, false); mipsDisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, false);
mips16DisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, true); mips16DisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, true);
ppcDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, false); ppcDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, false);
@ -183,6 +187,8 @@ public class DisassemblerPlugin extends Plugin {
tool.addAction(disassembleStaticAction); tool.addAction(disassembleStaticAction);
tool.addAction(armDisassembleAction); tool.addAction(armDisassembleAction);
tool.addAction(armThumbDisassembleAction); tool.addAction(armThumbDisassembleAction);
tool.addAction(hcs12DisassembleAction);
tool.addAction(xgateDisassembleAction);
tool.addAction(mipsDisassembleAction); tool.addAction(mipsDisassembleAction);
tool.addAction(mips16DisassembleAction); tool.addAction(mips16DisassembleAction);
tool.addAction(ppcDisassembleAction); tool.addAction(ppcDisassembleAction);
@ -350,6 +356,30 @@ public class DisassemblerPlugin extends Plugin {
} }
} }
public void disassembleHcs12Callback(ListingActionContext context, boolean xgMode) {
ProgramSelection currentSelection = context.getSelection();
ProgramLocation currentLocation = context.getLocation();
Program currentProgram = context.getProgram();
Hcs12DisassembleCommand cmd = null;
if ((currentSelection != null) && (!currentSelection.isEmpty())) {
cmd = new Hcs12DisassembleCommand(currentSelection, null, xgMode);
}
else {
Address addr = currentLocation.getAddress();
try {
currentProgram.getMemory().getByte(addr);
cmd = new Hcs12DisassembleCommand(addr, null, xgMode);
}
catch (MemoryAccessException e) {
tool.setStatusInfo("Can't disassemble unitialized memory!", true);
}
}
if (cmd != null) {
tool.executeBackgroundCommand(cmd, currentProgram);
}
}
public void disassembleMipsCallback(ListingActionContext context, boolean mips16) { public void disassembleMipsCallback(ListingActionContext context, boolean mips16) {
ProgramSelection currentSelection = context.getSelection(); ProgramSelection currentSelection = context.getSelection();
ProgramLocation currentLocation = context.getLocation(); ProgramLocation currentLocation = context.getLocation();

View file

@ -0,0 +1,84 @@
/* ###
* 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.disassembler;
import java.awt.event.KeyEvent;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Program;
/**
* Action for HCS12 mode disassembly
*/
class Hcs12DisassembleAction extends ListingContextAction {
private DisassemblerPlugin plugin;
private boolean disassembleXgate = false;
public Hcs12DisassembleAction(DisassemblerPlugin plugin, String groupName, boolean disassembleXgate) {
super("Disassemble " + (disassembleXgate ? "HCS12" : "XGate"), plugin.getName());
this.plugin = plugin;
this.disassembleXgate = disassembleXgate;
setPopupMenuData( new MenuData(
new String[]{"Disassemble - "+ (disassembleXgate ? "XGate" : "HCS12") },
null,
groupName ) );
int keyEvent = (disassembleXgate ? KeyEvent.VK_F12 : KeyEvent.VK_F11);
setKeyBindingData( new KeyBindingData( keyEvent, 0 ) );
}
@Override
public void actionPerformed(ListingActionContext context) {
plugin.disassembleHcs12Callback(context, disassembleXgate);
}
@Override
public boolean isEnabledForContext(ListingActionContext context) {
// Action only intended for use where Xgate instructions are available.
// The presence of the XGATE context register can be used for this
// determination.
Address address = context.getAddress();
if ( address == null ) {
return false;
}
Program program = context.getProgram();
Language lang = program.getLanguage();
Processor proc = lang.getProcessor();
if (!"HCS12".equals(proc.toString())) {
return false;
}
Register register = context.getProgram().getProgramContext().getRegister("XGATE");
if (register == null) {
return false;
}
return plugin.checkDisassemblyEnabled(context, address, true);
}
}