mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-4310_ghida1_RGB_DataTypes'
(Closes #6191)
This commit is contained in:
commit
794cb1c07c
18 changed files with 1073 additions and 62 deletions
|
@ -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.
|
||||
|
@ -23,6 +23,7 @@ import generic.theme.GThemeDefaults.Colors.Messages;
|
|||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.hover.AbstractConfigurableHover;
|
||||
import ghidra.app.util.ToolTipUtils;
|
||||
import ghidra.app.util.viewer.field.ResourceFieldLocation;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
|
@ -126,6 +127,11 @@ public class DataTypeListingHover extends AbstractConfigurableHover implements L
|
|||
(EquateOperandFieldLocation) programLocation;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -20,12 +20,20 @@ import java.math.BigInteger;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.*;
|
||||
import docking.widgets.fieldpanel.field.AbstractTextFieldElement;
|
||||
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.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.format.FieldFormatModel;
|
||||
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.ToolOptions;
|
||||
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.Playable;
|
||||
import ghidra.program.model.data.Union;
|
||||
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.symbol.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.program.model.symbol.Equate;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -180,8 +205,8 @@ abstract class OperandFieldHelper extends FieldFactory {
|
|||
this.maxDisplayLines = maxLines;
|
||||
}
|
||||
|
||||
FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField field,
|
||||
int opIndex, int column) {
|
||||
FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField field, int opIndex,
|
||||
int column) {
|
||||
if (field instanceof ListingTextField listingField) {
|
||||
RowColLocation rcl = listingField.dataToScreenLocation(opIndex, column);
|
||||
return new FieldLocation(index, fieldNum, rcl.row(), rcl.col());
|
||||
|
@ -211,7 +236,8 @@ abstract class OperandFieldHelper extends FieldFactory {
|
|||
|
||||
if (lf instanceof ImageFactoryField) {
|
||||
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(),
|
||||
data.getComponentPath(), codeUnitFormat.getDataValueRepresentationString(data),
|
||||
0, col, data);
|
||||
|
@ -362,6 +388,10 @@ abstract class OperandFieldHelper extends FieldFactory {
|
|||
return new ImageFactoryField(this, ((DataImage) value).getImageIcon(), proxy,
|
||||
getMetrics(), startX + varWidth, width);
|
||||
}
|
||||
if (value instanceof Icon) {
|
||||
return new ImageFactoryField(this, (Icon) value, proxy, getMetrics(), startX + varWidth,
|
||||
width);
|
||||
}
|
||||
else if (value instanceof Playable) {
|
||||
return new ImageFactoryField(this, ((Playable) value).getImageIcon(), proxy,
|
||||
getMetrics(), startX + varWidth, width);
|
||||
|
@ -452,8 +482,8 @@ abstract class OperandFieldHelper extends FieldFactory {
|
|||
if (wrapOnSemicolon) {
|
||||
List<FieldElement> lines = breakIntoLines(elements);
|
||||
if (lines.size() == 1) {
|
||||
return ListingTextField.createSingleLineTextField(this, proxy,
|
||||
lines.get(0), startX + varWidth, width, hlProvider);
|
||||
return ListingTextField.createSingleLineTextField(this, proxy, lines.get(0),
|
||||
startX + varWidth, width, hlProvider);
|
||||
}
|
||||
return ListingTextField.createMultilineTextField(this, proxy, lines, startX, width,
|
||||
hlProvider);
|
||||
|
|
|
@ -28,8 +28,10 @@ import ghidra.app.util.viewer.field.*;
|
|||
import ghidra.framework.options.*;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
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.scalar.Scalar;
|
||||
import ghidra.util.classfinder.*;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
|
@ -259,8 +261,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||
return false;
|
||||
}
|
||||
DataType type = data.getBaseDataType();
|
||||
return type.getLength() > 0 && type instanceof AbstractIntegerDataType ||
|
||||
type instanceof DefaultDataType;
|
||||
return type.getLength() > 0 && type.getValueClass(null) == Scalar.class;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -944,8 +945,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||
|
||||
private class MultipleHighlighterProvider implements ListingHighlightProvider {
|
||||
|
||||
private List<ListingHighlightProvider> highlightProviders =
|
||||
new CopyOnWriteArrayList<>();
|
||||
private List<ListingHighlightProvider> highlightProviders = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public Highlight[] createHighlights(String text, ListingField field, int cursorTextOffset) {
|
||||
|
@ -961,8 +961,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||
int size = highlightProviders.size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
ListingHighlightProvider provider = highlightProviders.get(i);
|
||||
Highlight[] highlights =
|
||||
provider.createHighlights(text, field, cursorTextOffset);
|
||||
Highlight[] highlights = provider.createHighlights(text, field, cursorTextOffset);
|
||||
for (Highlight highlight : highlights) {
|
||||
list.add(highlight);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -16,7 +16,6 @@
|
|||
package ghidra.docking.settings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
|
@ -40,14 +39,10 @@ public interface SettingsDefinition {
|
|||
if (settings == null) {
|
||||
return additional;
|
||||
}
|
||||
ArrayList<SettingsDefinition> list = new ArrayList<>();
|
||||
list.addAll(Arrays.asList(settings));
|
||||
for (SettingsDefinition def : additional) {
|
||||
if (!list.contains(def)) {
|
||||
list.add(def);
|
||||
}
|
||||
}
|
||||
return list.toArray(new SettingsDefinition[list.size()]);
|
||||
SettingsDefinition[] newArray = new SettingsDefinition[settings.length + additional.length];
|
||||
System.arraycopy(settings, 0, newArray, 0, settings.length);
|
||||
System.arraycopy(additional, 0, newArray, settings.length, additional.length);
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import ghidra.util.UniversalID;
|
|||
*/
|
||||
public abstract class AbstractDataType implements DataType {
|
||||
|
||||
private final static TypeDefSettingsDefinition[] EMPTY_TYPEDEF_DEFINITIONS =
|
||||
protected final static TypeDefSettingsDefinition[] EMPTY_TYPEDEF_DEFINITIONS =
|
||||
new TypeDefSettingsDefinition[0];
|
||||
|
||||
protected String name;
|
||||
|
|
|
@ -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.
|
||||
|
@ -53,9 +53,12 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
|||
protected static final DataTypeMnemonicSettingsDefinition MNEMONIC =
|
||||
DataTypeMnemonicSettingsDefinition.DEF;
|
||||
|
||||
private static SettingsDefinition[] SETTINGS_DEFS =
|
||||
protected static final SettingsDefinition[] SETTINGS_DEFS =
|
||||
{ FormatSettingsDefinition.DEF_HEX, PADDING, ENDIAN, MNEMONIC };
|
||||
|
||||
protected static final TypeDefSettingsDefinition[] TYPEDEF_SETTINGS_DEFS =
|
||||
EMPTY_TYPEDEF_DEFINITIONS;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -81,6 +84,11 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
|||
return SETTINGS_DEFS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDefSettingsDefinition[] getTypeDefSettingsDefinitions() {
|
||||
return TYPEDEF_SETTINGS_DEFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this type is signed.
|
||||
* @return true if this is a signed integer data-type
|
||||
|
@ -243,9 +251,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
|||
this);
|
||||
}
|
||||
BigInteger maxValueExclusive = BigInteger.ONE.shiftLeft(length * 8 - (isSigned() ? 1 : 0));
|
||||
BigInteger minValueInclusive = isSigned()
|
||||
? BigInteger.ONE.shiftLeft(length * 8 - 1).negate()
|
||||
: BigInteger.ZERO;
|
||||
BigInteger minValueInclusive =
|
||||
isSigned() ? BigInteger.ONE.shiftLeft(length * 8 - 1).negate() : BigInteger.ZERO;
|
||||
if (bigValue.compareTo(maxValueExclusive) >= 0) {
|
||||
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))
|
||||
.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 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 settings integer format settings (PADDING, FORMAT, etc.)
|
||||
* @param bitLength number of value bits to be used from bigInt
|
||||
* @param isSigned true if type is signed, else false
|
||||
* @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 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
|
||||
bigInt = bigInt.add(BigInteger.valueOf(2).pow(bitLength));
|
||||
}
|
||||
|
|
|
@ -102,8 +102,8 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
/**
|
||||
* 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.
|
||||
* @param declaredBitSize
|
||||
* @param baseTypeByteSize
|
||||
* @param declaredBitSize declare bitfield size
|
||||
* @param baseTypeByteSize base datatype size in bytes
|
||||
* @return effective bit-size
|
||||
*/
|
||||
public static int getEffectiveBitSize(int declaredBitSize, int baseTypeByteSize) {
|
||||
|
@ -417,9 +417,13 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
if (dt instanceof Enum) {
|
||||
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;
|
||||
if (intDT.getFormatSettingsDefinition()
|
||||
.getFormat(settings) == FormatSettingsDefinition.CHAR) {
|
||||
int format = intDT.getFormatSettingsDefinition().getFormat(settings);
|
||||
if (format == FormatSettingsDefinition.CHAR) {
|
||||
if (big.signum() < 0) {
|
||||
big = big.add(BigInteger.valueOf(2).pow(effectiveBitSize));
|
||||
}
|
||||
|
@ -429,7 +433,7 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
return StringDataInstance.getCharRepresentation(this, bytes, settings);
|
||||
}
|
||||
|
||||
return intDT.getRepresentation(big, settings, effectiveBitSize);
|
||||
return AbstractIntegerDataType.getRepresentation(big, settings, effectiveBitSize, isSigned);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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.
|
||||
|
@ -28,7 +28,7 @@ import ghidra.program.model.mem.MemoryAccessException;
|
|||
*/
|
||||
public class BooleanDataType extends AbstractUnsignedIntegerDataType {
|
||||
|
||||
private static SettingsDefinition[] SETTINGS_DEFS = {};
|
||||
private static SettingsDefinition[] BOOLEAN_SETTINGS_DEFS = {};
|
||||
|
||||
public static final BooleanDataType dataType = new BooleanDataType();
|
||||
|
||||
|
@ -95,14 +95,13 @@ public class BooleanDataType extends AbstractUnsignedIntegerDataType {
|
|||
return b.booleanValue() ? "TRUE" : "FALSE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) {
|
||||
return BigInteger.ZERO.equals(bigInt) ? "FALSE" : "TRUE";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SettingsDefinition[] getBuiltInSettingsDefinitions() {
|
||||
return SETTINGS_DEFS;
|
||||
return BOOLEAN_SETTINGS_DEFS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -84,6 +84,11 @@ public class DefaultDataType extends DataTypeImpl {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
return Scalar.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
return this;
|
||||
|
|
|
@ -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.
|
||||
|
@ -35,7 +35,7 @@ public class PointerTypeSettingsDefinition
|
|||
private static final String[] choices =
|
||||
{ "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() {
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
@ -41,4 +41,27 @@ public interface TypeDefSettingsDefinition extends SettingsDefinition {
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import ghidra.docking.settings.Settings;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeDisplayOptions;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.program.model.symbol.RefType;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
|
||||
|
@ -30,8 +31,10 @@ import ghidra.program.model.symbol.Reference;
|
|||
public interface Data extends CodeUnit, Settings {
|
||||
|
||||
/**
|
||||
* Returns the value of the data item. The value may be an address, a scalar,
|
||||
* register or null if no value.
|
||||
* Returns the value of this data as determined by the corresponding {@link DataType}.
|
||||
* The value may be an {@link Address}, {@link Scalar}, a datatype-defined object or null
|
||||
* if no value.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
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
|
||||
* 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();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue