In a Ghidra Java extension how can I achieve what the "Convert" context menu item does in the GUI? #6944
-
In the Ghidra UI there is a "Convert" function on data that lets you change signedness, decimal vs hex, etc: (Originally asked on StackExchange) |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 2 replies
-
You can look at The actual source for the plugin is here:
They are just DockingActions. The EquatePlugin1Test externally accesses these as part of a test unit. |
Beta Was this translation helpful? Give feedback.
-
You will need to potentially base your own class off ListingContextAction. I'm not sure if you can extend/inherit from EquatePlugin.
@dragonmacher (or any other team member) will be able to answer the latter question (if you can use a core plugin's classes from within your own extension). I believe so, but I am not sure about best practices. Technically with Java you can do virtually anything as far as loaded classes are involved. Again, take inspiration from the test unit plugin. |
Beta Was this translation helpful? Give feedback.
-
As mentioned by @sbrptdev2, the actions are created by the tool.addAction(new ConvertToUnsignedHexAction(this));
tool.addAction(new ConvertToUnsignedDecimalAction(this));
tool.addAction(new ConvertToOctalAction(this));
tool.addAction(new ConvertToSignedHexAction(this));
tool.addAction(new ConvertToSignedDecimalAction(this));
tool.addAction(new ConvertToCharAction(this));
tool.addAction(new ConvertToBinaryAction(this));
tool.addAction(new ConvertToFloatAction(this));
tool.addAction(new ConvertToDoubleAction(this)); If you just wish to see how the actions work, then you can just look inside each action. Typically, each action just calls some utility method that you should be able to call from your code. This may be obvious, but if you are writing loader code, then you do not want to create actions, but just use the code that they use, as needed. |
Beta Was this translation helpful? Give feedback.
-
I'm wondering if I was too vague in my original question. I don't need to access the context menu or the plugin (I think). In my loader where I figure out the file format I add comments and set datatypes like this: listing.createData(addr, ByteDataType.dataType);
listing.setComment(addr, CodeUnit.EOL_COMMENT, "My signed decimal byte"); And I'm wondering how I can get that byte to display as a signed decimal rather than as the default hex. I see |
Beta Was this translation helpful? Give feedback.
-
There's a bit to unpack in this snippet, but this is how the actions work. My intention was to show the code that the actions use, so you could build what you needed. Inside of private String applyEquate(Instruction instruction, int opIndex, int subOpIndex) {
if (instruction == null || opIndex == -1) {
return null;
}
Scalar scalar = grabMatchingScalar(instruction, opIndex, subOpIndex);
if (scalar == null) {
return null;
}
String equateName = action.convertToString(program, scalar, false);
if (equateName.isEmpty()) {
return null;
}
// Check for same named equate with different value.
EquateTable equateTable = program.getEquateTable();
Equate eqt = equateTable.getEquate(equateName);
if (eqt != null && valuesAreDifferent(eqt, scalar)) {
return "Couldn't convert to " + equateName + ". " + "Equate named " + equateName +
" already exists with value of " + eqt.getValue() + ".";
}
Address address = instruction.getAddress();
List<Equate> equates = equateTable.getEquates(address, opIndex);
// First, clear any existing equates with the same value
for (Equate equate : equates) {
if (!valuesAreDifferent(equate, scalar)) {
// Clears matching equates
ClearEquateCmd cmd = new ClearEquateCmd(equate.getName(), address, opIndex);
cmd.applyTo(program);
}
}
// check if default hex scalar format applies
if (action.getFormatChoice() == FormatSettingsDefinition.HEX) {
if (scalar.getSignedValue() >= 0 || action.isSignedChoice() == scalar.isSigned()) {
return null;
}
}
// Then, add the new equate
SetEquateCmd cmd = new SetEquateCmd(equateName, address, opIndex, scalar.getValue());
if (!cmd.applyTo(program)) {
return "Couldn't convert to " + equateName + ". " + cmd.getStatusMsg();
}
return null;
} The basic flow is to:
You would need to do something similar, but with much less housekeeping code. Also, context actions in Ghidra are just a way to plug functionality into the GUI. They are typically backed by a command object that gets run in the background. If you find an action in the GUI that you want to know more about, you can find it in the source code to see what type of command or utility code it is using. |
Beta Was this translation helpful? Give feedback.
Aha thanks. Took me a bit to chase down that I can access this
FormatSettingsDefinition
from inside a Loader in Java like this:I can't test it since I've forgotten where I needed it while down the Sleigh rabbithole but I have the snippet now when I need it.