mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GT-3501-rev308_Scalar_table_refactor'
This commit is contained in:
commit
2803e050c5
5 changed files with 341 additions and 224 deletions
|
@ -90,7 +90,7 @@
|
||||||
program. Any new code units containing scalars added to the program will
|
program. Any new code units containing scalars added to the program will
|
||||||
automatically appear in the table.</P>
|
automatically appear in the table.</P>
|
||||||
|
|
||||||
<P>To bring the <B>Scalar Table</B>, choose <B>Window</B><IMG src="../../shared/arrow.gif" border=
|
<P>To bring up the <B>Scalar Table</B>, choose <B>Window</B><IMG src="../../shared/arrow.gif" border=
|
||||||
"0"><B>Scalar Table</B> from the tool's menu. This table can be docked in the tool
|
"0"><B>Scalar Table</B> from the tool's menu. This table can be docked in the tool
|
||||||
if desired.</P>
|
if desired.</P>
|
||||||
|
|
||||||
|
@ -99,13 +99,17 @@
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>Location</B> - displays the address of the code unit containing the scalar.</LI>
|
<LI><B>Location</B> - displays the address of the code unit containing the scalar.</LI>
|
||||||
<LI><B>Preview</B> - displays the code unit containing the scalar.</LI>
|
<LI><B>Preview</B> - displays the code unit containing the scalar.</LI>
|
||||||
<LI><B>Hex</B> - displays the scalar as a hex number.</LI>
|
<LI><B>Hex</B> - displays the scalar as an unsigned hex number.</LI>
|
||||||
<LI><B>Decimal (Signed)</B> - displays the scalar as a decimal number.</LI>
|
<LI><B>Decimal (Signed)</B> - displays the scalar as a decimal number.</LI>
|
||||||
<LI><B>Function Name</B> - displays the name of the function containing the scalar.</LI>
|
<LI><B>Function Name</B> - displays the name of the function containing the scalar.</LI>
|
||||||
<LI><B>Decimal (Unsigned)</B> - displays the scalar as a decimal number (this
|
<LI><B>Decimal (Unsigned)</B> - displays the scalar as a decimal number (this
|
||||||
column is hidden by default).</LI>
|
column is hidden by default).</LI>
|
||||||
|
<LI><B>Bits</B> - displays the number of bits required to store the scalar value (this
|
||||||
|
column is hidden by default).</LI>
|
||||||
|
<LI><B>Signedness</B> - displays whether the scalar is <I>signed</I> or <I>unsigned</I> (this
|
||||||
|
column is hidden by default).</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H2><A name="Filter_Scalars"></A>Scalar Table Filters</H2>
|
<H2><A name="Filter_Scalars"></A>Scalar Table Filters</H2>
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/* ###
|
||||||
|
* 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.app.plugin.core.scalartable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import docking.widgets.table.constraint.*;
|
||||||
|
import docking.widgets.table.constraint.provider.LongEditorProvider;
|
||||||
|
import docking.widgets.table.constraint.provider.LongRangeEditorProvider;
|
||||||
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides Scalar-related column constraints.
|
||||||
|
*/
|
||||||
|
public class ScalarColumnConstraintProvider implements ColumnConstraintProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ColumnConstraint<?>> getColumnConstraints() {
|
||||||
|
|
||||||
|
List<ColumnConstraint<?>> list = new ArrayList<>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we're converting Scalar to Long, we'll also get the extant Long constraints;
|
||||||
|
* they'll operate on the scalars value, independent of signedness.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
list.add(makeSignedConstraint(new AtLeastColumnConstraint<>("At Least (signed)", 0l, new LongEditorProvider(), "scalar")));
|
||||||
|
list.add(makeSignedConstraint(new AtMostColumnConstraint<>("At Most (signed)", 0l, new LongEditorProvider(), "scalar")));
|
||||||
|
list.add(makeSignedConstraint(new InRangeColumnConstraint<>("In Range (signed)", 0l, 0l, new LongRangeEditorProvider(), "scalar")));
|
||||||
|
list.add(makeSignedConstraint(new NotInRangeColumnConstraint<>("Not In Range (signed)", 0l, 0l, new LongRangeEditorProvider(), "scalar")));
|
||||||
|
|
||||||
|
list.add(makeUnsignedConstraint(new AtLeastColumnConstraint<>("At Least (unsigned)", 0l, new LongEditorProvider(), "scalar-unsigned")));
|
||||||
|
list.add(makeUnsignedConstraint(new AtMostColumnConstraint<>("At Most (unsigned)", 0l, new LongEditorProvider(), "scalar-unsigned")));
|
||||||
|
list.add(makeUnsignedConstraint(new InRangeColumnConstraint<>("In Range (unsigned)", 0l, 0l, new LongRangeEditorProvider(), "scalar-unsigned")));
|
||||||
|
list.add(makeUnsignedConstraint(new NotInRangeColumnConstraint<>("Not In Range (unsigned)", 0l, 0l, new LongRangeEditorProvider(), "scalar-unsigned")));
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColumnConstraint<?> makeSignedConstraint(ColumnConstraint<Long> delegate) {
|
||||||
|
return new ScalarMappedColumnConstraint(new ScalarToSignedLongColumnTypeMapper(), delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColumnConstraint<?> makeUnsignedConstraint(ColumnConstraint<Long> delegate) {
|
||||||
|
return new ScalarMappedColumnConstraint(new ScalarToUnsignedLongColumnTypeMapper(),
|
||||||
|
delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that converts a Scalar to a signed Long value
|
||||||
|
*/
|
||||||
|
static class ScalarToSignedLongColumnTypeMapper extends ColumnTypeMapper<Scalar, Long> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long convert(Scalar value) {
|
||||||
|
return value.getSignedValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that converts a Scalar to an unsigned Long value
|
||||||
|
*/
|
||||||
|
static class ScalarToUnsignedLongColumnTypeMapper extends ColumnTypeMapper<Scalar, Long> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long convert(Scalar value) {
|
||||||
|
return value.getUnsignedValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to adapt Long-type constraints to Scalar-type columns.
|
||||||
|
*/
|
||||||
|
static class ScalarMappedColumnConstraint extends MappedColumnConstraint<Scalar, Long> {
|
||||||
|
|
||||||
|
public ScalarMappedColumnConstraint(ColumnTypeMapper<Scalar, Long> mapper,
|
||||||
|
ColumnConstraint<Long> delegate) {
|
||||||
|
super(mapper, delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ package ghidra.app.plugin.core.scalartable;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
|
@ -26,7 +27,6 @@ import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.Resource;
|
import ghidra.program.model.data.Resource;
|
||||||
import ghidra.program.model.lang.Register;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.Reference;
|
import ghidra.program.model.symbol.Reference;
|
||||||
|
@ -51,10 +51,6 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
|
|
||||||
static final int TEMP_MAX_RESULTS = 1_000_000;
|
static final int TEMP_MAX_RESULTS = 1_000_000;
|
||||||
|
|
||||||
private static final int FUNCTION_COL_WIDTH = 150;
|
|
||||||
private static final int HEXADECIMAL_COL_WIDTH = 100;
|
|
||||||
private static final int DECIMAL_COL_WIDTH = 100;
|
|
||||||
|
|
||||||
private Listing listing;
|
private Listing listing;
|
||||||
|
|
||||||
private ProgramSelection currentSelection;
|
private ProgramSelection currentSelection;
|
||||||
|
@ -77,12 +73,13 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()), 1, true);
|
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()), 1, true);
|
||||||
descriptor.addVisibleColumn(
|
descriptor.addVisibleColumn(
|
||||||
DiscoverableTableUtils.adaptColumForModel(this, new PreviewTableColumn()));
|
DiscoverableTableUtils.adaptColumForModel(this, new PreviewTableColumn()));
|
||||||
descriptor.addVisibleColumn(new ScalarHexValueTableColumn());
|
descriptor.addVisibleColumn(new ScalarHexUnsignedValueTableColumn());
|
||||||
descriptor.addVisibleColumn(new ScalarSignedDecimalValueTableColumn());
|
descriptor.addVisibleColumn(new ScalarSignedDecimalValueTableColumn());
|
||||||
descriptor.addHiddenColumn(new ScalarUnsignedDecimalValueTableColumn());
|
descriptor.addHiddenColumn(new ScalarUnsignedDecimalValueTableColumn());
|
||||||
descriptor.addVisibleColumn(
|
descriptor.addVisibleColumn(
|
||||||
DiscoverableTableUtils.adaptColumForModel(this, new ScalarFunctionNameTableColumn()));
|
DiscoverableTableUtils.adaptColumForModel(this, new ScalarFunctionNameTableColumn()));
|
||||||
|
descriptor.addHiddenColumn(new ScalarBitCountTableColumn());
|
||||||
|
descriptor.addHiddenColumn(new ScalarSignednessTableColumn());
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +166,7 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
Reference[] operandReferences = instruction.getOperandReferences(opIndex);
|
Reference[] operandReferences = instruction.getOperandReferences(opIndex);
|
||||||
|
|
||||||
if (operandReferences.length == 0) {
|
if (operandReferences.length == 0) {
|
||||||
getScalarFromInstruction(instruction, opObjs, monitor);
|
getScalarsFromInstruction(instruction, opObjs, monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,12 +197,16 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getScalarFromInstruction(Instruction instruction, Object[] opObjs,
|
private void getScalarsFromInstruction(Instruction instruction, Object[] opObjs,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
||||||
Scalar scalar = getScalarFromOperand(opObjs, monitor);
|
for (Object opObj : opObjs) {
|
||||||
if (scalar != null) {
|
monitor.checkCanceled();
|
||||||
addMatch(new ScalarRowObject(instruction, scalar));
|
|
||||||
|
Scalar scalar = getScalarFromOperand(opObj, monitor);
|
||||||
|
if (scalar != null) {
|
||||||
|
addMatch(new ScalarRowObject(instruction, scalar));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,25 +301,8 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
return rowObject.getAddress();
|
return rowObject.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scalar getScalarFromOperand(Object[] opObjs, TaskMonitor monitor)
|
private Scalar getScalarFromOperand(Object opObj, TaskMonitor monitor) {
|
||||||
throws CancelledException {
|
return opObj instanceof Scalar ? (Scalar) opObj : null;
|
||||||
|
|
||||||
if (opObjs == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object obj = null;
|
|
||||||
for (Object opObj : opObjs) {
|
|
||||||
monitor.checkCanceled();
|
|
||||||
if (opObj instanceof Register) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opObj instanceof Scalar) {
|
|
||||||
obj = opObj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (Scalar) obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scalar getScalarFromData(Data data) {
|
private Scalar getScalarFromData(Data data) {
|
||||||
|
@ -340,49 +324,110 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Columns
|
// Columns & Column helpers
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private class ScalarHexValueTableColumn
|
private class ScalarComparator implements Comparator<Scalar> {
|
||||||
extends AbstractDynamicTableColumn<ScalarRowObject, Scalar, Program>
|
|
||||||
implements ProgramLocationTableColumn<ScalarRowObject, Scalar> {
|
|
||||||
|
|
||||||
private GColumnRenderer<Scalar> renderer = new AbstractGColumnRenderer<Scalar>() {
|
@Override
|
||||||
@Override
|
public int compare(Scalar o1, Scalar o2) {
|
||||||
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
|
||||||
|
|
||||||
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
|
// @formatter:off
|
||||||
|
if (o1 == o2) { return 0;}
|
||||||
|
if (o1 == null) { return 1; }
|
||||||
|
if (o2 == null) { return -1; }
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
Scalar value = (Scalar) data.getValue();
|
// sort unsigned before signed
|
||||||
String text = asString(value);
|
if (o1.isSigned() != o2.isSigned()) {
|
||||||
label.setText(text);
|
return (o1.isSigned() ? 1 : -1);
|
||||||
label.setOpaque(true);
|
|
||||||
setHorizontalAlignment(SwingConstants.RIGHT);
|
|
||||||
return label;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String asString(Scalar s) {
|
return o1.compareTo(o2);
|
||||||
if (s == null) {
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class AbstractScalarValueRenderer extends AbstractGColumnRenderer<Scalar> {
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
||||||
|
|
||||||
|
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
|
||||||
|
|
||||||
|
Scalar value = (Scalar) data.getValue();
|
||||||
|
String text = formatScalar(value);
|
||||||
|
label.setText(text);
|
||||||
|
label.setOpaque(true);
|
||||||
|
setHorizontalAlignment(SwingConstants.RIGHT);
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String formatScalar(Scalar scalar);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColumnConstraintFilterMode getColumnConstraintFilterMode() {
|
||||||
|
return ColumnConstraintFilterMode.USE_COLUMN_CONSTRAINTS_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFilterString(Scalar t, Settings settings) {
|
||||||
|
return formatScalar(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class AbstractScalarValueTableColumn
|
||||||
|
extends AbstractDynamicTableColumn<ScalarRowObject, Scalar, Program>
|
||||||
|
implements ProgramLocationTableColumn<ScalarRowObject, Scalar> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Comparator<Scalar> getComparator() {
|
||||||
|
return new ScalarComparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProgramLocation getProgramLocation(ScalarRowObject rowObject, Settings settings,
|
||||||
|
Program p, ServiceProvider provider) {
|
||||||
|
return new ProgramLocation(p, rowObject.getAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScalarHexUnsignedValueTableColumn extends AbstractScalarValueTableColumn {
|
||||||
|
|
||||||
|
private static final int HEXADECIMAL_COL_WIDTH = 100;
|
||||||
|
|
||||||
|
AbstractScalarValueRenderer renderer = new AbstractScalarValueRenderer() {
|
||||||
|
|
||||||
|
private static final int RADIX = 16;
|
||||||
|
private static final boolean ZERO_PADDED = false;
|
||||||
|
private static final boolean SHOW_SIGN = false;
|
||||||
|
private static final String PREFIX = "0x";
|
||||||
|
private static final String SUFFIX = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String formatScalar(Scalar scalar) {
|
||||||
|
if (scalar == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return s.toString(16, false, false, "", "");
|
|
||||||
|
return scalar.toString(RADIX, ZERO_PADDED, SHOW_SIGN, PREFIX, SUFFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configureFont(JTable table, TableModel model, int column) {
|
protected void configureFont(JTable table, TableModel model, int column) {
|
||||||
setFont(getFixedWidthFont());
|
setFont(fixedWidthFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFilterString(Scalar t, Settings settings) {
|
public ColumnConstraintFilterMode getColumnConstraintFilterMode() {
|
||||||
return asString(t);
|
return ColumnConstraintFilterMode.USE_BOTH_COLUMN_RENDERER_FITLER_STRING_AND_CONSTRAINTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
return "Hex";
|
return "Hex (Unsigned)";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -390,27 +435,44 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
return HEXADECIMAL_COL_WIDTH;
|
return HEXADECIMAL_COL_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
|
||||||
ServiceProvider provider) throws IllegalArgumentException {
|
|
||||||
return rowObject.getScalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProgramLocation getProgramLocation(ScalarRowObject rowObject, Settings settings,
|
|
||||||
Program p, ServiceProvider provider) {
|
|
||||||
return new ProgramLocation(program, rowObject.getAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GColumnRenderer<Scalar> getColumnRenderer() {
|
public GColumnRenderer<Scalar> getColumnRenderer() {
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
||||||
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
|
Scalar scalar = rowObject.getScalar();
|
||||||
|
|
||||||
|
Scalar unsigned = new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false);
|
||||||
|
return unsigned;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScalarSignedDecimalValueTableColumn
|
private class ScalarSignedDecimalValueTableColumn extends AbstractScalarValueTableColumn {
|
||||||
extends AbstractDynamicTableColumn<ScalarRowObject, Long, Program>
|
|
||||||
implements ProgramLocationTableColumn<ScalarRowObject, Long> {
|
private static final int DECIMAL_COL_WIDTH = 100;
|
||||||
|
|
||||||
|
AbstractScalarValueRenderer renderer = new AbstractScalarValueRenderer() {
|
||||||
|
|
||||||
|
private static final int RADIX = 10;
|
||||||
|
private static final boolean ZERO_PADDED = false;
|
||||||
|
private static final boolean SHOW_SIGN = true;
|
||||||
|
private static final String PREFIX = "";
|
||||||
|
private static final String SUFFIX = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String formatScalar(Scalar scalar) {
|
||||||
|
if (scalar == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return scalar.toString(RADIX, ZERO_PADDED, SHOW_SIGN, PREFIX, SUFFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
|
@ -423,22 +485,45 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
public GColumnRenderer<Scalar> getColumnRenderer() {
|
||||||
ServiceProvider provider) throws IllegalArgumentException {
|
return renderer;
|
||||||
|
|
||||||
return rowObject.getScalar().getSignedValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProgramLocation getProgramLocation(ScalarRowObject rowObject, Settings settings,
|
public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
||||||
Program p, ServiceProvider provider) {
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
return new ProgramLocation(program, rowObject.getAddress());
|
Scalar scalar = rowObject.getScalar();
|
||||||
|
|
||||||
|
Scalar signed = new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), true);
|
||||||
|
return signed;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScalarUnsignedDecimalValueTableColumn
|
private class ScalarUnsignedDecimalValueTableColumn extends AbstractScalarValueTableColumn {
|
||||||
extends AbstractDynamicTableColumn<ScalarRowObject, Long, Program>
|
|
||||||
implements ProgramLocationTableColumn<ScalarRowObject, Long> {
|
private static final int DECIMAL_COL_WIDTH = 100;
|
||||||
|
|
||||||
|
AbstractScalarValueRenderer renderer = new AbstractScalarValueRenderer() {
|
||||||
|
|
||||||
|
private static final int RADIX = 10;
|
||||||
|
private static final boolean ZERO_PADDED = false;
|
||||||
|
private static final boolean SHOW_SIGN = false;
|
||||||
|
private static final String PREFIX = "";
|
||||||
|
private static final String SUFFIX = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String formatScalar(Scalar scalar) {
|
||||||
|
if (scalar == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return scalar.toString(RADIX, ZERO_PADDED, SHOW_SIGN, PREFIX, SUFFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
|
@ -451,10 +536,37 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
public GColumnRenderer<Scalar> getColumnRenderer() {
|
||||||
ServiceProvider provider) throws IllegalArgumentException {
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
return rowObject.getScalar().getUnsignedValue();
|
@Override
|
||||||
|
public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
||||||
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
|
Scalar scalar = rowObject.getScalar();
|
||||||
|
|
||||||
|
Scalar unsigned = new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false);
|
||||||
|
return unsigned;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScalarBitCountTableColumn
|
||||||
|
extends AbstractDynamicTableColumn<ScalarRowObject, Integer, Program>
|
||||||
|
implements ProgramLocationTableColumn<ScalarRowObject, Integer> {
|
||||||
|
|
||||||
|
private static final int BIT_COUNT_COL_WIDTH = 80;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumnName() {
|
||||||
|
return "Bits";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
||||||
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
|
return rowObject.getScalar().bitLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -462,10 +574,53 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
|
||||||
Program p, ServiceProvider provider) {
|
Program p, ServiceProvider provider) {
|
||||||
return new ProgramLocation(program, rowObject.getAddress());
|
return new ProgramLocation(program, rowObject.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnPreferredWidth() {
|
||||||
|
return BIT_COUNT_COL_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Signedness {
|
||||||
|
Signed, Unsigned
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScalarSignednessTableColumn
|
||||||
|
extends AbstractDynamicTableColumn<ScalarRowObject, Signedness, Program>
|
||||||
|
implements ProgramLocationTableColumn<ScalarRowObject, Signedness> {
|
||||||
|
|
||||||
|
private static final int SIGNEDNESS_COL_WIDTH = 100;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumnName() {
|
||||||
|
return "Signedness";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Signedness getValue(ScalarRowObject rowObject, Settings settings, Program p,
|
||||||
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
|
return rowObject.getScalar().isSigned() ? Signedness.Signed : Signedness.Unsigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProgramLocation getProgramLocation(ScalarRowObject rowObject, Settings settings,
|
||||||
|
Program p, ServiceProvider provider) {
|
||||||
|
return new ProgramLocation(program, rowObject.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnPreferredWidth() {
|
||||||
|
return SIGNEDNESS_COL_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScalarFunctionNameTableColumn extends FunctionNameTableColumn {
|
private class ScalarFunctionNameTableColumn extends FunctionNameTableColumn {
|
||||||
|
|
||||||
|
private static final int FUNCTION_COL_WIDTH = 150;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColumnPreferredWidth() {
|
public int getColumnPreferredWidth() {
|
||||||
return FUNCTION_COL_WIDTH;
|
return FUNCTION_COL_WIDTH;
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class Scalar implements Comparable<Scalar> {
|
||||||
public BigInteger getBigInteger() {
|
public BigInteger getBigInteger() {
|
||||||
int signum = (signed && testBit(bitLength - 1)) ? -1 : 1;
|
int signum = (signed && testBit(bitLength - 1)) ? -1 : 1;
|
||||||
|
|
||||||
// Get magnitide
|
// Get magnitude
|
||||||
int numBytes = ((bitLength - 1) / 8) + 1;
|
int numBytes = ((bitLength - 1) / 8) + 1;
|
||||||
long tmpVal = getValue();
|
long tmpVal = getValue();
|
||||||
if (signed && tmpVal < 0) {
|
if (signed && tmpVal < 0) {
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
|
||||||
* 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.scalar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ScalarFormat.java
|
|
||||||
*
|
|
||||||
* This class exists just to make it easy to hold onto sensible
|
|
||||||
* groupings and conventions for formatting scalars. This is
|
|
||||||
* used by Scalar in the toString(ScalarFormat) and the
|
|
||||||
* addToStringBuffer(StringBuffer, ScalarFormat) methods.
|
|
||||||
*
|
|
||||||
* @version 1999/02/04
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ScalarFormat {
|
|
||||||
private boolean zeroPadded;
|
|
||||||
private boolean signed;
|
|
||||||
private String pre;
|
|
||||||
private String post;
|
|
||||||
private int radix;
|
|
||||||
|
|
||||||
// Constructors:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Create a default ScalarFormat. (hex, zeropadded, unsigned
|
|
||||||
* no pre or post strings)</p>
|
|
||||||
*/
|
|
||||||
public ScalarFormat() {
|
|
||||||
radix = 16;
|
|
||||||
zeroPadded = true;
|
|
||||||
signed = false;
|
|
||||||
pre = "";
|
|
||||||
post = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p> Create a ScalarFormat with the given values.</p>
|
|
||||||
*
|
|
||||||
* @param radix the radix to use (only 2,8,10 and 16 are valid)..
|
|
||||||
* @param zeroPadded true if value should be 0 padded.
|
|
||||||
* @param signed true if value should be treated as signed.
|
|
||||||
* @param pre string to add after optional sign but before value.
|
|
||||||
* @param post string to add at end of the value.
|
|
||||||
* @throws IllegalArgumentException if radix is not one of (2,8,10,16).
|
|
||||||
*/
|
|
||||||
public ScalarFormat(int radix, boolean zeroPadded, boolean signed,
|
|
||||||
String pre, String post) {
|
|
||||||
switch (radix) {
|
|
||||||
case 2:
|
|
||||||
case 8:
|
|
||||||
case 10:
|
|
||||||
case 16:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid radix");
|
|
||||||
}
|
|
||||||
this.zeroPadded = zeroPadded;
|
|
||||||
this.signed = signed;
|
|
||||||
this.pre = pre;
|
|
||||||
this.post = post;
|
|
||||||
this.radix = radix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns whether value should be zero padded.</p>
|
|
||||||
*
|
|
||||||
* @return whether value should be zero padded.
|
|
||||||
*/
|
|
||||||
public boolean isZeroPadded() {
|
|
||||||
return zeroPadded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns whether value should be treated as signed.</p>
|
|
||||||
*
|
|
||||||
* @return whether value should be treated as signed.
|
|
||||||
*/
|
|
||||||
public boolean isSigned() {
|
|
||||||
return signed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns the prefix string.</p>
|
|
||||||
*
|
|
||||||
* @return the prefix string.
|
|
||||||
*/
|
|
||||||
public String getPre() {
|
|
||||||
return pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns the postfix string.</p>
|
|
||||||
*
|
|
||||||
* @return the postfix string.
|
|
||||||
*/
|
|
||||||
public String getPost() {
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns the radix.</p>
|
|
||||||
*
|
|
||||||
* @return the radix.
|
|
||||||
*/
|
|
||||||
public int getRadix() {
|
|
||||||
return radix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append("(radix=" + radix + ", ");
|
|
||||||
if (zeroPadded) {
|
|
||||||
buf.append("zero padded, ");
|
|
||||||
}
|
|
||||||
if (signed) {
|
|
||||||
buf.append("signed, ");
|
|
||||||
}
|
|
||||||
buf.append("pre='" + pre + "', post='" + post + "')");
|
|
||||||
return new String(buf);
|
|
||||||
}
|
|
||||||
} // ScalarFormat
|
|
Loading…
Add table
Add a link
Reference in a new issue