diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java index 9d29e56038..23f55a735e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java @@ -4,9 +4,9 @@ * 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. @@ -46,6 +46,7 @@ public class AddressFieldFactory extends FieldFactory { private boolean padZeros; private int minHexDigits; private boolean rightJustify; + private boolean displayUpperCase; /** * Default Constructor @@ -87,6 +88,7 @@ public class AddressFieldFactory extends FieldFactory { minHexDigits = afowo.getMinimumHexDigits(); displayBlockName = afowo.showBlockName(); rightJustify = afowo.rightJustify(); + displayUpperCase = afowo.displayUpperCase(); fieldOptions.getOptions(GROUP_TITLE).setOptionsHelpLocation(helpLoc); } @@ -100,6 +102,7 @@ public class AddressFieldFactory extends FieldFactory { minHexDigits = afowo.getMinimumHexDigits(); displayBlockName = afowo.showBlockName(); rightJustify = afowo.rightJustify(); + displayUpperCase = afowo.displayUpperCase(); model.update(); } } @@ -132,14 +135,26 @@ public class AddressFieldFactory extends FieldFactory { private String getAddressString(CodeUnit cu) { Address addr = cu.getMinAddress(); AddressSpace space = addr.getAddressSpace(); + int minDigits = padZeros ? 16 : minHexDigits; + String addrText = addr.toString(false, minDigits); + if (displayUpperCase) { + addrText = addrText.toUpperCase(); + } + if (displayBlockName) { - String text = addr.toString(false, padZeros ? 16 : minHexDigits); MemoryBlock block = cu.getProgram().getMemory().getBlock(addr); if (block != null) { - return block.getName() + ":" + text; + return block.getName() + ":" + addrText; } } - return addr.toString(space.showSpaceName(), padZeros ? 16 : minHexDigits); + + String spaceText = ""; + if (space.showSpaceName()) { + // this will be the space name followed by one or two colons + spaceText = space.toString(); + } + + return spaceText + addrText; } @Override @@ -178,8 +193,7 @@ public class AddressFieldFactory extends FieldFactory { } else if (loc instanceof AddressFieldLocation) { if (hasSamePath(lf, loc)) { - return new FieldLocation(index, fieldNum, 0, - ((AddressFieldLocation) loc).getCharOffset()); + return new FieldLocation(index, fieldNum, 0, loc.getCharOffset()); } } return null; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsPropertyEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsPropertyEditor.java index ba597aaad8..86858db870 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsPropertyEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsPropertyEditor.java @@ -4,9 +4,9 @@ * 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. @@ -38,9 +38,11 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport private static final String ADDRESS_DIGITS_LABEL = "Minimum Number of Address digits"; private static final String PADDING_LABEL = "Fully Pad With Leading Zeros"; private static final String JUSTIFICATION_LABEL = "Justification"; + private static final String UPPER_CASE_LABEL = "Display in Upper Case"; private static final String[] NAMES = - { SHOW_BLOCK_NAME_LABEL, ADDRESS_DIGITS_LABEL, PADDING_LABEL, JUSTIFICATION_LABEL }; + { SHOW_BLOCK_NAME_LABEL, ADDRESS_DIGITS_LABEL, PADDING_LABEL, JUSTIFICATION_LABEL, + UPPER_CASE_LABEL }; // help tooltips private static final String ADDRESS_PADDING_TOOLTIP = HTMLUtilities.toWrappedHTML( @@ -56,9 +58,11 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport "Specifies the justification for address text in the address field. The address " + "text will clip on the opposite side of the justification.", 75); + private static final String UPPER_CASE_TOOLTIP = HTMLUtilities.toWrappedHTML( + "Displays the hex digits of addresses in upper case in the address field.", 75); private static final String[] DESCRIPTIONS = { ADDRESS_PADDING_TOOLTIP, MIN_HEX_DIGITS_TOOLTIP, - SHOW_BLOCKNAME_TOOLTIP, RIGHT_JUSTIFY_TOOLTIP }; + SHOW_BLOCKNAME_TOOLTIP, RIGHT_JUSTIFY_TOOLTIP, UPPER_CASE_TOOLTIP }; private AddressFieldOptionsWrappedOption addressFieldOptionsWrappedOption; @@ -67,6 +71,7 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport private IntegerTextField minDigitsField; private GCheckBox showBlocknameCheckbox; private GhidraComboBox justificationCombobox; + private GCheckBox upperCaseCheckbox; public AddressFieldOptionsPropertyEditor() { editorComponent = buildEditor(); @@ -110,8 +115,16 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport justificationCombobox.setToolTipText(RIGHT_JUSTIFY_TOOLTIP); panel.add(justificationCombobox); + label = new GDLabel(UPPER_CASE_LABEL, SwingConstants.RIGHT); + label.setToolTipText(UPPER_CASE_TOOLTIP); + panel.add(label); + upperCaseCheckbox = new GCheckBox(); + upperCaseCheckbox.setToolTipText(UPPER_CASE_TOOLTIP); + panel.add(upperCaseCheckbox); + showBlocknameCheckbox.addItemListener(evt -> firePropertyChange()); justificationCombobox.addItemListener(evt -> firePropertyChange()); + upperCaseCheckbox.addItemListener(evt -> firePropertyChange()); padCheckBox.addItemListener(evt -> { boolean enabled = !padCheckBox.isSelected(); @@ -129,7 +142,7 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport } addressFieldOptionsWrappedOption = (AddressFieldOptionsWrappedOption) value; - setLocalValues(addressFieldOptionsWrappedOption); + setValuesFromOption(addressFieldOptionsWrappedOption); firePropertyChange(); } @@ -137,31 +150,36 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport return minDigitsField.getIntValue(); } - private void setLocalValues(AddressFieldOptionsWrappedOption addressPaddingOption) { - if (addressPaddingOption.showBlockName() != showBlocknameCheckbox.isSelected()) { - showBlocknameCheckbox.setSelected(addressPaddingOption.showBlockName()); + private void setValuesFromOption(AddressFieldOptionsWrappedOption option) { + if (option.showBlockName() != showBlocknameCheckbox.isSelected()) { + showBlocknameCheckbox.setSelected(option.showBlockName()); } boolean rightJust = justificationCombobox.getSelectedItem().equals("Right"); - if (addressPaddingOption.rightJustify() != rightJust) { - justificationCombobox.setSelectedIndex(addressPaddingOption.rightJustify() ? 1 : 0); + if (option.rightJustify() != rightJust) { + justificationCombobox.setSelectedIndex(option.rightJustify() ? 1 : 0); } - if (addressPaddingOption.padWithZeros() != padCheckBox.isSelected()) { - padCheckBox.setSelected(addressPaddingOption.padWithZeros()); + if (option.padWithZeros() != padCheckBox.isSelected()) { + padCheckBox.setSelected(option.padWithZeros()); } - if (!Integer.toString(addressPaddingOption.getMinimumHexDigits()).equals( - minDigitsField.getText())) { - minDigitsField.setValue(addressPaddingOption.getMinimumHexDigits()); + if (!Integer.toString(option.getMinimumHexDigits()) + .equals( + minDigitsField.getText())) { + minDigitsField.setValue(option.getMinimumHexDigits()); } boolean enabled = !padCheckBox.isSelected(); minDigitsField.setEnabled(enabled); + if (option.displayUpperCase() != upperCaseCheckbox.isSelected()) { + upperCaseCheckbox.setSelected(option.displayUpperCase()); + } } - private AddressFieldOptionsWrappedOption cloneAddressPadValues() { + private AddressFieldOptionsWrappedOption createOptionFromValues() { AddressFieldOptionsWrappedOption newOption = new AddressFieldOptionsWrappedOption(); newOption.setPadWithZeros(padCheckBox.isSelected()); newOption.setMinimumHexDigits(getMinNumberOfDigits()); newOption.setShowBlockName(showBlocknameCheckbox.isSelected()); newOption.setRightJustify(justificationCombobox.getSelectedItem().equals("Right")); + newOption.setDisplayUpperCase(upperCaseCheckbox.isSelected()); return newOption; } @@ -177,7 +195,7 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport @Override public Object getValue() { - return cloneAddressPadValues(); + return createOptionFromValues(); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsWrappedOption.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsWrappedOption.java index bfcc047f8b..478cedbd6f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsWrappedOption.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldOptionsWrappedOption.java @@ -4,9 +4,9 @@ * 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. @@ -27,17 +27,20 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { private static final String MIN_HEXL_DIGITS = "MinHexDigits"; private static final String RIGHT_JUSTIFY = "RightJustify"; private static final String SHOW_BLOCK_NAME = "ShowBlockName"; + private static final String DISPLAY_UPPER_CASE = "DisplayUpperCase"; private static final boolean DEFAULT_PAD_WITH_ZEROS = false; private static final boolean DEFAULT_SHOW_BLOCK_NAME = false; private static final boolean DEFAULT_RIGHT_JUSTIFY = true; private static final int DEFAULT_MIN_HEX_DIGITS = 8; + private static final boolean DEFAULT_DISPLAY_UPPER_CASE = false; // init with default values private boolean padWithZeros = DEFAULT_PAD_WITH_ZEROS; private boolean showBlockName = DEFAULT_SHOW_BLOCK_NAME; private boolean rightJustify = DEFAULT_RIGHT_JUSTIFY; private int minHexDigits = DEFAULT_MIN_HEX_DIGITS; + private boolean displayUpperCase = DEFAULT_DISPLAY_UPPER_CASE; public AddressFieldOptionsWrappedOption() { // required for persistence @@ -75,6 +78,14 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { rightJustify = b; } + public boolean displayUpperCase() { + return displayUpperCase; + } + + public void setDisplayUpperCase(boolean b) { + displayUpperCase = b; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof AddressFieldOptionsWrappedOption)) { @@ -89,7 +100,8 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { return (padWithZeros == otherOption.padWithZeros) && (minHexDigits == otherOption.minHexDigits) && (rightJustify == otherOption.rightJustify) && - (showBlockName == otherOption.showBlockName); + (showBlockName == otherOption.showBlockName) && + (displayUpperCase == otherOption.displayUpperCase); } @Override @@ -99,6 +111,7 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { result = prime * result + (padWithZeros ? 1 : 0); result = prime * result + (rightJustify ? 1 : 0); result = prime * result + (showBlockName ? 1 : 0); + result = prime * result + (displayUpperCase ? 1 : 0); result = prime * result + minHexDigits; return result; } @@ -112,6 +125,7 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { minHexDigits = properties.getInt(MIN_HEXL_DIGITS, minHexDigits); rightJustify = properties.getBoolean(RIGHT_JUSTIFY, rightJustify); showBlockName = properties.getBoolean(SHOW_BLOCK_NAME, showBlockName); + displayUpperCase = properties.getBoolean(DISPLAY_UPPER_CASE, displayUpperCase); } @Override @@ -120,5 +134,6 @@ public class AddressFieldOptionsWrappedOption implements CustomOption { properties.putInt(MIN_HEXL_DIGITS, minHexDigits); properties.putBoolean(RIGHT_JUSTIFY, rightJustify); properties.putBoolean(SHOW_BLOCK_NAME, showBlockName); + properties.putBoolean(DISPLAY_UPPER_CASE, displayUpperCase); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java index 35a0ff822c..97bbbc5c6c 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java @@ -256,6 +256,23 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest s = btf.getText(); assertEquals("01001000", s); + // Test displayUpperCase - navigate to an address whose hex offset contains A-F + cb.goToField(addr("0x100100a"), "Address", 0, 0); + btf = (ListingTextField) cb.getCurrentField(); + assertEquals("0100100a", btf.getText()); + + afowo.setDisplayUpperCase(true); + options.setCustomOption(names.get(0), afowo); + cb.updateNow(); + btf = (ListingTextField) cb.getCurrentField(); + assertEquals("0100100A", btf.getText()); + + afowo.setDisplayUpperCase(false); + options.setCustomOption(names.get(0), afowo); + cb.updateNow(); + btf = (ListingTextField) cb.getCurrentField(); + assertEquals("0100100a", btf.getText()); + } @Test diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/OverlayAddressSpace.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/OverlayAddressSpace.java index b75ec0721d..c631054478 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/OverlayAddressSpace.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/OverlayAddressSpace.java @@ -148,7 +148,7 @@ public abstract class OverlayAddressSpace extends AbstractAddressSpace { } /** - * If the given address is outside the overlay block, then the address is tranlated to an + * If the given address is outside the overlay block, then the address is translated to an * address in the base space with the same offset, otherwise (if the address exists in the * overlay block), it is returned * @@ -161,7 +161,7 @@ public abstract class OverlayAddressSpace extends AbstractAddressSpace { } /** - * Tranlated an overlay-space address (addr, which may exceed the bounds of the overlay space) + * Translated an overlay-space address (addr, which may exceed the bounds of the overlay space) * to an address in the base space with the same offset. If forceTranslation is false and addr * is contained within the overlay-space the original addr is returned. * @@ -221,8 +221,8 @@ public abstract class OverlayAddressSpace extends AbstractAddressSpace { } /** - * Compare this overlay to the spacified overlay. - * @param overlay other overlay to be checked for eqauality + * Compare this overlay to the specified overlay. + * @param overlay other overlay to be checked for equality * @return see {@link Comparable#compareTo(Object)} */ int compareOverlay(OverlayAddressSpace overlay) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java index 4b939baa17..40b6482f98 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java @@ -4,9 +4,9 @@ * 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. @@ -15,7 +15,6 @@ */ package ghidra.program.model.address; - /** * Address class for dealing with (intel) segmented addresses. The class itself is agnostic * about the mapping from segmented encoding to flat address offset, it uses the @@ -88,7 +87,7 @@ public class SegmentedAddress extends GenericAddress { /** * Returns a new address that is equivalent to this address using * the given segment number. - * @param seg the seqment value to normalize to. + * @param seg the segment value to normalize to. * @return the new address */ public SegmentedAddress normalize(int seg) { @@ -135,17 +134,11 @@ public class SegmentedAddress extends GenericAddress { return zeros.substring(0, 4 - str.length()) + str; } - /** - * @see ghidra.program.model.address.Address#toString(String) - */ @Override public String toString(String prefix) { return prefix + getString(segment) + SEPARATOR_CHAR + getString(getSegmentOffset()); } - /** - * @see ghidra.program.model.address.Address#getPhysicalAddress() - */ @Override public Address getPhysicalAddress() { return this; // A segmented address is already a physical address. @@ -155,7 +148,7 @@ public class SegmentedAddress extends GenericAddress { public String toString(boolean showAddressSpace, int minNumDigits) { String addr = getString(segment) + SEPARATOR_CHAR + getString(getSegmentOffset()); if (showAddressSpace) { - addr = addrSpace.getName() + SEPARATOR_CHAR + addr; + addr = addrSpace + addr; } return addr; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java index fe898e6feb..3c100acd63 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java @@ -33,7 +33,7 @@ public interface MemoryBlock extends Serializable, Comparable { * A special purpose EXTERNAL block may be created by certain program loaders * (e.g., Elf) to act as a stand-in for unknown external symbol locations when * relocation support is required using a valid memory address. While the - * EXTERNAL block is created out of neccessity for relocation processing it + * EXTERNAL block is created out of necessity for relocation processing it * introduces a number of limitations when used to carry data symbols * where pointer math and offset-references may occur. *

@@ -65,6 +65,7 @@ public interface MemoryBlock extends Serializable, Comparable { /** * Get memory data in the form of an InputStream. Null is returned for thos memory blocks which * have no data. + * @return the input stream */ public InputStream getData(); @@ -72,6 +73,7 @@ public interface MemoryBlock extends Serializable, Comparable { * Return whether addr is contained in this block. * * @param addr address + * @return true if contained */ public boolean contains(Address addr); @@ -303,8 +305,8 @@ public interface MemoryBlock extends Serializable, Comparable { public int putBytes(Address addr, byte[] b) throws MemoryAccessException; /** - * Tries to put len bytes from the specified byte array to this block. All the bytes may not be - * written if the requested length is beyond the end of the block. + * Tries to put {@code len} bytes from the specified byte array to this block. All the bytes may + * not be written if the requested length is beyond the end of the block. * * @param addr the address of where to put the bytes. * @param b the byte array containing the bytes to write. @@ -328,7 +330,7 @@ public interface MemoryBlock extends Serializable, Comparable { /** * Return whether this block has been initialized. *

- * WARNING: A mapped memory block may have a mix of intialized, uninitialized, and undefined + * WARNING: A mapped memory block may have a mix of initialized, uninitialized, and undefined * regions. The value returned by this method for a mapped memory block is always false * even if some regions are initialized. * @return true if block is fully initialized and not a memory-mapped-block, else false @@ -347,10 +349,10 @@ public interface MemoryBlock extends Serializable, Comparable { * (see {@link MemoryBlock#EXTERNAL_BLOCK_NAME}). Checks for individual addresses may be done * using {@link Memory#isExternalBlockAddress(Address)}. *

- * Note that EXTERNAL blocks always resides within a memory space and never within the artifial - * {@link AddressSpace#EXTERNAL_SPACE} which is not a memory space. This can be a source of confusion. - * An EXTERNAL memory block exists to facilitate relocation processing for some external - * symbols which require a real memory address. + * Note that EXTERNAL blocks always resides within a memory space and never within the + * artificial {@link AddressSpace#EXTERNAL_SPACE} which is not a memory space. This can be a + * source of confusion. An EXTERNAL memory block exists to facilitate relocation processing for + * some external symbols which require a real memory address. * * @return true if this is a reserved EXTERNAL memory block */