mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-12-30 18:49:42 -06:00
GP-6227 - Byte Viewer - Fixed configure options dialog to handle
programs with no min address
This commit is contained in:
@@ -225,7 +225,7 @@ public class AddressInput extends JPanel implements FocusableEditor {
|
||||
/**
|
||||
* Gets the current address the field evaluates to or null if the text does not evaluate to
|
||||
* a valid, unique address.
|
||||
* @return the current address the field evalutes to or null if the text does not evalute to
|
||||
* @return the current address the field evaluates to or null if the text does not evaluate to
|
||||
* a valid unique address.
|
||||
*/
|
||||
public Address getAddress() {
|
||||
|
||||
@@ -28,12 +28,13 @@ import javax.swing.border.Border;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.widgets.checkbox.GCheckBox;
|
||||
import docking.widgets.label.GLabel;
|
||||
import generic.theme.GThemeDefaults.Colors;
|
||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||
import ghidra.app.plugin.core.format.ByteBlockSelection;
|
||||
import ghidra.app.plugin.core.format.DataFormatModel;
|
||||
import ghidra.app.util.AddressInput;
|
||||
import ghidra.app.util.bean.FixedBitSizeValueField;
|
||||
@@ -78,17 +79,7 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
panel.add(new GLabel("Alignment Address:"));
|
||||
|
||||
if (provider instanceof ProgramByteViewerComponentProvider) {
|
||||
Program program = ((ProgramByteViewerComponentProvider) provider).getProgram();
|
||||
if (program != null) {
|
||||
Address alignment = getAlignmentAddress();
|
||||
addressInputField = new AddressInput(program, a -> update());
|
||||
addressInputField.setAddressSpaceFilter(s -> s == alignment.getAddressSpace());
|
||||
addressInputField.setAddress(alignment);
|
||||
panel.add(addressInputField);
|
||||
addressInputField.setAccessibleName("Alignment Address");
|
||||
}
|
||||
}
|
||||
buildAddressField(panel);
|
||||
|
||||
panel.add(new GLabel("Bytes Per Line:"));
|
||||
bytesPerLineField = new FixedBitSizeValueField(8, false, true);
|
||||
@@ -111,6 +102,38 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void buildAddressField(JPanel parentPanel) {
|
||||
if (!(provider instanceof ProgramByteViewerComponentProvider programProvider)) {
|
||||
buildSimpleAddressInput(parentPanel);
|
||||
return;
|
||||
}
|
||||
|
||||
Program program = programProvider.getProgram();
|
||||
if (program == null) {
|
||||
buildSimpleAddressInput(parentPanel);
|
||||
return;
|
||||
}
|
||||
|
||||
Address alignment = getAlignmentAddress();
|
||||
if (alignment == null) {
|
||||
buildSimpleAddressInput(parentPanel);
|
||||
return;
|
||||
}
|
||||
|
||||
addressInputField = new AddressInput(program, a -> update());
|
||||
addressInputField.setAccessibleName("Alignment Address");
|
||||
addressInputField.setAddressSpaceFilter(s -> s == alignment.getAddressSpace());
|
||||
addressInputField.setAddress(alignment);
|
||||
parentPanel.add(addressInputField);
|
||||
}
|
||||
|
||||
private void buildSimpleAddressInput(JPanel parentPanel) {
|
||||
addressInputField = new AddressInput();
|
||||
addressInputField.setAccessibleName("Alignment Address");
|
||||
addressInputField.setEnabled(false);
|
||||
parentPanel.add(addressInputField);
|
||||
}
|
||||
|
||||
private Component buildViewOptionsPanel() {
|
||||
JPanel panel = new JPanel(new GridLayout(0, 2, 40, 0));
|
||||
Border outer = BorderFactory.createTitledBorder("Views");
|
||||
@@ -136,39 +159,42 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
||||
int bytesPerLine = provider.getBytesPerLine();
|
||||
int offset = provider.getOffset();
|
||||
|
||||
Address minAddr =
|
||||
((ProgramByteViewerComponentProvider) provider).getProgram().getMinAddress();
|
||||
Program program = ((ProgramByteViewerComponentProvider) provider).getProgram();
|
||||
Address minAddr = program.getMinAddress();
|
||||
if (minAddr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long addressOffset = minAddr.getOffset() + offset;
|
||||
|
||||
int alignment = (int) (addressOffset % bytesPerLine);
|
||||
|
||||
return (alignment == 0) ? minAddr : minAddr.add(bytesPerLine - alignment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void okCallback() {
|
||||
Address alignmentAddress = addressInputField.getAddress();
|
||||
int bytesPerLine = bytesPerLineField.getValue().intValue();
|
||||
int groupSize = groupSizeField.getValue().intValue();
|
||||
int addrOffset = (int) (alignmentAddress.getOffset() % bytesPerLine);
|
||||
// since we want the alignment address to begin a column, need to subtract addrOffset from bytesPerLine
|
||||
int addrOffset = 0;
|
||||
Address alignmentAddress = addressInputField.getAddress();
|
||||
if (alignmentAddress != null) {
|
||||
addrOffset = (int) (alignmentAddress.getOffset() % bytesPerLine);
|
||||
}
|
||||
|
||||
// We want the alignment address to begin a column, so subtract addrOffset from bytesPerLine
|
||||
int offset = addrOffset == 0 ? 0 : bytesPerLine - addrOffset;
|
||||
int groupSize = groupSizeField.getValue().intValue();
|
||||
|
||||
ByteBlockSelection blockSelection = provider.getBlockSelection();
|
||||
|
||||
// Setting these properties individually is problematic since it can temporarily put
|
||||
// the system into a bad state. As a hack, set the bytes per line to 256 since that
|
||||
// can support all allowed group sizes. Then set the group first since there
|
||||
// will be a divide by zero exception if the group size is ever bigger than the bytes
|
||||
// per line. Also, remove any deleted views before changing settings because the new settings
|
||||
// may not be compatible with a deleted view. Finally, after all setting have been updated,
|
||||
// add in the newly added views. This has to happen last because the new views may not be
|
||||
// compatible with the old settings.
|
||||
removeDeletedViews();
|
||||
|
||||
// Setting these properties individually is problematic since it can temporarily put the
|
||||
// system into a bad state. As a hack, set the bytes per line to 256 since that can support
|
||||
// all allowed group sizes. Then set the group first since there will be a divide by zero
|
||||
// exception if the group size is ever bigger than the bytes per line. Finally, after all
|
||||
// setting have been updated, add in the newly added views.
|
||||
provider.setBytesPerLine(256);
|
||||
provider.setGroupSize(groupSize);
|
||||
provider.setBytesPerLine(bytesPerLine);
|
||||
provider.setBlockOffset(offset);
|
||||
|
||||
addNewViews();
|
||||
|
||||
close();
|
||||
@@ -213,15 +239,10 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
||||
}
|
||||
|
||||
private boolean hasValidFieldValues() {
|
||||
if (addressInputField.getText().length() == 0) {
|
||||
setStatusText("Enter an alignment address");
|
||||
return false;
|
||||
}
|
||||
Address alignmentAddress = addressInputField.getAddress();
|
||||
if (alignmentAddress == null) {
|
||||
setStatusText("Invalid alignment address:" + addressInputField.getText());
|
||||
if (!validateAddress()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BigInteger bytesPerLine = bytesPerLineField.getValue();
|
||||
if (bytesPerLine == null) {
|
||||
setStatusText("Enter a value for Bytes Per Line");
|
||||
@@ -252,6 +273,25 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean validateAddress() {
|
||||
if (!addressInputField.isEnabled()) {
|
||||
return true; // nothing to validate
|
||||
}
|
||||
|
||||
String addrText = addressInputField.getText();
|
||||
if (StringUtils.isBlank(addrText)) {
|
||||
setStatusText("Enter an alignment address");
|
||||
return false;
|
||||
}
|
||||
|
||||
Address alignmentAddress = addressInputField.getAddress();
|
||||
if (alignmentAddress == null) {
|
||||
setStatusText("Invalid alignment address:" + addrText);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean atLeastOneViewOn() {
|
||||
Set<Entry<String, JCheckBox>> entrySet = checkboxMap.entrySet();
|
||||
for (Entry<String, JCheckBox> entry : entrySet) {
|
||||
|
||||
Reference in New Issue
Block a user