Merge remote-tracking branch 'origin/GP-4310_ghida1_RGB_DataTypes'

(Closes #6191)
This commit is contained in:
Ryan Kurtz 2025-07-09 12:32:41 -04:00
commit 794cb1c07c
18 changed files with 1073 additions and 62 deletions

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -23,6 +23,7 @@ import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.plugin.core.hover.AbstractConfigurableHover; import ghidra.app.plugin.core.hover.AbstractConfigurableHover;
import ghidra.app.util.ToolTipUtils; import ghidra.app.util.ToolTipUtils;
import ghidra.app.util.viewer.field.ResourceFieldLocation;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
@ -126,6 +127,11 @@ public class DataTypeListingHover extends AbstractConfigurableHover implements L
(EquateOperandFieldLocation) programLocation; (EquateOperandFieldLocation) programLocation;
return createEquateToolTipComponent(program, equateLocation.getEquate()); return createEquateToolTipComponent(program, equateLocation.getEquate());
} }
if (programLocation instanceof ResourceFieldLocation resourceLoc) {
Data data = resourceLoc.getResourceData();
dt = data.getDataType();
return createTooltipComponent(dt.getRepresentation(data, data, data.getLength()));
}
return null; return null;
} }

View file

@ -20,12 +20,20 @@ import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.Icon;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import docking.widgets.fieldpanel.field.*; import docking.widgets.fieldpanel.field.AbstractTextFieldElement;
import docking.widgets.fieldpanel.support.*; import docking.widgets.fieldpanel.field.AttributedString;
import docking.widgets.fieldpanel.field.CompositeFieldElement;
import docking.widgets.fieldpanel.field.FieldElement;
import docking.widgets.fieldpanel.support.FieldLocation;
import docking.widgets.fieldpanel.support.FieldUtils;
import docking.widgets.fieldpanel.support.RowColLocation;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.util.*; import ghidra.app.util.ColorAndStyle;
import ghidra.app.util.ListingHighlightProvider;
import ghidra.app.util.SymbolInspector;
import ghidra.app.util.viewer.field.ListingColors.FunctionColors; import ghidra.app.util.viewer.field.ListingColors.FunctionColors;
import ghidra.app.util.viewer.format.FieldFormatModel; import ghidra.app.util.viewer.format.FieldFormatModel;
import ghidra.app.util.viewer.options.OptionsGui; import ghidra.app.util.viewer.options.OptionsGui;
@ -33,13 +41,30 @@ import ghidra.app.util.viewer.proxy.ProxyObj;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.DataImage;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.Enum; import ghidra.program.model.data.Enum;
import ghidra.program.model.data.Playable;
import ghidra.program.model.data.Union;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.LabelString;
import ghidra.program.model.listing.OperandRepresentationList;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.Variable;
import ghidra.program.model.listing.VariableOffset;
import ghidra.program.model.scalar.Scalar; import ghidra.program.model.scalar.Scalar;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.Equate;
import ghidra.program.util.*; import ghidra.program.model.symbol.EquateTable;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.util.EquateOperandFieldLocation;
import ghidra.program.util.OperandFieldLocation;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
/** /**
@ -180,8 +205,8 @@ abstract class OperandFieldHelper extends FieldFactory {
this.maxDisplayLines = maxLines; this.maxDisplayLines = maxLines;
} }
FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField field, FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField field, int opIndex,
int opIndex, int column) { int column) {
if (field instanceof ListingTextField listingField) { if (field instanceof ListingTextField listingField) {
RowColLocation rcl = listingField.dataToScreenLocation(opIndex, column); RowColLocation rcl = listingField.dataToScreenLocation(opIndex, column);
return new FieldLocation(index, fieldNum, rcl.row(), rcl.col()); return new FieldLocation(index, fieldNum, rcl.row(), rcl.col());
@ -211,7 +236,8 @@ abstract class OperandFieldHelper extends FieldFactory {
if (lf instanceof ImageFactoryField) { if (lf instanceof ImageFactoryField) {
Data data = (Data) obj; Data data = (Data) obj;
if (data.getValue() instanceof DataImage) { Object value = data.getValue();
if (value instanceof DataImage || value instanceof Icon) {
return new ResourceFieldLocation(data.getProgram(), data.getMinAddress(), return new ResourceFieldLocation(data.getProgram(), data.getMinAddress(),
data.getComponentPath(), codeUnitFormat.getDataValueRepresentationString(data), data.getComponentPath(), codeUnitFormat.getDataValueRepresentationString(data),
0, col, data); 0, col, data);
@ -362,6 +388,10 @@ abstract class OperandFieldHelper extends FieldFactory {
return new ImageFactoryField(this, ((DataImage) value).getImageIcon(), proxy, return new ImageFactoryField(this, ((DataImage) value).getImageIcon(), proxy,
getMetrics(), startX + varWidth, width); getMetrics(), startX + varWidth, width);
} }
if (value instanceof Icon) {
return new ImageFactoryField(this, (Icon) value, proxy, getMetrics(), startX + varWidth,
width);
}
else if (value instanceof Playable) { else if (value instanceof Playable) {
return new ImageFactoryField(this, ((Playable) value).getImageIcon(), proxy, return new ImageFactoryField(this, ((Playable) value).getImageIcon(), proxy,
getMetrics(), startX + varWidth, width); getMetrics(), startX + varWidth, width);
@ -452,8 +482,8 @@ abstract class OperandFieldHelper extends FieldFactory {
if (wrapOnSemicolon) { if (wrapOnSemicolon) {
List<FieldElement> lines = breakIntoLines(elements); List<FieldElement> lines = breakIntoLines(elements);
if (lines.size() == 1) { if (lines.size() == 1) {
return ListingTextField.createSingleLineTextField(this, proxy, return ListingTextField.createSingleLineTextField(this, proxy, lines.get(0),
lines.get(0), startX + varWidth, width, hlProvider); startX + varWidth, width, hlProvider);
} }
return ListingTextField.createMultilineTextField(this, proxy, lines, startX, width, return ListingTextField.createMultilineTextField(this, proxy, lines, startX, width,
hlProvider); hlProvider);

View file

@ -28,8 +28,10 @@ import ghidra.app.util.viewer.field.*;
import ghidra.framework.options.*; import ghidra.framework.options.*;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.Array;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.scalar.Scalar;
import ghidra.util.classfinder.*; import ghidra.util.classfinder.*;
import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet; import ghidra.util.datastruct.WeakSet;
@ -259,8 +261,7 @@ public class FormatManager implements OptionsChangeListener {
return false; return false;
} }
DataType type = data.getBaseDataType(); DataType type = data.getBaseDataType();
return type.getLength() > 0 && type instanceof AbstractIntegerDataType || return type.getLength() > 0 && type.getValueClass(null) == Scalar.class;
type instanceof DefaultDataType;
} }
/** /**
@ -944,8 +945,7 @@ public class FormatManager implements OptionsChangeListener {
private class MultipleHighlighterProvider implements ListingHighlightProvider { private class MultipleHighlighterProvider implements ListingHighlightProvider {
private List<ListingHighlightProvider> highlightProviders = private List<ListingHighlightProvider> highlightProviders = new CopyOnWriteArrayList<>();
new CopyOnWriteArrayList<>();
@Override @Override
public Highlight[] createHighlights(String text, ListingField field, int cursorTextOffset) { public Highlight[] createHighlights(String text, ListingField field, int cursorTextOffset) {
@ -961,8 +961,7 @@ public class FormatManager implements OptionsChangeListener {
int size = highlightProviders.size(); int size = highlightProviders.size();
for (int i = size - 1; i >= 0; i--) { for (int i = size - 1; i >= 0; i--) {
ListingHighlightProvider provider = highlightProviders.get(i); ListingHighlightProvider provider = highlightProviders.get(i);
Highlight[] highlights = Highlight[] highlights = provider.createHighlights(text, field, cursorTextOffset);
provider.createHighlights(text, field, cursorTextOffset);
for (Highlight highlight : highlights) { for (Highlight highlight : highlights) {
list.add(highlight); list.add(highlight);
} }

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -16,7 +16,6 @@
package ghidra.docking.settings; package ghidra.docking.settings;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
@ -40,14 +39,10 @@ public interface SettingsDefinition {
if (settings == null) { if (settings == null) {
return additional; return additional;
} }
ArrayList<SettingsDefinition> list = new ArrayList<>(); SettingsDefinition[] newArray = new SettingsDefinition[settings.length + additional.length];
list.addAll(Arrays.asList(settings)); System.arraycopy(settings, 0, newArray, 0, settings.length);
for (SettingsDefinition def : additional) { System.arraycopy(additional, 0, newArray, settings.length, additional.length);
if (!list.contains(def)) { return newArray;
list.add(def);
}
}
return list.toArray(new SettingsDefinition[list.size()]);
} }
/** /**

View file

@ -0,0 +1,145 @@
/* ###
* 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.program.model.data;
import java.awt.Color;
import java.math.BigInteger;
import java.util.List;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsImpl;
import ghidra.program.model.listing.Data;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.scalar.Scalar;
import ghidra.util.DataConverter;
import ghidra.util.Msg;
/**
* {@link AbstractColorDataType} provides an abstract color datatype whose value corresponds to an
* approriate Color decode of the bytes at a memory location. This datatype is a fixed-length
* unsigned integer type which is rendered with a Color block when applied as {@link Data}.
* <P>
* The {@link #getValue(MemBuffer, Settings, int)} method returns {@link ColorIcon} instance.
* <P>
* A fixed-length RGB datatype will adopt a predefined default encoding, however a Typedef may
* be formed from the RGB datatype which will allow an alternative encoding to be specified
* via a default Setting (See {@link #getTypeDefSettingsDefinitions()}).
*/
public abstract class AbstractColorDataType extends AbstractUnsignedIntegerDataType {
private static Settings rgbValueSettings = new SettingsImpl();
static {
PADDING.setPadded(rgbValueSettings, true);
}
/**
* Abstract color datatype whose value corresponds to an approriate Color decode
* of the bytes at a memory location.
* @param name datatype name
* @param dtm datatype manager
*/
public AbstractColorDataType(String name, DataTypeManager dtm) {
super(name, dtm);
}
@Override
public AbstractIntegerDataType getOppositeSignednessDataType() {
Msg.error(this, "Unsupported method use for " + getClass().getName(),
new UnsupportedOperationException());
return this;
}
@Override
public final Class<?> getValueClass(Settings settings) {
return ColorIcon.class;
}
@Override
public final String getRepresentation(MemBuffer buf, Settings settings, int length) {
int size = getLength();
byte[] bytes = new byte[size];
if (buf.getBytes(bytes, 0) != size) {
return "??";
}
// Full RGB value always displayed as Padded Hex but must respect Endianess setting
BigInteger value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf))
.getBigInteger(bytes, size, true);
String valueRep = getRepresentation(value, rgbValueSettings, 8 * size, false);
// Representation: <encoding>: <valueRep> {<componentValueList>}
StringBuilder strbuf = new StringBuilder();
strbuf.append(getEncodingName(settings));
strbuf.append(" ");
strbuf.append(valueRep);
strbuf.append(" {");
int cnt = 0;
for (ComponentValue compValue : getComponentValues(buf, settings)) {
if (cnt++ != 0) {
strbuf.append(",");
}
strbuf.append(compValue.getRepresentation(settings));
}
strbuf.append("}");
return strbuf.toString();
}
protected abstract String getEncodingName(Settings settings);
protected abstract List<ComponentValue> getComponentValues(MemBuffer buf, Settings settings);
@Override
public ColorIcon getValue(MemBuffer buf, Settings settings, int length) {
int size = getLength();
if (size < 1 || size > 8) {
throw new AssertionError("Unsupported length: " + size);
}
byte[] bytes = new byte[size];
if (buf.getBytes(bytes, 0) != size) {
return null; // insufficient bytes available
}
return new ColorIcon(decodeColor(buf, settings));
}
/**
* Generate the {@link Color} which corresponds to the memory bytes.
* Implementation must factor Endianess setting into value used.
* @param buf memory bytes buffer
* @param settings datatype settings
* @return Color to be rendered
*/
protected abstract Color decodeColor(MemBuffer buf, Settings settings);
protected record ComponentValue(String name, int value, int bitLength) {
String getRepresentation(Settings settings) {
BigInteger bigValue = BigInteger.valueOf(Integer.toUnsignedLong(value));
// CHAR format will default to HEX format
return name + ":" +
AbstractIntegerDataType.getRepresentation(bigValue, settings, bitLength, false);
}
}
protected static int getFieldValue(long fullValue, int rightShift, int finalMask) {
return (int) (fullValue >>> rightShift) & finalMask;
}
protected static int scaleFieldValue(int value, int bitSize) {
return (value * 255) / ((1 << bitSize) - 1);
}
}

View file

@ -28,7 +28,7 @@ import ghidra.util.UniversalID;
*/ */
public abstract class AbstractDataType implements DataType { public abstract class AbstractDataType implements DataType {
private final static TypeDefSettingsDefinition[] EMPTY_TYPEDEF_DEFINITIONS = protected final static TypeDefSettingsDefinition[] EMPTY_TYPEDEF_DEFINITIONS =
new TypeDefSettingsDefinition[0]; new TypeDefSettingsDefinition[0];
protected String name; protected String name;

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -53,9 +53,12 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
protected static final DataTypeMnemonicSettingsDefinition MNEMONIC = protected static final DataTypeMnemonicSettingsDefinition MNEMONIC =
DataTypeMnemonicSettingsDefinition.DEF; DataTypeMnemonicSettingsDefinition.DEF;
private static SettingsDefinition[] SETTINGS_DEFS = protected static final SettingsDefinition[] SETTINGS_DEFS =
{ FormatSettingsDefinition.DEF_HEX, PADDING, ENDIAN, MNEMONIC }; { FormatSettingsDefinition.DEF_HEX, PADDING, ENDIAN, MNEMONIC };
protected static final TypeDefSettingsDefinition[] TYPEDEF_SETTINGS_DEFS =
EMPTY_TYPEDEF_DEFINITIONS;
/** /**
* Constructor * Constructor
* *
@ -81,6 +84,11 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
return SETTINGS_DEFS; return SETTINGS_DEFS;
} }
@Override
public TypeDefSettingsDefinition[] getTypeDefSettingsDefinitions() {
return TYPEDEF_SETTINGS_DEFS;
}
/** /**
* Determine if this type is signed. * Determine if this type is signed.
* @return true if this is a signed integer data-type * @return true if this is a signed integer data-type
@ -243,9 +251,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
this); this);
} }
BigInteger maxValueExclusive = BigInteger.ONE.shiftLeft(length * 8 - (isSigned() ? 1 : 0)); BigInteger maxValueExclusive = BigInteger.ONE.shiftLeft(length * 8 - (isSigned() ? 1 : 0));
BigInteger minValueInclusive = isSigned() BigInteger minValueInclusive =
? BigInteger.ONE.shiftLeft(length * 8 - 1).negate() isSigned() ? BigInteger.ONE.shiftLeft(length * 8 - 1).negate() : BigInteger.ZERO;
: BigInteger.ZERO;
if (bigValue.compareTo(maxValueExclusive) >= 0) { if (bigValue.compareTo(maxValueExclusive) >= 0) {
throw new DataTypeEncodeException("Value is too large", bigValue, this); throw new DataTypeEncodeException("Value is too large", bigValue, this);
} }
@ -282,11 +289,12 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
BigInteger value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf)) BigInteger value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf))
.getBigInteger(bytes, size, true); .getBigInteger(bytes, size, true);
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) { int format = getFormatSettingsDefinition().getFormat(settings);
if (format == FormatSettingsDefinition.CHAR) {
return StringDataInstance.getCharRepresentation(this, bytes, settings); return StringDataInstance.getCharRepresentation(this, bytes, settings);
} }
return getRepresentation(value, settings, 8 * length); return getRepresentation(value, settings, 8 * length, isSigned());
} }
/** /**
@ -298,16 +306,18 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
* @param bigInt BigInteger value with the appropriate sign * @param bigInt BigInteger value with the appropriate sign
* @param settings integer format settings (PADDING, FORMAT, etc.) * @param settings integer format settings (PADDING, FORMAT, etc.)
* @param bitLength number of value bits to be used from bigInt * @param bitLength number of value bits to be used from bigInt
* @param isSigned true if type is signed, else false
* @return formatted integer string * @return formatted integer string
*/ */
/*package*/ String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) { /*package*/ static String getRepresentation(BigInteger bigInt, Settings settings, int bitLength,
boolean isSigned) {
int format = getFormatSettingsDefinition().getFormat(settings);
boolean padded = PADDING.isPadded(settings); boolean padded = PADDING.isPadded(settings);
boolean negative = bigInt.signum() < 0; boolean negative = bigInt.signum() < 0;
if (negative && (!isSigned() || (format != FormatSettingsDefinition.DECIMAL))) { int format = FormatSettingsDefinition.DEF_HEX.getChoice(settings);
if (negative && (!isSigned || (format != FormatSettingsDefinition.DECIMAL))) {
// force use of unsigned value // force use of unsigned value
bigInt = bigInt.add(BigInteger.valueOf(2).pow(bitLength)); bigInt = bigInt.add(BigInteger.valueOf(2).pow(bitLength));
} }

View file

@ -102,8 +102,8 @@ public class BitFieldDataType extends AbstractDataType {
/** /**
* Get the effective bit-size based upon the specified base type size. A bit size * Get the effective bit-size based upon the specified base type size. A bit size
* larger than the base type size will truncated to the base type size. * larger than the base type size will truncated to the base type size.
* @param declaredBitSize * @param declaredBitSize declare bitfield size
* @param baseTypeByteSize * @param baseTypeByteSize base datatype size in bytes
* @return effective bit-size * @return effective bit-size
*/ */
public static int getEffectiveBitSize(int declaredBitSize, int baseTypeByteSize) { public static int getEffectiveBitSize(int declaredBitSize, int baseTypeByteSize) {
@ -417,9 +417,13 @@ public class BitFieldDataType extends AbstractDataType {
if (dt instanceof Enum) { if (dt instanceof Enum) {
return ((Enum) dt).getRepresentation(big, settings, effectiveBitSize); return ((Enum) dt).getRepresentation(big, settings, effectiveBitSize);
} }
if (dt instanceof BooleanDataType) {
// TRUE or FALSE representation
return ((BooleanDataType) dt).getRepresentation(big, settings, effectiveBitSize);
}
AbstractIntegerDataType intDT = (AbstractIntegerDataType) dt; AbstractIntegerDataType intDT = (AbstractIntegerDataType) dt;
if (intDT.getFormatSettingsDefinition() int format = intDT.getFormatSettingsDefinition().getFormat(settings);
.getFormat(settings) == FormatSettingsDefinition.CHAR) { if (format == FormatSettingsDefinition.CHAR) {
if (big.signum() < 0) { if (big.signum() < 0) {
big = big.add(BigInteger.valueOf(2).pow(effectiveBitSize)); big = big.add(BigInteger.valueOf(2).pow(effectiveBitSize));
} }
@ -429,7 +433,7 @@ public class BitFieldDataType extends AbstractDataType {
return StringDataInstance.getCharRepresentation(this, bytes, settings); return StringDataInstance.getCharRepresentation(this, bytes, settings);
} }
return intDT.getRepresentation(big, settings, effectiveBitSize); return AbstractIntegerDataType.getRepresentation(big, settings, effectiveBitSize, isSigned);
} }
@Override @Override

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -28,7 +28,7 @@ import ghidra.program.model.mem.MemoryAccessException;
*/ */
public class BooleanDataType extends AbstractUnsignedIntegerDataType { public class BooleanDataType extends AbstractUnsignedIntegerDataType {
private static SettingsDefinition[] SETTINGS_DEFS = {}; private static SettingsDefinition[] BOOLEAN_SETTINGS_DEFS = {};
public static final BooleanDataType dataType = new BooleanDataType(); public static final BooleanDataType dataType = new BooleanDataType();
@ -95,14 +95,13 @@ public class BooleanDataType extends AbstractUnsignedIntegerDataType {
return b.booleanValue() ? "TRUE" : "FALSE"; return b.booleanValue() ? "TRUE" : "FALSE";
} }
@Override
public String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) { public String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) {
return BigInteger.ZERO.equals(bigInt) ? "FALSE" : "TRUE"; return BigInteger.ZERO.equals(bigInt) ? "FALSE" : "TRUE";
} }
@Override @Override
protected SettingsDefinition[] getBuiltInSettingsDefinitions() { protected SettingsDefinition[] getBuiltInSettingsDefinitions() {
return SETTINGS_DEFS; return BOOLEAN_SETTINGS_DEFS;
} }
@Override @Override

View file

@ -0,0 +1,88 @@
/* ###
* 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.program.model.data;
import java.awt.*;
import javax.swing.Icon;
import generic.theme.GColor;
/**
* {@link ColorIcon} provides a color icon patch to convey a specified color with
* Alpha transparancy. This implementation was created in support of color
* data types (see {@link AbstractColorDataType}).
*/
public class ColorIcon implements Icon {
private static final int WIDTH = 16;
private static final int HEIGHT = 16;
private static Color BORDER_COLOR = new GColor("color.fg");
private final Color color;
/**
* Construct a 16x16 RGB color icon patch
* @param color icon color
*/
ColorIcon(Color color) {
this.color = color;
}
@Override
public int getIconHeight() {
return HEIGHT;
}
@Override
public int getIconWidth() {
return WIDTH;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2d = (Graphics2D) g;
// Enable anti-aliasing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Draw a white box with a diagonal black line under the colored-box to convey
// Alpha channel transparency while preserving color.
g.setColor(Color.WHITE);
g.fillRect(x + 1, y + 1, WIDTH - 2, HEIGHT - 2);
g.setColor(Color.BLACK);
g.drawLine(x + 1, y + 1, x + WIDTH - 2, y + HEIGHT - 2);
// Draw colored-box
g.setColor(color);
g.fillRect(x + 1, y + 1, WIDTH - 2, HEIGHT - 2);
g.setColor(BORDER_COLOR);
g.drawLine(x + 1, y, x + WIDTH - 2, y);
g.drawLine(x + WIDTH - 1, y + 1, x + WIDTH - 1, y + HEIGHT - 2);
g.drawLine(x + 1, y + HEIGHT - 1, x + WIDTH - 2, y + HEIGHT - 1);
g.drawLine(x, y + 1, x, y + HEIGHT - 2);
}
/**
* {@return standardized RGB value}
*/
public int getRGBValue() {
return color.getRGB();
}
}

View file

@ -84,6 +84,11 @@ public class DefaultDataType extends DataTypeImpl {
} }
} }
@Override
public Class<?> getValueClass(Settings settings) {
return Scalar.class;
}
@Override @Override
public DataType clone(DataTypeManager dtm) { public DataType clone(DataTypeManager dtm) {
return this; return this;

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -35,7 +35,7 @@ public class PointerTypeSettingsDefinition
private static final String[] choices = private static final String[] choices =
{ "default", "image-base-relative", "relative", "file-offset" }; { "default", "image-base-relative", "relative", "file-offset" };
public static final PointerTypeSettingsDefinition DEF = new PointerTypeSettingsDefinition(); // Format with HEX default public static final PointerTypeSettingsDefinition DEF = new PointerTypeSettingsDefinition();
private PointerTypeSettingsDefinition() { private PointerTypeSettingsDefinition() {
} }

View file

@ -0,0 +1,167 @@
/* ###
* 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.program.model.data;
import java.awt.Color;
import java.util.*;
import ghidra.docking.settings.Settings;
import ghidra.program.model.data.RGB16EncodingSettingsDefinition.RGB16Encoding;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.DataConverter;
/**
* {@link RGB16ColorDataType} provides a base implementation for 16-bit RGB Color values.
* While this base implementation defaults to RGB_565 encoding a {@link TypeDef}
* may be established with a different 16-bit encoding specified via a default setting of
* {@link RGB16EncodingSettingsDefinition}.
*/
public class RGB16ColorDataType extends AbstractColorDataType {
public static RGB16ColorDataType datatype = new RGB16ColorDataType();
private static int LENGTH = 2;
private static TypeDefSettingsDefinition[] RGB16_TYPEDEF_SETTINGS = TypeDefSettingsDefinition
.concat(UnsignedIntegerDataType.dataType.getTypeDefSettingsDefinitions(),
RGB16EncodingSettingsDefinition.DEF);
/**
* Generate a 16-bit RGB typedef with a specific encoding
* @param rgb16Encoding 16-bit RGB encoding
* @return RGB16 typedef
*/
public static TypedefDataType createRGB16Typedef(RGB16Encoding rgb16Encoding) {
Objects.requireNonNull(rgb16Encoding, "RGB16Encoding required");
TypedefDataType dt = new TypedefDataType(rgb16Encoding.name(), datatype);
Settings settings = dt.getDefaultSettings();
RGB16EncodingSettingsDefinition.DEF.setRGBEncoding(settings, rgb16Encoding);
return dt;
}
public RGB16ColorDataType() {
this(null);
}
public RGB16ColorDataType(DataTypeManager dtm) {
super("RGB16", dtm);
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
}
return new RGB16ColorDataType(dtm);
}
@Override
public int getLength() {
return LENGTH;
}
@Override
public String getDescription() {
return "An RGB color with 16-bit encoding (default encoding is RGB_565, use Typedef for other 16-bit encodings)";
}
@Override
public TypeDefSettingsDefinition[] getTypeDefSettingsDefinitions() {
return RGB16_TYPEDEF_SETTINGS;
}
@Override
protected Color decodeColor(MemBuffer buf, Settings settings) {
byte[] bytes = new byte[LENGTH];
buf.getBytes(bytes, 0);
int value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf)).getShort(bytes, 0);
int argbValue = 0; // scaled ARGB_8888 value
// Convert encoding to default ARGB_8888 value used by Java Color instantiation
RGB16Encoding rgbEncoding = RGB16EncodingSettingsDefinition.DEF.getRGBEncoding(settings);
switch (rgbEncoding) {
case RGB_565:
argbValue = 0xff << 24; // Alpha (enabled)
argbValue |= scaleFieldValue(getFieldValue(value, 11, 0x1f), 5) << 16; // R
argbValue |= scaleFieldValue(getFieldValue(value, 6, 0x3f), 6) << 8; // G
argbValue |= scaleFieldValue(getFieldValue(value, 0, 0x1f), 5); // B
break;
case RGB_555: {
argbValue = 0xff << 24; // Alpha (enabled)
argbValue |= scaleFieldValue(getFieldValue(value, 10, 0x1f), 5) << 16; // R
argbValue |= scaleFieldValue(getFieldValue(value, 5, 0x1f), 5) << 8; // G
argbValue |= scaleFieldValue(getFieldValue(value, 0, 0x1f), 5); // B
break;
}
case ARGB_1555: {
argbValue = (0xff * getFieldValue(value, 15, 0x1)) << 24; // Alpha
argbValue |= scaleFieldValue(getFieldValue(value, 10, 0x1f), 5) << 16; // R
argbValue |= scaleFieldValue(getFieldValue(value, 5, 0x1f), 5) << 8; // G
argbValue |= scaleFieldValue(getFieldValue(value, 0, 0x1f), 5); // B
break;
}
default:
throw new AssertionError("Missing RGB16 Encoding support: " + rgbEncoding);
}
// 32-bit ARGB_8888 Encoding is used by Java Color
return new Color(argbValue, true);
}
@Override
protected String getEncodingName(Settings settings) {
return RGB16EncodingSettingsDefinition.DEF.getRGBEncoding(settings).name();
}
@Override
protected List<ComponentValue> getComponentValues(MemBuffer buf, Settings settings) {
byte[] bytes = new byte[LENGTH];
buf.getBytes(bytes, 0);
int value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf)).getShort(bytes, 0);
List<ComponentValue> list = new ArrayList<>();
RGB16Encoding rgbEncoding = RGB16EncodingSettingsDefinition.DEF.getRGBEncoding(settings);
switch (rgbEncoding) {
case RGB_565:
list.add(new ComponentValue("R", getFieldValue(value, 11, 0x1f), 5));
list.add(new ComponentValue("G", getFieldValue(value, 6, 0x3f), 6));
list.add(new ComponentValue("B", getFieldValue(value, 0, 0x1f), 5));
break;
case RGB_555: {
list.add(new ComponentValue("R", getFieldValue(value, 10, 0x1f), 5));
list.add(new ComponentValue("G", getFieldValue(value, 5, 0x1f), 5));
list.add(new ComponentValue("B", getFieldValue(value, 0, 0x1f), 5));
break;
}
case ARGB_1555: {
list.add(new ComponentValue("A", getFieldValue(value, 15, 0x1), 1));
list.add(new ComponentValue("R", getFieldValue(value, 10, 0x1f), 5));
list.add(new ComponentValue("G", getFieldValue(value, 5, 0x1f), 5));
list.add(new ComponentValue("B", getFieldValue(value, 0, 0x1f), 5));
break;
}
default:
throw new AssertionError("Missing RGB16 Encoding support: " + rgbEncoding);
}
return list;
}
}

View file

@ -0,0 +1,182 @@
/* ###
* 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.program.model.data;
import java.util.NoSuchElementException;
import ghidra.docking.settings.EnumSettingsDefinition;
import ghidra.docking.settings.Settings;
/**
* The typedef settings definition which specifies a 16-bit RGB Color Encoding
*/
public class RGB16EncodingSettingsDefinition
implements EnumSettingsDefinition, TypeDefSettingsDefinition {
public enum RGB16Encoding {
RGB_565, RGB_555, ARGB_1555;
}
public static final RGB16Encoding DEFAULT_ENCODING = RGB16Encoding.RGB_565;
private static final String RGB16_ENCODING_SETTINGS_NAME = "rgb16";
private static final String DESCRIPTION = "Specifies a 16-bit RGB Color Encoding";
private static final String DISPLAY_NAME = "RGB16 Encoding";
private static final String[] choices = { RGB16Encoding.RGB_565.name(),
RGB16Encoding.RGB_555.name(), RGB16Encoding.ARGB_1555.name() };
public static final RGB16EncodingSettingsDefinition DEF = new RGB16EncodingSettingsDefinition();
private RGB16EncodingSettingsDefinition() {
}
/**
* Returns the RGB encoding standard based on the specified settings
* @param settings the instance settings or null for default value.
* @return the RGB encoding standard. The default encoding will be returned
* if no setting has been made.
*/
public RGB16Encoding getRGBEncoding(Settings settings) {
return RGB16Encoding.valueOf(getValueString(settings));
}
@Override
public int getChoice(Settings settings) {
if (settings == null) {
return 0;
}
Long value = settings.getLong(RGB16_ENCODING_SETTINGS_NAME);
if (value == null) {
return 0;
}
int choice = (int) value.longValue();
try {
if (choice >= 0 || choice < choices.length) {
return choice;
}
}
catch (NoSuchElementException e) {
// ignore
}
return 0;
}
@Override
public String getValueString(Settings settings) {
return choices[getChoice(settings)];
}
@Override
public void setChoice(Settings settings, int choice) {
try {
if (choice > 0 || choice < choices.length) {
// non-default encoding setting
settings.setLong(RGB16_ENCODING_SETTINGS_NAME, choice);
return;
}
}
catch (NoSuchElementException e) {
// ignore
}
settings.clearSetting(RGB16_ENCODING_SETTINGS_NAME);
}
public void setRGBEncoding(Settings settings, RGB16Encoding encoding) {
String encodingName = encoding.name();
for (int i = 0; i < choices.length; i++) {
if (choices[i].equals(encodingName)) {
setChoice(settings, i);
break;
}
}
throw new AssertionError("Missing RGB Encoding choice: " + encoding);
}
@Override
public String[] getDisplayChoices(Settings settings) {
return choices;
}
@Override
public String getName() {
return DISPLAY_NAME;
}
@Override
public String getStorageKey() {
return RGB16_ENCODING_SETTINGS_NAME;
}
@Override
public String getDescription() {
return DESCRIPTION;
}
@Override
public String getDisplayChoice(int value, Settings s1) {
return choices[value];
}
@Override
public void clear(Settings settings) {
settings.clearSetting(RGB16_ENCODING_SETTINGS_NAME);
}
@Override
public void copySetting(Settings settings, Settings destSettings) {
Long l = settings.getLong(RGB16_ENCODING_SETTINGS_NAME);
if (l == null) {
destSettings.clearSetting(RGB16_ENCODING_SETTINGS_NAME);
}
else {
destSettings.setLong(RGB16_ENCODING_SETTINGS_NAME, l);
}
}
@Override
public boolean hasValue(Settings setting) {
return setting.getValue(RGB16_ENCODING_SETTINGS_NAME) != null;
}
public String getDisplayChoice(Settings settings) {
return choices[getChoice(settings)];
}
/**
* Sets the settings object to the enum value indicating the specified choice as a string.
* @param settings the settings to store the value.
* @param choice enum string representing a choice in the enum.
*/
public void setDisplayChoice(Settings settings, String choice) {
for (int i = 0; i < choices.length; i++) {
if (choices[i].equals(choice)) {
setChoice(settings, i);
break;
}
}
}
@Override
public String getAttributeSpecification(Settings settings) {
int choice = getChoice(settings);
if (choice != 0) {
return choices[choice];
}
return null;
}
}

View file

@ -0,0 +1,172 @@
/* ###
* 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.program.model.data;
import java.awt.Color;
import java.util.*;
import ghidra.docking.settings.Settings;
import ghidra.program.model.data.RGB32EncodingSettingsDefinition.RGB32Encoding;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.DataConverter;
/**
* {@link RGB32ColorDataType} provides a base implementation for 32-bit RGB Color values with
* an Alpha channel. While this base implementation defaults to ARGB_8888 encoding a {@link TypeDef}
* may be established with a different 32-bit encoding specified via a default setting of
* {@link RGB32EncodingSettingsDefinition}.
*/
public class RGB32ColorDataType extends AbstractColorDataType {
public static RGB32ColorDataType datatype = new RGB32ColorDataType();
private static int LENGTH = 4;
private static TypeDefSettingsDefinition[] RGB32_TYPEDEF_SETTINGS = TypeDefSettingsDefinition
.concat(UnsignedIntegerDataType.dataType.getTypeDefSettingsDefinitions(),
RGB32EncodingSettingsDefinition.DEF);
/**
* Generate a 32-bit RGB typedef with a specific encoding
* @param rgb32Encoding 32-bit RGB encoding
* @return RGB32 typedef
*/
public static TypedefDataType createRGB32Typedef(RGB32Encoding rgb32Encoding) {
Objects.requireNonNull(rgb32Encoding, "RGB32Encoding required");
TypedefDataType dt = new TypedefDataType(rgb32Encoding.name(), datatype);
Settings settings = dt.getDefaultSettings();
RGB32EncodingSettingsDefinition.DEF.setRGBEncoding(settings, rgb32Encoding);
return dt;
}
public RGB32ColorDataType() {
this(null);
}
public RGB32ColorDataType(DataTypeManager dtm) {
super("RGB32", dtm);
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
}
return new RGB32ColorDataType(dtm);
}
@Override
public int getLength() {
return LENGTH;
}
@Override
public String getDescription() {
return "An RGB color with 32-bit encoding (default encoding is ARGB_8888, use Typedef for other 32-bit encodings)";
}
@Override
public TypeDefSettingsDefinition[] getTypeDefSettingsDefinitions() {
return RGB32_TYPEDEF_SETTINGS;
}
@Override
protected Color decodeColor(MemBuffer buf, Settings settings) {
byte[] bytes = new byte[LENGTH];
buf.getBytes(bytes, 0);
int value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf)).getInt(bytes, 0);
// Convert encoding to 32-bit ARGB_8888 value used by Java Color instantiation
RGB32Encoding rgbEncoding = RGB32EncodingSettingsDefinition.DEF.getRGBEncoding(settings);
switch (rgbEncoding) {
case ARGB_8888:
break;
case RGBA_8888: {
int alpha = value & 0xff;
int rgb = value >>> 8;
value = rgb + (alpha << 24);
break;
}
case BGRA_8888: {
value = Integer.reverseBytes(value);
break;
}
case ABGR_8888: {
int rgb = Integer.reverseBytes(value) >>> 8;
value = rgb + (value & 0xff000000);
break;
}
default:
throw new AssertionError("Missing RGB32 Encoding support: " + rgbEncoding);
}
// 32-bit ARGB_8888 Encoding is used by Java Color
return new Color(value, true);
}
@Override
protected String getEncodingName(Settings settings) {
return RGB32EncodingSettingsDefinition.DEF.getRGBEncoding(settings).name();
}
@Override
protected List<ComponentValue> getComponentValues(MemBuffer buf, Settings settings) {
byte[] bytes = new byte[LENGTH];
buf.getBytes(bytes, 0);
int value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf)).getInt(bytes, 0);
List<ComponentValue> list = new ArrayList<>();
RGB32Encoding rgbEncoding = RGB32EncodingSettingsDefinition.DEF.getRGBEncoding(settings);
switch (rgbEncoding) {
case ARGB_8888:
list.add(new ComponentValue("A", getFieldValue(value, 24, 0xff), 8));
list.add(new ComponentValue("R", getFieldValue(value, 16, 0xff), 8));
list.add(new ComponentValue("G", getFieldValue(value, 8, 0xff), 8));
list.add(new ComponentValue("B", getFieldValue(value, 0, 0xff), 8));
break;
case RGBA_8888: {
list.add(new ComponentValue("R", getFieldValue(value, 24, 0xff), 8));
list.add(new ComponentValue("G", getFieldValue(value, 16, 0xff), 8));
list.add(new ComponentValue("B", getFieldValue(value, 8, 0xff), 8));
list.add(new ComponentValue("A", getFieldValue(value, 0, 0xff), 8));
break;
}
case BGRA_8888: {
list.add(new ComponentValue("B", getFieldValue(value, 24, 0xff), 8));
list.add(new ComponentValue("G", getFieldValue(value, 16, 0xff), 8));
list.add(new ComponentValue("R", getFieldValue(value, 8, 0xff), 8));
list.add(new ComponentValue("A", getFieldValue(value, 0, 0xff), 8));
break;
}
case ABGR_8888: {
list.add(new ComponentValue("A", getFieldValue(value, 24, 0xff), 8));
list.add(new ComponentValue("B", getFieldValue(value, 16, 0xff), 8));
list.add(new ComponentValue("G", getFieldValue(value, 8, 0xff), 8));
list.add(new ComponentValue("R", getFieldValue(value, 0, 0xff), 8));
break;
}
default:
throw new AssertionError("Missing RGB32 Encoding support: " + rgbEncoding);
}
return list;
}
}

View file

@ -0,0 +1,183 @@
/* ###
* 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.program.model.data;
import java.util.NoSuchElementException;
import ghidra.docking.settings.EnumSettingsDefinition;
import ghidra.docking.settings.Settings;
/**
* The typedef settings definition which specifies a 32-bit RGB Color Encoding
*/
public class RGB32EncodingSettingsDefinition
implements EnumSettingsDefinition, TypeDefSettingsDefinition {
public enum RGB32Encoding {
ARGB_8888, RGBA_8888, BGRA_8888, ABGR_8888;
}
public static final RGB32Encoding DEFAULT_ENCODING = RGB32Encoding.ARGB_8888;
private static final String RGB32_ENCODING_SETTINGS_NAME = "rgb32";
private static final String DESCRIPTION = "Specifies a 32-bit RGB Color Encoding";
private static final String DISPLAY_NAME = "RGB32 Encoding";
private static final String[] choices =
{ RGB32Encoding.ARGB_8888.name(), RGB32Encoding.RGBA_8888.name(),
RGB32Encoding.BGRA_8888.name(), RGB32Encoding.ABGR_8888.name() };
public static final RGB32EncodingSettingsDefinition DEF = new RGB32EncodingSettingsDefinition();
private RGB32EncodingSettingsDefinition() {
}
/**
* Returns the RGB encoding standard based on the specified settings
* @param settings the instance settings or null for default value.
* @return the RGB encoding standard. The default encoding will be returned
* if no setting has been made.
*/
public RGB32Encoding getRGBEncoding(Settings settings) {
return RGB32Encoding.valueOf(getValueString(settings));
}
@Override
public int getChoice(Settings settings) {
if (settings == null) {
return 0;
}
Long value = settings.getLong(RGB32_ENCODING_SETTINGS_NAME);
if (value == null) {
return 0;
}
int choice = (int) value.longValue();
try {
if (choice >= 0 || choice < choices.length) {
return choice;
}
}
catch (NoSuchElementException e) {
// ignore
}
return 0;
}
@Override
public String getValueString(Settings settings) {
return choices[getChoice(settings)];
}
@Override
public void setChoice(Settings settings, int choice) {
try {
if (choice > 0 || choice < choices.length) {
// non-default encoding setting
settings.setLong(RGB32_ENCODING_SETTINGS_NAME, choice);
return;
}
}
catch (NoSuchElementException e) {
// ignore
}
settings.clearSetting(RGB32_ENCODING_SETTINGS_NAME);
}
public void setRGBEncoding(Settings settings, RGB32Encoding encoding) {
String encodingName = encoding.name();
for (int i = 0; i < choices.length; i++) {
if (choices[i].equals(encodingName)) {
setChoice(settings, i);
break;
}
}
throw new AssertionError("Missing RGB Encoding choice: " + encoding);
}
@Override
public String[] getDisplayChoices(Settings settings) {
return choices;
}
@Override
public String getName() {
return DISPLAY_NAME;
}
@Override
public String getStorageKey() {
return RGB32_ENCODING_SETTINGS_NAME;
}
@Override
public String getDescription() {
return DESCRIPTION;
}
@Override
public String getDisplayChoice(int value, Settings s1) {
return choices[value];
}
@Override
public void clear(Settings settings) {
settings.clearSetting(RGB32_ENCODING_SETTINGS_NAME);
}
@Override
public void copySetting(Settings settings, Settings destSettings) {
Long l = settings.getLong(RGB32_ENCODING_SETTINGS_NAME);
if (l == null) {
destSettings.clearSetting(RGB32_ENCODING_SETTINGS_NAME);
}
else {
destSettings.setLong(RGB32_ENCODING_SETTINGS_NAME, l);
}
}
@Override
public boolean hasValue(Settings setting) {
return setting.getValue(RGB32_ENCODING_SETTINGS_NAME) != null;
}
public String getDisplayChoice(Settings settings) {
return choices[getChoice(settings)];
}
/**
* Sets the settings object to the enum value indicating the specified choice as a string.
* @param settings the settings to store the value.
* @param choice enum string representing a choice in the enum.
*/
public void setDisplayChoice(Settings settings, String choice) {
for (int i = 0; i < choices.length; i++) {
if (choices[i].equals(choice)) {
setChoice(settings, i);
break;
}
}
}
@Override
public String getAttributeSpecification(Settings settings) {
int choice = getChoice(settings);
if (choice != 0) {
return choices[choice];
}
return null;
}
}

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -41,4 +41,27 @@ public interface TypeDefSettingsDefinition extends SettingsDefinition {
*/ */
String getAttributeSpecification(Settings settings); String getAttributeSpecification(Settings settings);
/**
* Create a new list of {@link TypeDefSettingsDefinition}s by concat'ing a base list with
* a var-arg'ish additional list of setting defs. Any additional duplicates are discarded.
* @param settings List of settings defs.
* @param additional More settings defs to add
* @return new array with all the settings defs joined together.
*/
public static TypeDefSettingsDefinition[] concat(TypeDefSettingsDefinition[] settings,
TypeDefSettingsDefinition... additional) {
if (additional == null) {
return settings;
}
if (settings == null) {
return additional;
}
TypeDefSettingsDefinition[] newArray =
new TypeDefSettingsDefinition[settings.length + additional.length];
System.arraycopy(settings, 0, newArray, 0, settings.length);
System.arraycopy(additional, 0, newArray, settings.length, additional.length);
return newArray;
}
} }

View file

@ -21,6 +21,7 @@ import ghidra.docking.settings.Settings;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeDisplayOptions; import ghidra.program.model.data.DataTypeDisplayOptions;
import ghidra.program.model.scalar.Scalar;
import ghidra.program.model.symbol.RefType; import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.Reference;
@ -30,8 +31,10 @@ import ghidra.program.model.symbol.Reference;
public interface Data extends CodeUnit, Settings { public interface Data extends CodeUnit, Settings {
/** /**
* Returns the value of the data item. The value may be an address, a scalar, * Returns the value of this data as determined by the corresponding {@link DataType}.
* register or null if no value. * The value may be an {@link Address}, {@link Scalar}, a datatype-defined object or null
* if no value.
*
* @return the value * @return the value
*/ */
public Object getValue(); public Object getValue();
@ -42,7 +45,7 @@ public interface Data extends CodeUnit, Settings {
* <p>NOTE: This determination is made based upon data type and settings only and does not * <p>NOTE: This determination is made based upon data type and settings only and does not
* examine memory bytes which are used to construct the data value object. * examine memory bytes which are used to construct the data value object.
* *
* @return value class or null if a consistent class is not utilized. * @return value class or null if a consistent value class is not utilized.
*/ */
public Class<?> getValueClass(); public Class<?> getValueClass();