Merge branch 'GP-1379_ghidra1_FloatDataTypeValues' (Closes #4853)

This commit is contained in:
ghidra1 2023-04-26 17:00:28 -04:00
commit 6d85c6cbc1
116 changed files with 2122 additions and 1757 deletions

View file

@ -27,6 +27,7 @@ import ghidra.dbg.target.TargetDataTypeMember;
import ghidra.dbg.target.TargetNamedDataType; import ghidra.dbg.target.TargetNamedDataType;
import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator; import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.util.Msg; import ghidra.util.Msg;
public class TargetDataTypeConverter { public class TargetDataTypeConverter {
@ -481,6 +482,8 @@ public class TargetDataTypeConverter {
case SINT: case SINT:
return AbstractIntegerDataType.getSignedDataType(tPrimitive.getLength(), dtm); return AbstractIntegerDataType.getSignedDataType(tPrimitive.getLength(), dtm);
case FLOAT: case FLOAT:
// TODO: lookup by length must use "raw" encoding size since "aligned" lengths
// may be duplicated across different float types.
return AbstractFloatDataType.getFloatDataType(tPrimitive.getLength(), dtm); return AbstractFloatDataType.getFloatDataType(tPrimitive.getLength(), dtm);
case COMPLEX: case COMPLEX:
return AbstractComplexDataType.getComplexDataType(tPrimitive.getLength(), dtm); return AbstractComplexDataType.getComplexDataType(tPrimitive.getLength(), dtm);

View file

@ -23,8 +23,8 @@ import db.DBRecord;
import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.AbstractFloatDataType;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.Varnode; import ghidra.program.model.pcode.Varnode;

View file

@ -126,22 +126,51 @@ public class CreateDataBackgroundCmd extends BackgroundCommand {
return true; return true;
} }
private static Address alignAddress(Address addr, int alignment) {
if (addr == null) {
return null;
}
long mod = addr.getOffset() % alignment;
if (mod == 0) {
return addr;
}
try {
return addr.addNoWrap(alignment - mod);
}
catch (AddressOverflowException e) {
// ignore
}
return null;
}
private void createData(Address start, Address end, DataType dataType, Program p, private void createData(Address start, Address end, DataType dataType, Program p,
TaskMonitor monitor) throws AddressOverflowException, CodeUnitInsertionException { TaskMonitor monitor) throws CodeUnitInsertionException {
int alignment = 1;
if (newDataType.getLength() != newDataType.getAlignedLength()) {
// datatypes whose length does not match their aligned-length must
// be properly aligned to account for padding (e.g., x86-32 80-bit floats)
alignment = newDataType.getAlignment();
}
int initialProgress = bytesApplied;
Listing listing = p.getListing(); Listing listing = p.getListing();
listing.clearCodeUnits(start, end, false); listing.clearCodeUnits(start, end, false);
int length = (int) end.subtract(start) + 1; Address nextAddr = alignAddress(start, alignment);
while (start.compareTo(end) <= 0) { int length = (int) end.subtract(nextAddr) + 1;
while (nextAddr != null && nextAddr.compareTo(end) <= 0) {
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
return; return;
} }
Data d = listing.createData(start, dataType, length); Data d = listing.createData(nextAddr, dataType, length);
int dataLen = d.getLength(); Address maxDataAddr = d.getMaxAddress();
start = start.addNoWrap(dataLen); bytesApplied = initialProgress + (int) maxDataAddr.subtract(start) + 1;
length -= dataLen; nextAddr = alignAddress(maxDataAddr.next(), alignment);
bytesApplied += dataLen; if (nextAddr != null) {
length = (int) end.subtract(nextAddr) + 1;
}
monitor.setProgress(bytesApplied); monitor.setProgress(bytesApplied);
if (++numDataCreated % 10000 == 0) { if (++numDataCreated % 10000 == 0) {

View file

@ -133,7 +133,7 @@ public class CreateDataInStructureBackgroundCmd extends BackgroundCommand {
// MemBuffer memBuf = new ProgramStructureProviderContext(program,addr, // MemBuffer memBuf = new ProgramStructureProviderContext(program,addr,
// struct, struct.getComponent(index).getOffset()); // struct, struct.getComponent(index).getOffset());
DataTypeInstance dti = DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(newDataType, length); DataTypeInstance.getDataTypeInstance(newDataType, length, true);
if (dti == null || dti.getLength() > length) { if (dti == null || dti.getLength() > length) {
break; break;
} }

View file

@ -114,7 +114,8 @@ public class CreateDataInStructureCmd implements Command {
else { else {
// MemBuffer memBuf = new ProgramStructureProviderContext(program,addr, // MemBuffer memBuf = new ProgramStructureProviderContext(program,addr,
// struct, dataComp.getParentOffset()); // struct, dataComp.getParentOffset());
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(newDataType, -1); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(newDataType, -1, true);
struct.replace(index, dti.getDataType(), dti.getLength()); struct.replace(index, dti.getDataType(), dti.getLength());
} }
} }

View file

@ -212,7 +212,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
} }
DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true); DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true);
int resultLen = resultDt.getLength(); int resultLen = resultDt.getAlignedLength();
if (resultDt instanceof Dynamic) { if (resultDt instanceof Dynamic) {
resultLen = DataTypeHelper.requestDtSize(getProvider(), resultDt.getDisplayName(), resultLen = DataTypeHelper.requestDtSize(getProvider(), resultDt.getDisplayName(),
@ -222,7 +222,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
throw new InvalidDataTypeException("Data types of size 0 are not allowed."); throw new InvalidDataTypeException("Data types of size 0 are not allowed.");
} }
return DataTypeInstance.getDataTypeInstance(resultDt, resultLen); return DataTypeInstance.getDataTypeInstance(resultDt, resultLen, true);
} }
/** /**
@ -1172,7 +1172,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
dtName = dt.getDisplayName(); dtName = dt.getDisplayName();
if (dtString.equals(dtName)) { if (dtString.equals(dtName)) {
return DataTypeInstance.getDataTypeInstance(element.getDataType(), return DataTypeInstance.getDataTypeInstance(element.getDataType(),
element.getLength()); element.getLength(), true);
} }
} }
@ -1204,7 +1204,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (maxLength > 0 && newLength > maxLength) { if (maxLength > 0 && newLength > maxLength) {
throw new UsrException(newDt.getDisplayName() + " doesn't fit."); throw new UsrException(newDt.getDisplayName() + " doesn't fit.");
} }
return DataTypeInstance.getDataTypeInstance(newDt, newLength); return DataTypeInstance.getDataTypeInstance(newDt, newLength, true);
} }
@SuppressWarnings("unused") // the exception is thrown by subclasses @SuppressWarnings("unused") // the exception is thrown by subclasses

View file

@ -570,7 +570,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
else if (columnIndex == getDataTypeColumn()) { else if (columnIndex == getDataTypeColumn()) {
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
int dtLen = dt.getLength(); int dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength()); return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength(),
true);
} }
else if (columnIndex == getNameColumn()) { else if (columnIndex == getNameColumn()) {
value = dtc.getFieldName(); value = dtc.getFieldName();

View file

@ -146,7 +146,7 @@ public class DataTypeHelper {
throw new InvalidDataTypeException( throw new InvalidDataTypeException(
"Data type " + dt.getDisplayName() + " has no size and is not allowed."); "Data type " + dt.getDisplayName() + " has no size and is not allowed.");
} }
return DataTypeInstance.getDataTypeInstance(dt, dtLen); return DataTypeInstance.getDataTypeInstance(dt, dtLen, true);
} }
public static int requestDtSize(CompositeEditorProvider provider, String dtName, public static int requestDtSize(CompositeEditorProvider provider, String dtName,
@ -203,7 +203,7 @@ public class DataTypeHelper {
int maxBytes = model.getMaxReplaceLength(index); int maxBytes = model.getMaxReplaceLength(index);
return requestBytes(model, dt, maxBytes); return requestBytes(model, dt, maxBytes);
} }
return DataTypeInstance.getDataTypeInstance(dt, length); return DataTypeInstance.getDataTypeInstance(dt, length, true);
} }
public static DataTypeInstance requestBytes(CompositeEditorModel model, DataType dt, public static DataTypeInstance requestBytes(CompositeEditorModel model, DataType dt,
@ -228,7 +228,7 @@ public class DataTypeHelper {
if (size >= 1) { if (size >= 1) {
model.setLastNumBytes(size); model.setLastNumBytes(size);
return DataTypeInstance.getDataTypeInstance(dt, size); return DataTypeInstance.getDataTypeInstance(dt, size, true);
} }
return null; return null;
} }

View file

@ -59,7 +59,8 @@ public class InsertUndefinedAction extends CompositeEditorTableAction {
DataType undefinedDt = DataType undefinedDt =
model.viewComposite.isPackingEnabled() ? Undefined1DataType.dataType model.viewComposite.isPackingEnabled() ? Undefined1DataType.dataType
: DataType.DEFAULT; : DataType.DEFAULT;
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(undefinedDt, -1); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(undefinedDt, -1, false);
model.insert(index, dti.getDataType(), dti.getLength()); model.insert(index, dti.getDataType(), dti.getLength());
} }
} }

View file

@ -161,7 +161,8 @@ class StructureEditorModel extends CompEditorModel {
else if (columnIndex == getDataTypeColumn()) { else if (columnIndex == getDataTypeColumn()) {
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
int dtLen = dt.getLength(); int dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength()); return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength(),
true);
} }
else if (columnIndex == getNameColumn()) { else if (columnIndex == getNameColumn()) {
value = dtc.getFieldName(); value = dtc.getFieldName();

View file

@ -141,7 +141,7 @@ class CreateArrayAction extends ListingContextAction {
} }
int length = sel.getByteLength(); int length = sel.getByteLength();
int numElements = length / dt.getLength(); int numElements = length / dt.getAlignedLength();
Command cmd = new CreateArrayInStructureCmd(from.getAddress(), numElements, dt, Command cmd = new CreateArrayInStructureCmd(from.getAddress(), numElements, dt,
from.getComponentPath()); from.getComponentPath());
@ -161,7 +161,7 @@ class CreateArrayAction extends ListingContextAction {
} }
length += dtc.getLength(); length += dtc.getLength();
} }
return length / dt.getLength(); return length / dt.getAlignedLength();
} }
private int getMaxElements(Structure struct, int index, DataType dt) { private int getMaxElements(Structure struct, int index, DataType dt) {
@ -171,7 +171,7 @@ class CreateArrayAction extends ListingContextAction {
DataTypeComponent dtc = struct.getComponent(index++); DataTypeComponent dtc = struct.getComponent(index++);
length += dtc.getLength(); length += dtc.getLength();
} }
return length / dt.getLength(); return length / dt.getAlignedLength();
} }
private void createArrayAtAddress(Program program, Address addr) { private void createArrayAtAddress(Program program, Address addr) {
@ -210,10 +210,13 @@ class CreateArrayAction extends ListingContextAction {
return; return;
} }
DataType dt = data.getDataType(); DataType dt = data.getDataType();
int dtLength = data.getLength(); int elementLength = data.getLength();
if (!(dt instanceof Dynamic)) {
elementLength = dt.getAlignedLength();
}
int length = (int) range.getLength(); int length = (int) range.getLength();
int numElements = length / dtLength; int numElements = length / elementLength;
CreateArrayCmd cmd = new CreateArrayCmd(addr, numElements, dt, dtLength); CreateArrayCmd cmd = new CreateArrayCmd(addr, numElements, dt, elementLength);
if (!tool.execute(cmd, program)) { if (!tool.execute(cmd, program)) {
tool.setStatusInfo(cmd.getStatusMsg()); tool.setStatusInfo(cmd.getStatusMsg());
} }

View file

@ -501,7 +501,7 @@ public class DataPlugin extends Plugin implements DataService {
} }
DataTypeInstance dataTypeInstance = DataTypeInstance.getDataTypeInstance(dataType, DataTypeInstance dataTypeInstance = DataTypeInstance.getDataTypeInstance(dataType,
new DumbMemBufferImpl(program.getMemory(), start)); new DumbMemBufferImpl(program.getMemory(), start), false);
if (dataTypeInstance == null) { if (dataTypeInstance == null) {
tool.setStatusInfo("Unallowed data type at " + start + ": " + dataType.getName()); tool.setStatusInfo("Unallowed data type at " + start + ": " + dataType.getName());
return -1; return -1;

View file

@ -1,494 +0,0 @@
/* ###
* 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.datamgr;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import docking.widgets.checkbox.GCheckBox;
import docking.widgets.label.GLabel;
import ghidra.program.model.data.DataOrganizationImpl;
import ghidra.util.layout.PairLayout;
public class DataOrganizationPanel extends JPanel {
JCheckBox charIsSignedCheckbox;
JTextField charSizeComponent;
JTextField wcharSizeComponent;
JTextField shortSizeComponent;
JTextField integerSizeComponent;
JTextField longSizeComponent;
JTextField longLongSizeComponent;
JTextField floatSizeComponent;
JTextField doubleSizeComponent;
JTextField longDoubleSizeComponent;
JTextField absoluteMaxAlignComponent;
JTextField machineAlignComponent;
JTextField defaultAlignComponent;
JTextField pointerAlignComponent;
DataOrganizationImpl dataOrganization;
public DataOrganizationPanel() {
super(new PairLayout(3, 5));
setUpAbsoluteMaxAlignment();
setUpMachineAlignment();
setUpDefaultAlignment();
setUpPointerAlignment();
setUpSignedChar();
setUpCharSize();
setUpWideCharSize();
setUpShortSize();
setUpIntegerSize();
setUpLongSize();
setUpLongLongSize();
setUpFloatSize();
setUpDoubleSize();
setUpLongDoubleSize();
add(new GLabel(""));
add(new GLabel(""));
add(new GLabel("Absolute Max Alignment"));
add(absoluteMaxAlignComponent);
add(new GLabel("Machine Alignment"));
add(machineAlignComponent);
add(new GLabel("Default Alignment"));
add(defaultAlignComponent);
add(new GLabel("Default Pointer Alignment"));
add(pointerAlignComponent);
add(new GLabel(""));
add(new GLabel(""));
add(new GLabel("Signed-Char:"));
add(charIsSignedCheckbox);
add(new GLabel("Char Size"));
add(charSizeComponent);
add(new GLabel("Wide-Char Size"));
add(wcharSizeComponent);
add(new GLabel("Short Size"));
add(shortSizeComponent);
add(new GLabel("Integer Size"));
add(integerSizeComponent);
add(new GLabel("Long Size"));
add(longSizeComponent);
add(new GLabel("LongLong Size"));
add(longLongSizeComponent);
add(new GLabel("Float Size"));
add(floatSizeComponent);
add(new GLabel("Double Size"));
add(doubleSizeComponent);
add(new GLabel("LongDouble Size"));
add(longDoubleSizeComponent);
add(new GLabel(""));
add(new GLabel(""));
}
public void setOrganization(DataOrganizationImpl dataOrganization) {
this.dataOrganization = dataOrganization;
int absoluteMaxAlignment = dataOrganization.getAbsoluteMaxAlignment();
int machineAlignment = dataOrganization.getMachineAlignment();
int defaultAlignment = dataOrganization.getDefaultAlignment();
int defaultPointerAlignment = dataOrganization.getDefaultPointerAlignment();
int charSize = dataOrganization.getCharSize();
int wcharSize = dataOrganization.getWideCharSize();
int shortSize = dataOrganization.getShortSize();
int integerSize = dataOrganization.getIntegerSize();
int longSize = dataOrganization.getLongSize();
int longLongSize = dataOrganization.getLongLongSize();
int floatSize = dataOrganization.getFloatSize();
int doubleSize = dataOrganization.getDoubleSize();
int longDoubleSize = dataOrganization.getLongDoubleSize();
String maxAlignString =
(absoluteMaxAlignment == 0) ? "none" : Integer.toString(absoluteMaxAlignment);
absoluteMaxAlignComponent.setText(maxAlignString);
machineAlignComponent.setText(Integer.toString(machineAlignment));
defaultAlignComponent.setText(Integer.toString(defaultAlignment));
pointerAlignComponent.setText(Integer.toString(defaultPointerAlignment));
charSizeComponent.setText(Integer.toString(charSize));
wcharSizeComponent.setText(Integer.toString(wcharSize));
shortSizeComponent.setText(Integer.toString(shortSize));
integerSizeComponent.setText(Integer.toString(integerSize));
longSizeComponent.setText(Integer.toString(longSize));
longLongSizeComponent.setText(Integer.toString(longLongSize));
floatSizeComponent.setText(Integer.toString(floatSize));
doubleSizeComponent.setText(Integer.toString(doubleSize));
longDoubleSizeComponent.setText(Integer.toString(longDoubleSize));
}
private void setUpSignedChar() {
charIsSignedCheckbox = new GCheckBox();
charIsSignedCheckbox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateSignedChar();
}
});
}
private void setUpCharSize() {
charSizeComponent = new JTextField(3);
charSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedCharSize();
}
});
charSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedCharSize();
}
});
}
private void setUpWideCharSize() {
wcharSizeComponent = new JTextField(3);
wcharSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedWideCharSize();
}
});
wcharSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedWideCharSize();
}
});
}
private void setUpShortSize() {
shortSizeComponent = new JTextField(3);
shortSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedShortSize();
}
});
shortSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedShortSize();
}
});
}
private void setUpIntegerSize() {
integerSizeComponent = new JTextField(3);
integerSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedIntegerSize();
}
});
integerSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedIntegerSize();
}
});
}
private void setUpLongSize() {
longSizeComponent = new JTextField(3);
longSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedLongSize();
}
});
longSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedLongSize();
}
});
}
private void setUpLongLongSize() {
longLongSizeComponent = new JTextField(3);
longLongSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedLongLongSize();
}
});
longLongSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedLongLongSize();
}
});
}
private void setUpFloatSize() {
floatSizeComponent = new JTextField(3);
floatSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedFloatSize();
}
});
floatSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedFloatSize();
}
});
}
private void setUpDoubleSize() {
doubleSizeComponent = new JTextField(3);
doubleSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedDoubleSize();
}
});
doubleSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedDoubleSize();
}
});
}
private void setUpLongDoubleSize() {
longDoubleSizeComponent = new JTextField(3);
longDoubleSizeComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedLongDoubleSize();
}
});
longDoubleSizeComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedLongDoubleSize();
}
});
}
private void setUpAbsoluteMaxAlignment() {
absoluteMaxAlignComponent = new JTextField(3);
absoluteMaxAlignComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedAbsoluteMaxAlignment();
}
});
absoluteMaxAlignComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedAbsoluteMaxAlignment();
}
});
}
private void setUpMachineAlignment() {
machineAlignComponent = new JTextField(3);
machineAlignComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedMachineAlignment();
}
});
machineAlignComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedMachineAlignment();
}
});
}
private void setUpDefaultAlignment() {
defaultAlignComponent = new JTextField(3);
defaultAlignComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedDefaultAlignment();
}
});
defaultAlignComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedDefaultAlignment();
}
});
}
private void setUpPointerAlignment() {
pointerAlignComponent = new JTextField(3);
pointerAlignComponent.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatedDefaultPointerAlignment();
}
});
pointerAlignComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// TODO
}
@Override
public void focusLost(FocusEvent e) {
updatedDefaultPointerAlignment();
}
});
}
protected void updateSignedChar() {
boolean isSigned = charIsSignedCheckbox.isSelected();
dataOrganization.setCharIsSigned(isSigned);
}
protected void updatedCharSize() {
int charSize = Integer.decode(charSizeComponent.getText()).intValue();
dataOrganization.setCharSize(charSize);
}
protected void updatedWideCharSize() {
int wcharSize = Integer.decode(wcharSizeComponent.getText()).intValue();
dataOrganization.setWideCharSize(wcharSize);
}
protected void updatedShortSize() {
int shortSize = Integer.decode(shortSizeComponent.getText()).intValue();
dataOrganization.setShortSize(shortSize);
}
protected void updatedIntegerSize() {
int integerSize = Integer.decode(integerSizeComponent.getText()).intValue();
dataOrganization.setIntegerSize(integerSize);
}
protected void updatedLongSize() {
int longSize = Integer.decode(longSizeComponent.getText()).intValue();
dataOrganization.setLongSize(longSize);
}
protected void updatedLongLongSize() {
int longLongSize = Integer.decode(longLongSizeComponent.getText()).intValue();
dataOrganization.setLongLongSize(longLongSize);
}
protected void updatedFloatSize() {
int floatSize = Integer.decode(floatSizeComponent.getText()).intValue();
dataOrganization.setFloatSize(floatSize);
}
protected void updatedDoubleSize() {
int doubleSize = Integer.decode(doubleSizeComponent.getText()).intValue();
dataOrganization.setDoubleSize(doubleSize);
}
protected void updatedLongDoubleSize() {
int longDoubleSize = Integer.decode(longDoubleSizeComponent.getText()).intValue();
dataOrganization.setLongDoubleSize(longDoubleSize);
}
protected void updatedAbsoluteMaxAlignment() {
String maxAlignString = absoluteMaxAlignComponent.getText().toLowerCase();
int absoluteMax =
("none".equals(maxAlignString)) ? 0 : Integer.decode(maxAlignString).intValue();
dataOrganization.setAbsoluteMaxAlignment(absoluteMax);
}
protected void updatedMachineAlignment() {
int machineAlignment = Integer.decode(machineAlignComponent.getText()).intValue();
dataOrganization.setMachineAlignment(machineAlignment);
}
protected void updatedDefaultAlignment() {
int defaultAlignment = Integer.decode(defaultAlignComponent.getText()).intValue();
dataOrganization.setDefaultAlignment(defaultAlignment);
}
protected void updatedDefaultPointerAlignment() {
int defaultPointerAlignment = Integer.decode(pointerAlignComponent.getText()).intValue();
dataOrganization.setDefaultPointerAlignment(defaultPointerAlignment);
}
}

View file

@ -1,156 +0,0 @@
/* ###
* 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.datamgr;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import ghidra.program.model.data.DataOrganizationImpl;
import ghidra.util.Msg;
import ghidra.util.exception.NoValueException;
import ghidra.util.table.GhidraTable;
public class SizeAlignmentPanel extends JPanel {
GhidraTable table;
DataOrganizationImpl dataOrganization;
public SizeAlignmentPanel() {
super(new BorderLayout());
TableModel tableModel = new SizeAlignmentTableModel();
table = new GhidraTable(tableModel);
table.setAutoEditEnabled(true);
JScrollPane sp = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(200, 80));
add(sp, BorderLayout.CENTER);
}
public void setOrganization(DataOrganizationImpl dataOrganization) {
this.dataOrganization = dataOrganization;
((SizeAlignmentTableModel) table.getModel()).fireTableDataChanged();
}
class SizeAlignmentTableModel extends AbstractTableModel {
private final String[] columnNames = new String[] { "Size", "Alignment" };
private final int SIZE_COLUMN = 0;
private final int ALIGNMENT_COLUMN = 1;
SizeAlignmentTableModel() {
super();
}
@Override
public void addTableModelListener(TableModelListener l) {
// TODO Auto-generated method stub
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
@Override
public int getRowCount() {
return dataOrganization.getSizeAlignmentCount() + 1;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
int[] sizes = dataOrganization.getSizes();
if (rowIndex < sizes.length) {
int size = sizes[rowIndex];
if (columnIndex == SIZE_COLUMN) {
return size;
}
else if (columnIndex == ALIGNMENT_COLUMN) {
try {
return dataOrganization.getSizeAlignment(size);
}
catch (NoValueException e) {
return null;
}
}
}
return null;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (rowIndex == dataOrganization.getSizeAlignmentCount()) {
return columnIndex == SIZE_COLUMN;
}
return columnIndex == ALIGNMENT_COLUMN;
}
@Override
public void removeTableModelListener(TableModelListener l) {
// TODO Auto-generated method stub
}
@Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
if (value == null) {
return;
}
int[] sizes = dataOrganization.getSizes();
if (rowIndex < sizes.length) {
int alignment = ((Integer) value).intValue();
int size = sizes[rowIndex];
dataOrganization.setSizeAlignment(size, alignment);
}
if (rowIndex == sizes.length) {
int size = ((Integer) value).intValue();
// Check that we don't already have this size.
try {
dataOrganization.getSizeAlignment(size);
setStatusMessage("An alignment is already defined for a size of " + size + ".");
return;
}
catch (NoValueException e) {
// Actually don't want to find a value so we can set one below.
}
int alignment = size; // Set the alignment to match the size initially.
dataOrganization.setSizeAlignment(size, alignment);
fireTableDataChanged();
}
}
}
public void setStatusMessage(String message) {
// TODO Change this to write to the status line in the dialog.
Msg.showError(this, this, "Invalid Input", message);
}
}

View file

@ -41,7 +41,8 @@ class DataTypePreview implements Preview {
public String getPreview(Memory memory, Address addr) { public String getPreview(Memory memory, Address addr) {
try { try {
MemBuffer mb = new DumbMemBufferImpl(memory, addr); MemBuffer mb = new DumbMemBufferImpl(memory, addr);
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dt, mb, MAX_PREVIEW_LENGTH); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(dt, mb, MAX_PREVIEW_LENGTH, false);
if (dti == null) { if (dti == null) {
return ""; return "";
} }

View file

@ -42,7 +42,7 @@ public class ConvertToDoubleAction extends AbstractConvertAction {
try { try {
FloatFormat format = FloatFormat format =
FloatFormatFactory.getFloatFormat(dataOrganization.getDoubleSize()); FloatFormatFactory.getFloatFormat(dataOrganization.getDoubleSize());
return format.round(format.getHostFloat(s.getBigInteger())); return format.round(format.decodeBigFloat(s.getBigInteger()));
} }
catch (UnsupportedFloatFormatException e) { catch (UnsupportedFloatFormatException e) {
return null; return null;

View file

@ -41,7 +41,7 @@ public class ConvertToFloatAction extends AbstractConvertAction {
DataOrganization dataOrganization = program.getDataTypeManager().getDataOrganization(); DataOrganization dataOrganization = program.getDataTypeManager().getDataOrganization();
try { try {
FloatFormat format = FloatFormatFactory.getFloatFormat(dataOrganization.getFloatSize()); FloatFormat format = FloatFormatFactory.getFloatFormat(dataOrganization.getFloatSize());
return format.round(format.getHostFloat(s.getBigInteger())); return format.round(format.decodeBigFloat(s.getBigInteger()));
} }
catch (UnsupportedFloatFormatException e) { catch (UnsupportedFloatFormatException e) {
return null; return null;

View file

@ -100,16 +100,19 @@ class CreateArrayAction extends ListingContextAction {
Variable var = varLoc.getVariable(); Variable var = varLoc.getVariable();
if (var.isStackVariable()) { if (var.isStackVariable()) {
DataType dt = var.getDataType(); DataType dt = var.getDataType();
int len = var.getLength(); if (dt.getLength() < 1) {
int defaultElements = plugin.getMaxStackVariableSize(fun, var); return;
if (defaultElements <= 0) {
defaultElements = 1;
} }
int n = getNumElements(dt, Integer.MAX_VALUE, defaultElements); int availableLen = plugin.getMaxStackVariableSize(fun, var);
if (availableLen <= 0) {
availableLen = 1;
}
int maxElements = availableLen / var.getDataType().getAlignedLength();
int n = getNumElements(dt, Integer.MAX_VALUE, maxElements);
if (n == 0) { if (n == 0) {
return; return;
} }
Array array = new ArrayDataType(dt, n, len); Array array = new ArrayDataType(dt, n, -1);
plugin.createData(array, context, true, true); plugin.createData(array, context, true, true);
} }
} }

View file

@ -22,6 +22,7 @@ import ghidra.app.util.cparser.C.ParseException;
import ghidra.app.util.parser.FunctionSignatureParser; import ghidra.app.util.parser.FunctionSignatureParser;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.listing.Function.FunctionUpdateType; import ghidra.program.model.listing.Function.FunctionUpdateType;
@ -1206,6 +1207,7 @@ public class FunctionEditorModel {
catch (InvalidInputException e) { catch (InvalidInputException e) {
// ignore // ignore
} }
setFunctionData(f); setFunctionData(f);
isInParsingMode = false; isInParsingMode = false;
} }

View file

@ -33,6 +33,7 @@ import ghidra.app.util.datatype.DataTypeSelectionEditor;
import ghidra.app.util.datatype.NavigationDirection; import ghidra.app.util.datatype.NavigationDirection;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;

View file

@ -202,7 +202,7 @@ public class StackEditorModel extends CompositeEditorModel {
dt = element.getDataType(); dt = element.getDataType();
dtLen = dt.getLength(); dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, return DataTypeInstance.getDataTypeInstance(dt,
(dtLen > 0) ? dtLen : element.getLength()); (dtLen > 0) ? dtLen : element.getLength(), true);
case NAME: case NAME:
String fieldName = getFieldNameAtRow(rowIndex, (StackFrameDataType) viewComposite); String fieldName = getFieldNameAtRow(rowIndex, (StackFrameDataType) viewComposite);
if (fieldName == null) { if (fieldName == null) {
@ -1127,7 +1127,7 @@ public class StackEditorModel extends CompositeEditorModel {
OffsetPairs offsetSelection = getRelOffsetSelection(); OffsetPairs offsetSelection = getRelOffsetSelection();
int transID = startTransaction("Apply Data Type \"" + dt.getName() + "\""); int transID = startTransaction("Apply Data Type \"" + dt.getName() + "\"");
try { try {
fieldEdited(DataTypeInstance.getDataTypeInstance(dt, dtLength), index, fieldEdited(DataTypeInstance.getDataTypeInstance(dt, dtLength, true), index,
getDataTypeColumn()); getDataTypeColumn());
setRelOffsetSelection(offsetSelection); setRelOffsetSelection(offsetSelection);
} }
@ -1157,7 +1157,7 @@ public class StackEditorModel extends CompositeEditorModel {
if (max == Integer.MAX_VALUE) { if (max == Integer.MAX_VALUE) {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }
return max / dtc.getLength(); return max / dtc.getDataType().getAlignedLength();
} }
@Override @Override
@ -1320,7 +1320,7 @@ public class StackEditorModel extends CompositeEditorModel {
dtName = dt.getDisplayName(); dtName = dt.getDisplayName();
if (dtString.equals(dtName)) { if (dtString.equals(dtName)) {
return DataTypeInstance.getDataTypeInstance(element.getDataType(), return DataTypeInstance.getDataTypeInstance(element.getDataType(),
element.getLength()); element.getLength(), true);
} }
} }
@ -1346,7 +1346,7 @@ public class StackEditorModel extends CompositeEditorModel {
if (maxLength > 0 && newLength > maxLength) { if (maxLength > 0 && newLength > maxLength) {
throw new UsrException(newDt.getDisplayName() + " doesn't fit."); throw new UsrException(newDt.getDisplayName() + " doesn't fit.");
} }
return DataTypeInstance.getDataTypeInstance(newDt, newLength); return DataTypeInstance.getDataTypeInstance(newDt, newLength, true);
} }
@Override @Override

View file

@ -25,6 +25,7 @@ import ghidra.app.util.bin.format.dwarf4.encoding.*;
import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException; import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException;
import ghidra.app.util.bin.format.dwarf4.next.DWARFDataTypeImporter.DWARFDataType; import ghidra.app.util.bin.format.dwarf4.next.DWARFDataTypeImporter.DWARFDataType;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -381,7 +382,7 @@ public class DWARFDataTypeManager {
String mangledName = null; String mangledName = null;
if (name != null) { if (name != null) {
dt = baseDataTypes.get(name); dt = baseDataTypes.get(name);
if (dt != null && dt.getLength() == dwarfSize && if (dt != null && dt.getAlignedLength() == dwarfSize &&
isEncodingCompatible(dwarfEncoding, dt)) { isEncodingCompatible(dwarfEncoding, dt)) {
return dt; return dt;
} }
@ -394,6 +395,9 @@ public class DWARFDataTypeManager {
dt = switch (dwarfEncoding) { dt = switch (dwarfEncoding) {
case DWARFEncoding.DW_ATE_address -> baseDataTypeVoid; // TODO: Check if bytesize != 0 - may want to make a void pointer case DWARFEncoding.DW_ATE_address -> baseDataTypeVoid; // TODO: Check if bytesize != 0 - may want to make a void pointer
case DWARFEncoding.DW_ATE_boolean -> dwarfSize == 1 ? baseDataTypeBool : null; case DWARFEncoding.DW_ATE_boolean -> dwarfSize == 1 ? baseDataTypeBool : null;
// TODO: Float lookup by length must use "raw" encoding size since "aligned" lengths
// may be duplicated across different float types. Lookup by name is preferred.
// May need to add name lookup capability to AbstractFloatDataType
case DWARFEncoding.DW_ATE_float -> AbstractFloatDataType.getFloatDataType(dwarfSize, case DWARFEncoding.DW_ATE_float -> AbstractFloatDataType.getFloatDataType(dwarfSize,
getCorrectDTMForFixedLengthTypes(name, dwarfSize)); getCorrectDTMForFixedLengthTypes(name, dwarfSize));
case DWARFEncoding.DW_ATE_signed -> AbstractIntegerDataType.getSignedDataType(dwarfSize, case DWARFEncoding.DW_ATE_signed -> AbstractIntegerDataType.getSignedDataType(dwarfSize,
@ -426,6 +430,7 @@ public class DWARFDataTypeManager {
return dt; return dt;
} }
private DataTypeManager getCorrectDTMForFixedLengthTypes(String name, int dwarfSize) { private DataTypeManager getCorrectDTMForFixedLengthTypes(String name, int dwarfSize) {
// If the requested name of the base type appears to have a bitsize string // If the requested name of the base type appears to have a bitsize string
// embedded in it, this chunk of code will switch between using the normal DTM // embedded in it, this chunk of code will switch between using the normal DTM

View file

@ -25,6 +25,8 @@ import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata;
import ghidra.app.util.bin.format.pe.cli.tables.*; import ghidra.app.util.bin.format.pe.cli.tables.*;
import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexTypeDefOrRef; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexTypeDefOrRef;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.Float32DataType;
import ghidra.program.model.data.floats.Float64DataType;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
public abstract class CliAbstractSig extends CliBlob implements CliRepresentable { public abstract class CliAbstractSig extends CliBlob implements CliRepresentable {
@ -139,9 +141,9 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable
return UnsignedIntegerDataType.dataType; return UnsignedIntegerDataType.dataType;
case ELEMENT_TYPE_R4: case ELEMENT_TYPE_R4:
return Float4DataType.dataType; return Float32DataType.dataType;
case ELEMENT_TYPE_R8: case ELEMENT_TYPE_R8:
return Float8DataType.dataType; return Float64DataType.dataType;
case ELEMENT_TYPE_I8: case ELEMENT_TYPE_I8:
return LongLongDataType.dataType; return LongLongDataType.dataType;

View file

@ -32,6 +32,8 @@ import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodDef.CliMethodDefRo
import ghidra.app.util.bin.format.pe.cli.tables.CliTypeTable; import ghidra.app.util.bin.format.pe.cli.tables.CliTypeTable;
import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexCustomAttributeType; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexCustomAttributeType;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.Float32DataType;
import ghidra.program.model.data.floats.Float64DataType;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
@ -410,12 +412,12 @@ public class CliBlobCustomAttrib extends CliBlob {
case ELEMENT_TYPE_R4: case ELEMENT_TYPE_R4:
addFixedArg(processFixedArgs, baseTypeCode, addFixedArg(processFixedArgs, baseTypeCode,
reader.readNextByteArray(Float4DataType.dataType.getLength())); reader.readNextByteArray(Float32DataType.dataType.getLength()));
break; break;
case ELEMENT_TYPE_R8: case ELEMENT_TYPE_R8:
addFixedArg(processFixedArgs, baseTypeCode, addFixedArg(processFixedArgs, baseTypeCode,
reader.readNextByteArray(Float8DataType.dataType.getLength())); reader.readNextByteArray(Float64DataType.dataType.getLength()));
break; break;
case ELEMENT_TYPE_STRING: case ELEMENT_TYPE_STRING:

View file

@ -15,8 +15,7 @@
*/ */
package ghidra.app.util.datatype.microsoft; package ghidra.app.util.datatype.microsoft;
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAbsoluteAddress; import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.is64Bit;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsImpl; import ghidra.docking.settings.SettingsImpl;
@ -111,7 +110,7 @@ public class RTTI0DataType extends RTTIDataType {
Address nameAddress = start.add(nameOffset); Address nameAddress = start.add(nameOffset);
MemoryBufferImpl nameBuf = new MemoryBufferImpl(buf.getMemory(), nameAddress, 1024); MemoryBufferImpl nameBuf = new MemoryBufferImpl(buf.getMemory(), nameAddress, 1024);
DataTypeInstance dti = DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(new TerminatedStringDataType(), nameBuf); DataTypeInstance.getDataTypeInstance(new TerminatedStringDataType(), nameBuf, false);
if (dti != null) { if (dti != null) {
comps[2] = new ReadOnlyDataTypeComponent(dti.getDataType(), this, dti.getLength(), 2, comps[2] = new ReadOnlyDataTypeComponent(dti.getDataType(), this, dti.getLength(), 2,
@ -178,7 +177,8 @@ public class RTTI0DataType extends RTTIDataType {
WrappedMemBuffer nameBuf = null; WrappedMemBuffer nameBuf = null;
try { try {
nameBuf = new WrappedMemBuffer(buf, getNameOffset(buf.getMemory().getProgram())); nameBuf = new WrappedMemBuffer(buf, getNameOffset(buf.getMemory().getProgram()));
dti = DataTypeInstance.getDataTypeInstance(new TerminatedStringDataType(), nameBuf); dti = DataTypeInstance.getDataTypeInstance(new TerminatedStringDataType(), nameBuf,
false);
} }
catch (AddressOutOfBoundsException e) { catch (AddressOutOfBoundsException e) {
// ignore // ignore

View file

@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum; import ghidra.program.model.data.Enum;
import ghidra.program.model.data.floats.Float128DataType;
import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.Namespace;
/** /**
@ -283,7 +284,7 @@ public class DemangledDataType extends DemangledType {
dt = FloatDataType.dataType; dt = FloatDataType.dataType;
} }
else if (FLOAT128.equals(name)) { else if (FLOAT128.equals(name)) {
dt = new TypedefDataType(FLOAT128, Float16DataType.dataType); dt = new TypedefDataType(FLOAT128, Float128DataType.dataType);
} }
else if (DOUBLE.equals(name)) { else if (DOUBLE.equals(name)) {
dt = DoubleDataType.dataType; dt = DoubleDataType.dataType;

View file

@ -149,7 +149,7 @@ class DefinedDataXmlMgr {
private void clearExistingData(Address addr, int size, DataType dt, Listing listing) { private void clearExistingData(Address addr, int size, DataType dt, Listing listing) {
DumbMemBufferImpl buf = new DumbMemBufferImpl(program.getMemory(), addr); DumbMemBufferImpl buf = new DumbMemBufferImpl(program.getMemory(), addr);
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dt, buf, size); DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dt, buf, size, false);
if (dti != null) { if (dti != null) {
boolean doClear = false; boolean doClear = false;
Address maxAddr = addr.add(dti.getLength() - 1); Address maxAddr = addr.add(dti.getLength() - 1);

View file

@ -784,7 +784,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
false) false)
: LittleEndianDataConverter.INSTANCE.getBigInteger(bytes, index, elementSize, : LittleEndianDataConverter.INSTANCE.getBigInteger(bytes, index, elementSize,
false); false);
BigDecimal val = ff.round(ff.getHostFloat(encoding)); BigDecimal val = ff.round(ff.decodeBigFloat(encoding));
return val.toString(); return val.toString();
} }
} }
@ -879,7 +879,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
if (reg != null && floatRegSet.contains(reg)) { if (reg != null && floatRegSet.contains(reg)) {
FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(size); FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(size);
BigDecimal hostFloat = BigDecimal hostFloat =
floatFormat.round(floatFormat.getHostFloat(new BigInteger(1, values))); floatFormat.round(floatFormat.decodeBigFloat(new BigInteger(1, values)));
floatStr = " (" + hostFloat.toString() + ")"; floatStr = " (" + hostFloat.toString() + ")";
} }

View file

@ -22,7 +22,6 @@ import static org.junit.Assert.*;
import org.junit.*; import org.junit.*;
import ghidra.app.events.ProgramActivatedPluginEvent;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
import ghidra.app.plugin.core.datapreview.DataTypePreviewPlugin.DTPPTableModel; import ghidra.app.plugin.core.datapreview.DataTypePreviewPlugin.DTPPTableModel;
@ -174,6 +173,7 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe
// integerSize = 4; // integerSize = 4;
// longSize = 4; // longSize = 4;
// defaultAlignment = 1; // defaultAlignment = 1;
// alignment per size: 2->2, 4->4, 8->4
plugin.addDataType(IntegerDataType.dataType); plugin.addDataType(IntegerDataType.dataType);
plugin.addDataType(LongDataType.dataType); plugin.addDataType(LongDataType.dataType);
@ -190,12 +190,11 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe
assertEquals(6, model.getRowCount()); assertEquals(6, model.getRowCount());
Program program = buildProgram(); Program program = buildProgram();
DataOrganizationImpl dataOrganization = DataOrganizationImpl dataOrganization =
(DataOrganizationImpl) program.getDataTypeManager().getDataOrganization(); (DataOrganizationImpl) program.getCompilerSpec().getDataOrganization();
dataOrganization.setLongSize(8); dataOrganization.setLongSize(8);
// Open program in tool and goto tested memory location
env.open(program); env.open(program);
gotoService.goTo(addr(program, 0x100df26)); gotoService.goTo(addr(program, 0x100df26));
@ -210,19 +209,23 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe
assertEquals("61004D00200065h", model.getValueAt(4, DTPPTableModel.PREVIEW_COL));// 8-byte long at offset 4 assertEquals("61004D00200065h", model.getValueAt(4, DTPPTableModel.PREVIEW_COL));// 8-byte long at offset 4
assertEquals("72h", model.getValueAt(5, DTPPTableModel.PREVIEW_COL));// 2-byte short at offset 12 assertEquals("72h", model.getValueAt(5, DTPPTableModel.PREVIEW_COL));// 2-byte short at offset 12
// deactivate program env.close(program);
plugin.getTool().firePluginEvent(new ProgramActivatedPluginEvent("Test", null));
waitForPostedSwingRunnables();
// Re-create program with mutated data-organization to simulate shift to 3-byte aligned types
// NOTE: Altering data organization on-the-fly is not supported // NOTE: Altering data organization on-the-fly is not supported
dataOrganization.setDefaultAlignment(2);
// alignment map should jive with 3-byte mutliple primitive type sizes
dataOrganization.clearSizeAlignmentMap();
dataOrganization.setSizeAlignment(1, 1);
dataOrganization.setSizeAlignment(3, 3);
dataOrganization.setSizeAlignment(6, 6);
dataOrganization.setShortSize(3); dataOrganization.setShortSize(3);
dataOrganization.setIntegerSize(3); dataOrganization.setIntegerSize(3);
dataOrganization.setLongSize(6); dataOrganization.setLongSize(6);
// activate program // Open program in tool and goto tested memory location
plugin.getTool().firePluginEvent(new ProgramActivatedPluginEvent("Test", program)); program = buildProgram();
waitForPostedSwingRunnables(); env.open(program);
gotoService.goTo(addr(program, 0x100df26)); gotoService.goTo(addr(program, 0x100df26));
@ -231,8 +234,8 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe
assertEquals("680054h", model.getValueAt(2, DTPPTableModel.PREVIEW_COL));// 3-byte short assertEquals("680054h", model.getValueAt(2, DTPPTableModel.PREVIEW_COL));// 3-byte short
assertEquals("680054h", model.getValueAt(3, DTPPTableModel.PREVIEW_COL));// 3-byte int at offset 0 assertEquals("680054h", model.getValueAt(3, DTPPTableModel.PREVIEW_COL));// 3-byte int at offset 0
assertEquals("4D00200065h", model.getValueAt(4, DTPPTableModel.PREVIEW_COL));// 6-byte long at offset 4 assertEquals("61004D0020h", model.getValueAt(4, DTPPTableModel.PREVIEW_COL));// 6-byte long at offset 6
assertEquals("720061h", model.getValueAt(5, DTPPTableModel.PREVIEW_COL));// 3-byte short at offset 10 assertEquals("670072h", model.getValueAt(5, DTPPTableModel.PREVIEW_COL));// 3-byte short at offset 12
} }

View file

@ -863,7 +863,7 @@ public class EquatePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
} }
else if (name.indexOf("Float") >= 0) { else if (name.indexOf("Float") >= 0) {
assertTrue(popupPath[1].startsWith("Float")); assertTrue(popupPath[1].startsWith("Float"));
assertTrue(popupPath[1].endsWith(" 5.605194E-45")); assertTrue(popupPath[1].endsWith(" 5.6051939E-45"));
} }
else { else {
fail("Unhandled Convert item: " + name); fail("Unhandled Convert item: " + name);

View file

@ -23,6 +23,7 @@ import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin; import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
import ghidra.app.plugin.core.script.GhidraScriptMgrPlugin; import ghidra.app.plugin.core.script.GhidraScriptMgrPlugin;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.pcode.floatformat.BigFloat;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet; import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -400,13 +401,13 @@ public class GhidraScriptRealProgramTest extends AbstractGhidraHeadedIntegration
address = script.toAddr(0x010085a7); address = script.toAddr(0x010085a7);
data = script.createFloat(address); data = script.createFloat(address);
assertNotNull(data); assertNotNull(data);
assertEquals(-1.4682312f, data.getValue()); assertEquals("-1.468231", ((BigFloat) data.getValue()).toString());
script.clearListing(address); script.clearListing(address);
address = script.toAddr(0x010085a9); address = script.toAddr(0x010085a9);
data = script.createDouble(address); data = script.createDouble(address);
assertNotNull(data); assertNotNull(data);
assertEquals(-8.373196719664668E298, data.getValue()); assertEquals("-8.37319671966467E+298", ((BigFloat) data.getValue()).toString());
script.clearListing(address); script.clearListing(address);
} }

View file

@ -64,7 +64,7 @@ public class ConvertDoubleAction extends ConvertConstantAction {
private static BigDecimal value(int size, Scalar s) { private static BigDecimal value(int size, Scalar s) {
try { try {
FloatFormat format = FloatFormatFactory.getFloatFormat(size); FloatFormat format = FloatFormatFactory.getFloatFormat(size);
return format.round(format.getHostFloat(s.getBigInteger())); return format.round(format.decodeBigFloat(s.getBigInteger()));
} }
catch (UnsupportedFloatFormatException e) { catch (UnsupportedFloatFormatException e) {
return null; return null;

View file

@ -64,7 +64,7 @@ public class ConvertFloatAction extends ConvertConstantAction {
private static BigDecimal value(int size, Scalar s) { private static BigDecimal value(int size, Scalar s) {
try { try {
FloatFormat format = FloatFormatFactory.getFloatFormat(size); FloatFormat format = FloatFormatFactory.getFloatFormat(size);
return format.round(format.getHostFloat(s.getBigInteger())); return format.round(format.decodeBigFloat(s.getBigInteger()));
} }
catch (UnsupportedFloatFormatException e) { catch (UnsupportedFloatFormatException e) {
return null; return null;

View file

@ -794,7 +794,7 @@ public class PdbParser {
void createData(Address address, DataType dataType, MessageLog log) { void createData(Address address, DataType dataType, MessageLog log) {
DumbMemBufferImpl memBuffer = new DumbMemBufferImpl(program.getMemory(), address); DumbMemBufferImpl memBuffer = new DumbMemBufferImpl(program.getMemory(), address);
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dataType, memBuffer); DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dataType, memBuffer, false);
if (dti == null) { if (dti == null) {
log.appendMsg("PDB", log.appendMsg("PDB",
"Failed to apply datatype " + dataType.getName() + " at " + address); "Failed to apply datatype " + dataType.getName() + " at " + address);

View file

@ -115,7 +115,7 @@ public class DataSymbolApplier extends MsSymbolApplier {
//TODO: might want to do an ApplyDatatypeCmd here!!! //TODO: might want to do an ApplyDatatypeCmd here!!!
DumbMemBufferImpl memBuffer = DumbMemBufferImpl memBuffer =
new DumbMemBufferImpl(applicator.getProgram().getMemory(), address); new DumbMemBufferImpl(applicator.getProgram().getMemory(), address);
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dataType, memBuffer); DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(dataType, memBuffer, false);
if (dti == null) { if (dti == null) {
applicator.appendLogMsg( applicator.appendLogMsg(
"Error: Failed to apply datatype " + dataType.getName() + " at " + address); "Error: Failed to apply datatype " + dataType.getName() + " at " + address);

View file

@ -20,6 +20,7 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.PrimitiveMsType; import ghidra.app.util.bin.format.pdb2.pdbreader.type.PrimitiveMsType;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
/** /**
@ -516,21 +517,24 @@ public class PdbPrimitiveTypeApplicator {
return getRealType(16, "float128"); return getRealType(16, "float128");
} }
/* /**
* First get type from "other" list, which are typedefs to underlying primitives. If it does * First get type from "other" list, which are typedefs to underlying primitives. If it does
* not exist, then find the proper underlying primitive, create the typedef, and cache this * not exist, then find the proper underlying primitive, create the typedef, and cache this
* newly minted (typedef) unique primitive type. * newly minted (typedef) unique primitive type.
* @param rawSize "raw" encoding size in bytes
* @param name assigned type name
*/ */
private DataType getRealType(int size, String name) { private DataType getRealType(int rawSize, String name) {
DataType dataType = otherPrimitives.get(name); DataType dataType = otherPrimitives.get(name);
if (dataType != null) { if (dataType != null) {
return dataType; return dataType;
} }
dataType = floatGhidraPrimitives.get(size); dataType = floatGhidraPrimitives.get(rawSize);
DataType resolved; DataType resolved;
if (dataType == null) { if (dataType == null) {
resolved = resolve(AbstractFloatDataType.getFloatDataType(size, getDataTypeManager())); resolved =
floatGhidraPrimitives.put(size, resolved); resolve(AbstractFloatDataType.getFloatDataType(rawSize, getDataTypeManager()));
floatGhidraPrimitives.put(rawSize, resolved);
if (resolved instanceof Undefined) { // Not a real type implemented in Ghidra. if (resolved instanceof Undefined) { // Not a real type implemented in Ghidra.
DataType type = createTypedef(name, resolved); DataType type = createTypedef(name, resolved);
resolved = resolve(type); resolved = resolve(type);

View file

@ -38,23 +38,23 @@ public class OpBehaviorFloatAbsTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, ff.opAbs(a)); long result = op.evaluateUnary(8, 8, ff.opAbs(a));
Assert.assertEquals(2.5, ff.getHostFloat(result), 0); Assert.assertEquals(2.5, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.5); a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.5, ff.getHostFloat(result), 0); Assert.assertEquals(2.5, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -66,23 +66,23 @@ public class OpBehaviorFloatAbsTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a); BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.5d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d)); a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.5d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -39,32 +39,32 @@ public class OpBehaviorFloatAddTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(1.234); long a = ff.getEncoding(1.234);
long b = ff.getEncoding(1.123); long b = ff.getEncoding(1.123);
long result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123 long result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
Assert.assertEquals(2.357, ff.getHostFloat(result), 0); Assert.assertEquals(2.357, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-1.123); a = ff.getEncoding(-1.123);
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123 result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
Assert.assertEquals(0d, ff.getHostFloat(result), 0); Assert.assertEquals(0d, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123 result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123 result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.NEGATIVE_INFINITY); b = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.POSITIVE_INFINITY); b = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
b = ff.getEncoding(1.123); b = ff.getEncoding(1.123);
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123 result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -77,32 +77,32 @@ public class OpBehaviorFloatAddTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(1.234d)); BigInteger a = ff.getEncoding(ff.getBigFloat(1.234d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.123d)); BigInteger b = ff.getEncoding(ff.getBigFloat(1.123d));
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123 BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
Assert.assertEquals(ff.getBigFloat(2.357), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.357), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-1.123d)); a = ff.getEncoding(ff.getBigFloat(-1.123d));
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123 result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigZero(false), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigInfinity(false)); a = ff.getEncoding(ff.getBigInfinity(false));
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123 result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123 result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
b = ff.getBigInfinityEncoding(true); b = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
b = ff.getEncoding(ff.getBigInfinity(false)); b = ff.getEncoding(ff.getBigInfinity(false));
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
b = ff.getEncoding(ff.getBigFloat(1.123d)); b = ff.getEncoding(ff.getBigFloat(1.123d));
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123 result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -38,23 +38,23 @@ public class OpBehaviorFloatCeilTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long result = ff.opCeil(a); long result = ff.opCeil(a);
Assert.assertEquals(3.0, ff.getHostFloat(result), 0); Assert.assertEquals(3.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.5); a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0); Assert.assertEquals(-2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -66,23 +66,23 @@ public class OpBehaviorFloatCeilTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a); BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(3.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d)); a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.0d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -39,19 +39,19 @@ public class OpBehaviorFloatDivTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(3.75); long a = ff.getEncoding(3.75);
long b = ff.getEncoding(1.5); long b = ff.getEncoding(1.5);
long result = ff.opDiv(a, b); long result = ff.opDiv(a, b);
Assert.assertEquals(2.5, ff.getHostFloat(result), 0); Assert.assertEquals(2.5, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(0); b = ff.getEncoding(0);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-3.75); a = ff.getEncoding(-3.75);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.NaN); b = ff.getEncoding(Double.NaN);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -64,19 +64,19 @@ public class OpBehaviorFloatDivTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(3.75d)); BigInteger a = ff.getEncoding(ff.getBigFloat(3.75d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d)); BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d));
BigInteger result = op.evaluateBinary(8, 8, a, b); BigInteger result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.5d), ff.decodeBigFloat(result));
b = ff.getBigZeroEncoding(false); b = ff.getBigZeroEncoding(false);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-3.75d)); a = ff.getEncoding(ff.getBigFloat(-3.75d));
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
b = ff.getBigNaNEncoding(false); b = ff.getBigNaNEncoding(false);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -39,23 +39,23 @@ public class OpBehaviorFloatFloat2FloatTest extends AbstractOpBehaviorTest {
long a = ff4.getEncoding(1.75); long a = ff4.getEncoding(1.75);
long result = op.evaluateUnary(8, 4, a); long result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(1.75, ff8.getHostFloat(result), 0); Assert.assertEquals(1.75, ff8.decodeHostFloat(result), 0);
a = ff4.getEncoding(-1.75); a = ff4.getEncoding(-1.75);
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(-1.75, ff8.getHostFloat(result), 0); Assert.assertEquals(-1.75, ff8.decodeHostFloat(result), 0);
a = ff4.getEncoding(Float.POSITIVE_INFINITY); a = ff4.getEncoding(Float.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff8.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff8.decodeHostFloat(result), 0);
a = ff4.getEncoding(Float.NEGATIVE_INFINITY); a = ff4.getEncoding(Float.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff8.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff8.decodeHostFloat(result), 0);
a = ff4.getEncoding(Float.NaN); a = ff4.getEncoding(Float.NaN);
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.NaN, ff8.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff8.decodeHostFloat(result), 0);
} }
@Test @Test
@ -68,23 +68,23 @@ public class OpBehaviorFloatFloat2FloatTest extends AbstractOpBehaviorTest {
BigInteger a = ff4.getEncoding(ff4.getBigFloat(1.75d)); BigInteger a = ff4.getEncoding(ff4.getBigFloat(1.75d));
BigInteger result = op.evaluateUnary(8, 4, a); BigInteger result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigFloat(1.75d), ff8.getHostFloat(result)); Assert.assertEquals(ff8.getBigFloat(1.75d), ff8.decodeBigFloat(result));
a = ff4.getEncoding(ff4.getBigFloat(-1.75d)); a = ff4.getEncoding(ff4.getBigFloat(-1.75d));
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigFloat(-1.75d), ff8.getHostFloat(result)); Assert.assertEquals(ff8.getBigFloat(-1.75d), ff8.decodeBigFloat(result));
a = ff4.getEncoding(ff4.getBigInfinity(false)); a = ff4.getEncoding(ff4.getBigInfinity(false));
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigInfinity(false), ff8.getHostFloat(result)); Assert.assertEquals(ff8.getBigInfinity(false), ff8.decodeBigFloat(result));
a = ff4.getEncoding(ff4.getBigInfinity(true)); a = ff4.getEncoding(ff4.getBigInfinity(true));
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigInfinity(true), ff8.getHostFloat(result)); Assert.assertEquals(ff8.getBigInfinity(true), ff8.decodeBigFloat(result));
a = ff4.getEncoding(ff4.getBigNaN(false)); a = ff4.getEncoding(ff4.getBigNaN(false));
result = op.evaluateUnary(8, 4, a); result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigNaN(false), ff8.getHostFloat(result)); Assert.assertEquals(ff8.getBigNaN(false), ff8.decodeBigFloat(result));
} }
} }

View file

@ -38,27 +38,27 @@ public class OpBehaviorFloatFloorTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, a); long result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.0, ff.getHostFloat(result), 0); Assert.assertEquals(2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.0); a = ff.getEncoding(-2.0);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0); Assert.assertEquals(-2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.5); a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-3.0, ff.getHostFloat(result), 0); Assert.assertEquals(-3.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -70,27 +70,27 @@ public class OpBehaviorFloatFloorTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a); BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.0d)); a = ff.getEncoding(ff.getBigFloat(-2.0d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d)); a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-3.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-3.0d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -41,19 +41,19 @@ public class OpBehaviorFloatInt2FloatTest extends AbstractOpBehaviorTest {
long result = op.evaluateUnary(4, 4, 2); long result = op.evaluateUnary(4, 4, 2);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(2.0d, ff.getHostFloat(result), 0); Assert.assertEquals(2.0d, ff.decodeHostFloat(result), 0);
result = op.evaluateUnary(4, 4, -2); result = op.evaluateUnary(4, 4, -2);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(-2.0d, ff.getHostFloat(result), 0); Assert.assertEquals(-2.0d, ff.decodeHostFloat(result), 0);
result = op.evaluateUnary(4, 4, 0); result = op.evaluateUnary(4, 4, 0);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(0d, ff.getHostFloat(result), 0); Assert.assertEquals(0d, ff.decodeHostFloat(result), 0);
result = op.evaluateUnary(4, 4, 0x0ffffffffL); result = op.evaluateUnary(4, 4, 0x0ffffffffL);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(-1.0d, ff.getHostFloat(result), 0); Assert.assertEquals(-1.0d, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -67,20 +67,20 @@ public class OpBehaviorFloatInt2FloatTest extends AbstractOpBehaviorTest {
BigInteger result = op.evaluateUnary(4, 4, BigInteger.valueOf(2)); BigInteger result = op.evaluateUnary(4, 4, BigInteger.valueOf(2));
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.0d), ff.decodeBigFloat(result));
result = op.evaluateUnary(4, 4, BigInteger.valueOf(-2)); result = op.evaluateUnary(4, 4, BigInteger.valueOf(-2));
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.0d), ff.decodeBigFloat(result));
result = op.evaluateUnary(4, 4, BigInteger.ZERO); result = op.evaluateUnary(4, 4, BigInteger.ZERO);
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigZero(false), ff.decodeBigFloat(result));
BigInteger NEG_ONE = Utils.bytesToBigInteger( BigInteger NEG_ONE = Utils.bytesToBigInteger(
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 4, false, false); new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 4, false, false);
result = op.evaluateUnary(4, 4, NEG_ONE); result = op.evaluateUnary(4, 4, NEG_ONE);
Assert.assertEquals(ff.getBigFloat(-1.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-1.0d), ff.decodeBigFloat(result));
} }

View file

@ -39,19 +39,19 @@ public class OpBehaviorFloatMultTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long b = ff.getEncoding(1.5); long b = ff.getEncoding(1.5);
long result = op.evaluateBinary(8, 8, a, b); long result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(3.75, ff.getHostFloat(result), 0); Assert.assertEquals(3.75, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.POSITIVE_INFINITY); b = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.NaN); b = ff.getEncoding(Double.NaN);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -64,19 +64,19 @@ public class OpBehaviorFloatMultTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d)); BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d));
BigInteger result = op.evaluateBinary(8, 8, a, b); BigInteger result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigFloat(3.75d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(3.75d), ff.decodeBigFloat(result));
b = ff.getBigInfinityEncoding(false); b = ff.getBigInfinityEncoding(false);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
b = ff.getBigNaNEncoding(false); b = ff.getBigNaNEncoding(false);
result = op.evaluateBinary(8, 8, a, b); result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -38,23 +38,23 @@ public class OpBehaviorFloatNegTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, a); long result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.5, ff.getHostFloat(result), 0); Assert.assertEquals(-2.5, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.5); a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.5, ff.getHostFloat(result), 0); Assert.assertEquals(2.5, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -66,23 +66,23 @@ public class OpBehaviorFloatNegTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a); BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.5d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d)); a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.5d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }
} }

View file

@ -38,39 +38,39 @@ public class OpBehaviorFloatRoundTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(2.5); long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, a); long result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(3.0, ff.getHostFloat(result), 0); Assert.assertEquals(3.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(2.25); a = ff.getEncoding(2.25);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.0, ff.getHostFloat(result), 0); Assert.assertEquals(2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(2.75); a = ff.getEncoding(2.75);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(3.0, ff.getHostFloat(result), 0); Assert.assertEquals(3.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.5); a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0); Assert.assertEquals(-2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.25); a = ff.getEncoding(-2.25);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0); Assert.assertEquals(-2.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-2.75); a = ff.getEncoding(-2.75);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-3.0, ff.getHostFloat(result), 0); Assert.assertEquals(-3.0, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -82,39 +82,39 @@ public class OpBehaviorFloatRoundTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a); BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(3.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(2.25d)); a = ff.getEncoding(ff.getBigFloat(2.25d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(2.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(2.75d)); a = ff.getEncoding(ff.getBigFloat(2.75d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(3.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d)); a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.25d)); a = ff.getEncoding(ff.getBigFloat(-2.25d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.0d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.75d)); a = ff.getEncoding(ff.getBigFloat(-2.75d));
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-3.0d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-3.0d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a); result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }

View file

@ -37,7 +37,7 @@ public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
long longbits = ff.getEncoding(2.0); long longbits = ff.getEncoding(2.0);
longbits = op.evaluateUnary(8, 8, longbits); longbits = op.evaluateUnary(8, 8, longbits);
double d = ff.getHostFloat(longbits); double d = ff.decodeHostFloat(longbits);
Assert.assertEquals("1.414213562373095", Double.toString(d).substring(0, 17)); Assert.assertEquals("1.414213562373095", Double.toString(d).substring(0, 17));
} }
@ -52,7 +52,7 @@ public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
BigFloat big = ff.getBigFloat(2.0); BigFloat big = ff.getBigFloat(2.0);
BigInteger encoding = ff.getEncoding(big); BigInteger encoding = ff.getEncoding(big);
encoding = op.evaluateUnary(8, 8, encoding); encoding = op.evaluateUnary(8, 8, encoding);
BigFloat result = ff.getHostFloat(encoding); BigFloat result = ff.decodeBigFloat(encoding);
Assert.assertEquals("1.414213562373095", ff.round(result).toString()); Assert.assertEquals("1.414213562373095", ff.round(result).toString());
} }

View file

@ -39,32 +39,32 @@ public class OpBehaviorFloatSubTest extends AbstractOpBehaviorTest {
long a = ff.getEncoding(1.5); long a = ff.getEncoding(1.5);
long b = ff.getEncoding(1.25); long b = ff.getEncoding(1.25);
long result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25 long result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25
Assert.assertEquals(0.25, ff.getHostFloat(result), 0); Assert.assertEquals(0.25, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(-1.25); a = ff.getEncoding(-1.25);
result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25 result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25
Assert.assertEquals(-2.5, ff.getHostFloat(result), 0); Assert.assertEquals(-2.5, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY); a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25 result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.POSITIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY); a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25 result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.NEGATIVE_INFINITY); b = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
b = ff.getEncoding(Double.POSITIVE_INFINITY); b = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.decodeHostFloat(result), 0);
a = ff.getEncoding(Double.NaN); a = ff.getEncoding(Double.NaN);
b = ff.getEncoding(1.25); b = ff.getEncoding(1.25);
result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25 result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0); Assert.assertEquals(Double.NaN, ff.decodeHostFloat(result), 0);
} }
@Test @Test
@ -77,32 +77,32 @@ public class OpBehaviorFloatSubTest extends AbstractOpBehaviorTest {
BigInteger a = ff.getEncoding(ff.getBigFloat(1.5d)); BigInteger a = ff.getEncoding(ff.getBigFloat(1.5d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.25d)); BigInteger b = ff.getEncoding(ff.getBigFloat(1.25d));
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25 BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25
Assert.assertEquals(ff.getBigFloat(0.25d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(0.25d), ff.decodeBigFloat(result));
a = ff.getEncoding(ff.getBigFloat(-1.25d)); a = ff.getEncoding(ff.getBigFloat(-1.25d));
result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25 result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25
Assert.assertEquals(ff.getBigFloat(-2.5d), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigFloat(-2.5d), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(false); a = ff.getBigInfinityEncoding(false);
result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25 result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(false), ff.decodeBigFloat(result));
a = ff.getBigInfinityEncoding(true); a = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25 result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
b = ff.getBigInfinityEncoding(true); b = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
b = ff.getBigInfinityEncoding(false); b = ff.getBigInfinityEncoding(false);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigInfinity(true), ff.decodeBigFloat(result));
a = ff.getBigNaNEncoding(false); a = ff.getBigNaNEncoding(false);
b = ff.getEncoding(ff.getBigFloat(1.25d)); b = ff.getEncoding(ff.getBigFloat(1.25d));
result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25 result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result)); Assert.assertEquals(ff.getBigNaN(false), ff.decodeBigFloat(result));
} }

View file

@ -57,7 +57,8 @@ public class ProgramProviderContext implements DataTypeProviderContext {
} }
DataType dt = data.getDataType(); DataType dt = data.getDataType();
int length = data.getLength(); int length = DataTypeComponentImpl.getPreferredComponentLength(dt,
Math.max(data.getLength(), dt.getAlignedLength()));
String label = null; String label = null;
Symbol symbol = data.getPrimarySymbol(); Symbol symbol = data.getPrimarySymbol();
if (symbol != null && !symbol.isDynamic()) { if (symbol != null && !symbol.isDynamic()) {

View file

@ -15,8 +15,9 @@
*/ */
package ghidra.pcode.floatformat; package ghidra.pcode.floatformat;
import java.math.BigDecimal; import java.math.*;
import java.math.BigInteger; import java.util.HashMap;
import java.util.Map;
/** /**
* An IEEE 754 floating point class. * An IEEE 754 floating point class.
@ -31,8 +32,20 @@ import java.math.BigInteger;
* *
* <p>Operations compute exact result then round to nearest even. * <p>Operations compute exact result then round to nearest even.
*/ */
public strictfp class BigFloat implements Comparable<BigFloat> { public class BigFloat implements Comparable<BigFloat> {
final int fracbits; // there are fracbits+1 significant bits.
public static final String INFINITY = "Infinity";
public static final String POSITIVE_INFINITY = "+" + INFINITY;
public static final String NEGATIVE_INFINITY = "-" + INFINITY;
public static final String NAN = "NaN";
private static final int INFINITE_SCALE = -(64 * 1024);
public static final BigDecimal BIG_POSITIVE_INFINITY =
new BigDecimal(BigInteger.ONE, INFINITE_SCALE);
public static final BigDecimal BIG_NEGATIVE_INFINITY =
(new BigDecimal(BigInteger.ONE, INFINITE_SCALE)).negate();
final int fracbits; // number of significant mantissa bits including implied msb if relavent
final int expbits; // # bits used for exponent final int expbits; // # bits used for exponent
final int maxScale; final int maxScale;
@ -40,19 +53,22 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
FloatKind kind; FloatKind kind;
// -1, +1 int sign; // -1, +1
int sign;
// normal numbers have unscaled.bitLength() = fracbits+1 // normal numbers have unscaled.bitLength() = fracbits+1
// subnormal numbers have scale=0 and unscaled.bitLength() <= fracbits // subnormal numbers have scale=0 and unscaled.bitLength() <= fracbits
BigInteger unscaled; BigInteger unscaled;
int scale; int scale;
private static Map<Integer, MathContext> defaultDisplayContextMap = new HashMap<>();
/** /**
* Construct a BigFloat. If kind is FINITE, the value is <code>sign*unscaled*2^(scale-fracbits)</code>. * Construct a BigFloat. If kind is FINITE, the value is <code>sign*unscaled*2^(scale-fracbits)</code>.
* <p> * <p>
* NOTE: Requires that normal values are constructed in a normal form as with denormal values. * NOTE: Requires that normal values are constructed in a normal form as with denormal values.
* *
* @param fracbits number of fractional bits (positive non-zero value) * @param fracbits number of fractional bits (positive non-zero value; includes additional
* implied bit if relavent).
* @param expbits maximum number of bits in exponent (positive non-zero value) * @param expbits maximum number of bits in exponent (positive non-zero value)
* @param kind the Kind, FINITE, INFINITE, ... * @param kind the Kind, FINITE, INFINITE, ...
* @param sign +1 or -1 * @param sign +1 or -1
@ -71,8 +87,8 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
this.maxScale = (1 << (expbits - 1)) - 1; this.maxScale = (1 << (expbits - 1)) - 1;
this.minScale = 1 - this.maxScale; this.minScale = 1 - this.maxScale;
if (unscaled.bitLength() > (fracbits + 1)) { if (unscaled.bitLength() > fracbits) {
throw new IllegalArgumentException("unscaled value exceeds " + (fracbits + 1) + throw new IllegalArgumentException("unscaled value exceeds " + fracbits +
" bits in length (length=" + unscaled.bitLength() + ")"); " bits in length (length=" + unscaled.bitLength() + ")");
} }
if (scale < minScale || scale > maxScale) { if (scale < minScale || scale > maxScale) {
@ -182,7 +198,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
*/ */
public static BigFloat infinity(int fracbits, int expbits, int sign) { public static BigFloat infinity(int fracbits, int expbits, int sign) {
return new BigFloat(fracbits, expbits, FloatKind.INFINITE, sign, return new BigFloat(fracbits, expbits, FloatKind.INFINITE, sign,
BigInteger.ONE.shiftLeft(fracbits), (1 << (expbits - 1)) - 1); BigInteger.ONE.shiftLeft(fracbits - 1), (1 << (expbits - 1)) - 1);
} }
/** /**
@ -223,7 +239,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
* @return {@code true} if this BigFloat is FINITE and normal. * @return {@code true} if this BigFloat is FINITE and normal.
*/ */
public boolean isNormal() { public boolean isNormal() {
return kind == FloatKind.FINITE && unscaled.bitLength() == (fracbits + 1); return kind == FloatKind.FINITE && unscaled.bitLength() == fracbits;
} }
/** /**
@ -236,7 +252,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
*/ */
public boolean isDenormal() { public boolean isDenormal() {
return kind == FloatKind.FINITE && !unscaled.equals(BigInteger.ZERO) && return kind == FloatKind.FINITE && !unscaled.equals(BigInteger.ZERO) &&
unscaled.bitLength() <= fracbits; unscaled.bitLength() < fracbits;
} }
/** /**
@ -263,7 +279,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
return; return;
} }
int extrabits = Math.max(unscaled.bitLength() - (fracbits + 1), minScale - scale); int extrabits = Math.max(unscaled.bitLength() - fracbits, minScale - scale);
if (extrabits <= 0) { if (extrabits <= 0) {
throw new AssertionError("Rounding with no extra bits of precision"); throw new AssertionError("Rounding with no extra bits of precision");
@ -279,7 +295,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
if (midbitset && (eps || odd)) { if (midbitset && (eps || odd)) {
unscaled = unscaled.add(BigInteger.ONE); unscaled = unscaled.add(BigInteger.ONE);
// handle overflowing carry // handle overflowing carry
if (unscaled.bitLength() > fracbits + 1) { if (unscaled.bitLength() > fracbits) {
assert (unscaled.bitLength() == unscaled.getLowestSetBit() + 1); assert (unscaled.bitLength() == unscaled.getLowestSetBit() + 1);
unscaled = unscaled.shiftRight(1); unscaled = unscaled.shiftRight(1);
scale += 1; scale += 1;
@ -295,14 +311,15 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
if (kind != FloatKind.FINITE || unscaled.signum() == 0) { if (kind != FloatKind.FINITE || unscaled.signum() == 0) {
throw new AssertionError("lead bit of non-finite or zero"); throw new AssertionError("lead bit of non-finite or zero");
} }
return unscaled.bitLength() - fracbits + scale; return unscaled.bitLength() - fracbits + scale + 1;
} }
/** /**
* If finite, the returned BigDecimal is exactly equal to this. If not finite, one of the * If finite, the returned BigDecimal is exactly equal to this. If not finite, one of the
* FloatFormat.BIG_* constants is returned. * FloatFormat.BIG_* constants is returned.
* *
* @return a BigDecimal * @return a BigDecimal or null if value is NaN (i.e., {@link FloatKind#QUIET_NAN} or
* {@link FloatKind#SIGNALING_NAN}).
*/ */
public BigDecimal toBigDecimal() { public BigDecimal toBigDecimal() {
switch (kind) { switch (kind) {
@ -312,7 +329,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
} }
int unusedBits = Math.max(unscaled.getLowestSetBit(), 0); int unusedBits = Math.max(unscaled.getLowestSetBit(), 0);
BigInteger val = unscaled; BigInteger val = unscaled;
int iscale = scale - fracbits; int iscale = scale - fracbits + 1;
BigDecimal x; BigDecimal x;
if (iscale >= -unusedBits) { if (iscale >= -unusedBits) {
x = new BigDecimal(val.shiftLeft(iscale)); x = new BigDecimal(val.shiftLeft(iscale));
@ -330,11 +347,10 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
} }
return x; return x;
case INFINITE: case INFINITE:
return sign < 0 ? FloatFormat.BIG_NEGATIVE_INFINITY return sign < 0 ? BIG_NEGATIVE_INFINITY : BIG_POSITIVE_INFINITY;
: FloatFormat.BIG_POSITIVE_INFINITY;
case QUIET_NAN: case QUIET_NAN:
case SIGNALING_NAN: case SIGNALING_NAN:
return FloatFormat.BIG_NaN; return null;
default: default:
throw new AssertionError("unknown BigFloat kind: " + kind); throw new AssertionError("unknown BigFloat kind: " + kind);
} }
@ -359,15 +375,16 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
String binary; String binary;
if (this.isNormal()) { if (this.isNormal()) {
binary = "1." + unscaled.toString(2).substring(1); binary = "1." + unscaled.toString(2).substring(1);
ascale += (unscaled.bitLength() - (fracbits + 1)); ascale += (unscaled.bitLength() - fracbits);
} }
else { // subnormal else { // subnormal
assert (unscaled.bitLength() <= fracbits); assert (unscaled.bitLength() < fracbits);
if (unscaled.equals(BigInteger.ZERO)) { if (unscaled.equals(BigInteger.ZERO)) {
return String.format("%s0b0.0", s); return String.format("%s0b0.0", s);
} }
binary = binary =
"0." + "0".repeat(fracbits - unscaled.bitLength()) + unscaled.toString(2); "0." + "0".repeat(fracbits - unscaled.bitLength() - 1) +
unscaled.toString(2);
} }
binary = binary.replaceAll("0*$", ""); binary = binary.replaceAll("0*$", "");
if (binary.endsWith(".")) { if (binary.endsWith(".")) {
@ -497,7 +514,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
// nbits(x) - nbits(y) <= nbits(x/y) <= nbits(x) - nbits(y) + 1 // nbits(x) - nbits(y) <= nbits(x/y) <= nbits(x) - nbits(y) + 1
// so // so
// this + lshift - other = fracbits+2 => // this + lshift - other = fracbits+2 =>
int lshift = fracbits + 2 + other.unscaled.bitLength() - this.unscaled.bitLength(); int lshift = fracbits + 1 + other.unscaled.bitLength() - this.unscaled.bitLength();
this.upscale(lshift); this.upscale(lshift);
BigInteger qr[] = this.unscaled.divideAndRemainder(other.unscaled); BigInteger qr[] = this.unscaled.divideAndRemainder(other.unscaled);
@ -505,7 +522,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
BigInteger r = qr[1]; BigInteger r = qr[1];
this.sign *= other.sign; this.sign *= other.sign;
this.scale -= other.scale - fracbits; this.scale -= other.scale - fracbits + 1;
this.unscaled = q; this.unscaled = q;
this.internalRound(r.signum() != 0); this.internalRound(r.signum() != 0);
} }
@ -545,9 +562,9 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
// this and other are finite // this and other are finite
this.sign *= other.sign; this.sign *= other.sign;
this.unscaled = this.unscaled.multiply(other.unscaled); this.unscaled = this.unscaled.multiply(other.unscaled);
this.scale += other.scale - fracbits; this.scale += other.scale - fracbits + 1;
this.scaleUpTo(fracbits + 2); this.scaleUpTo(fracbits + 1);
this.internalRound(false); this.internalRound(false);
} }
@ -639,10 +656,10 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
protected void add0(BigFloat other) { protected void add0(BigFloat other) {
int d = this.scale - other.scale; int d = this.scale - other.scale;
if (d > fracbits + 1) { if (d > fracbits) {
return; return;
} }
else if (d < -(fracbits + 1)) { else if (d < -fracbits) {
this.copyFrom(other); this.copyFrom(other);
return; return;
} }
@ -664,7 +681,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
this.scale = a.scale - 1; this.scale = a.scale - 1;
this.unscaled = a.unscaled.shiftLeft(1).add(b.unscaled.shiftRight(d - 1)); this.unscaled = a.unscaled.shiftLeft(1).add(b.unscaled.shiftRight(d - 1));
scaleUpTo(fracbits + 2); scaleUpTo(fracbits + 1);
internalRound(residue); internalRound(residue);
} }
@ -672,10 +689,10 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
protected void sub0(BigFloat other) { protected void sub0(BigFloat other) {
int d = this.scale - other.scale; int d = this.scale - other.scale;
if (d > fracbits + 2) { if (d > fracbits + 1) {
return; return;
} }
else if (d < -(fracbits + 2)) { else if (d < -(fracbits + 1)) {
this.copyFrom(other); this.copyFrom(other);
return; return;
} }
@ -710,7 +727,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
this.sign *= -1; this.sign *= -1;
this.unscaled = this.unscaled.negate(); this.unscaled = this.unscaled.negate();
} }
scaleUpTo(fracbits + 2); scaleUpTo(fracbits + 1);
internalRound(residue); internalRound(residue);
} }
@ -751,11 +768,11 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
BigInteger bit; BigInteger bit;
//// force at least fracbits+2 bits of precision in the result //// force at least fracbits+2 bits of precision in the result
int sigbits = 2 * fracbits + 3; int sigbits = 2 * fracbits + 2;
this.scaleUpTo(sigbits); this.scaleUpTo(sigbits);
// scale+fracbits needs to be even for the sqrt computation // scale+fracbits needs to be even for the sqrt computation
if (((scale + fracbits) & 1) != 0) { if (((scale + fracbits - 1) & 1) != 0) {
upscale(1); upscale(1);
} }
@ -778,7 +795,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
} }
unscaled = result; unscaled = result;
scale = (scale + fracbits) / 2; scale = (scale + fracbits - 1) / 2;
internalRound(residue.signum() != 0); internalRound(residue.signum() != 0);
} }
@ -790,7 +807,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
makeZero(); makeZero();
return; return;
} }
int nbitsUnderOne = fracbits - scale; int nbitsUnderOne = fracbits - scale - 1;
unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne); unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne);
} }
@ -798,7 +815,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
private void makeOne() { private void makeOne() {
kind = FloatKind.FINITE; kind = FloatKind.FINITE;
scale = 0; scale = 0;
unscaled = BigInteger.ONE.shiftLeft(fracbits); unscaled = BigInteger.ONE.shiftLeft(fracbits - 1);
} }
// ceil, ignoring sign // ceil, ignoring sign
@ -811,7 +828,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
return; return;
} }
int nbitsUnderOne = fracbits - scale; int nbitsUnderOne = fracbits - scale - 1;
boolean increment = unscaled.getLowestSetBit() < nbitsUnderOne; boolean increment = unscaled.getLowestSetBit() < nbitsUnderOne;
unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne); unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne);
if (increment) { if (increment) {
@ -819,7 +836,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
} }
// if we carry to a new bit, change the scale // if we carry to a new bit, change the scale
if (unscaled.bitLength() > fracbits + 1) { if (unscaled.bitLength() > fracbits) {
upscale(-1); upscale(-1);
} }
} }
@ -945,7 +962,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
* @return the truncated integer form of this BigFloat * @return the truncated integer form of this BigFloat
*/ */
public BigInteger toBigInteger() { public BigInteger toBigInteger() {
BigInteger res = unscaled.shiftRight(fracbits - scale); BigInteger res = unscaled.shiftRight(fracbits - scale - 1);
if (sign < 0) { if (sign < 0) {
return res.negate(); return res.negate();
} }
@ -967,7 +984,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
*/ */
public void round() { public void round() {
BigFloat half = new BigFloat(fracbits, expbits, FloatKind.FINITE, +1, BigFloat half = new BigFloat(fracbits, expbits, FloatKind.FINITE, +1,
BigInteger.ONE.shiftLeft(fracbits), -1); BigInteger.ONE.shiftLeft(fracbits - 1), -1);
add(half); add(half);
floor(); floor();
} }
@ -1018,4 +1035,138 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
return this.sign * this.unscaled.compareTo(other.unscaled); return this.sign * this.unscaled.compareTo(other.unscaled);
} }
private String formatSpecialCase() {
if (isNaN()) {
return NAN;
}
if (isInfinite()) {
return sign < 0 ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
}
return null;
}
/**
* Perform rounding and conversion to BigDecimal prior to generating
* a formatted decimal string of the specified BigFloat value.
* A default generated {@link MathContext} is used.
* @return decimal string representation
*/
@Override
public String toString() {
String special = formatSpecialCase();
if (special != null) {
return special;
}
BigDecimal bd = toBigDecimal();
bd = bd.round(getDefaultDisplayContext(fracbits));
return bd.toString();
}
/**
* Perform rounding and conversion to BigDecimal prior to generating
* a formatted decimal string of the specified BigFloat value.
* @param displayContext display context used for rounding and precision.
* @return decimal string representation
*/
public String toString(MathContext displayContext) {
String special = formatSpecialCase();
if (special != null) {
return special;
}
BigDecimal bd = toBigDecimal();
bd = bd.round(displayContext);
return bd.toString();
}
/**
* Perform appropriate rounding and conversion to BigDecimal prior to generating
* a formatted decimal string of the specified BigFloat value.
* See {@link #toString(FloatFormat, boolean)},
* {@link FloatFormat#toDecimalString(BigFloat)} and
* {@link FloatFormat#toDecimalString(BigFloat, boolean)}.
* @param ff float format
* @param compact if true the precision will be reduced to a form which is still equivalent at
* the binary encoding level for the specified FloatFormat.
* @return decimal string representation
*/
public String toString(FloatFormat ff, boolean compact) {
String special = formatSpecialCase();
if (special != null) {
return special;
}
BigDecimal bd = toBigDecimal();
bd = bd.round(ff.getDisplayContext());
String str = bd.toString();
int precision = bd.precision();
int bdScale = bd.scale();
// Generate compact representation if requested
if (compact && precision > 2) {
BigInteger encoding = ff.getEncoding(this);
for (String newStr = str; newStr != null;) {
newStr = removeFractionalDigit(newStr, 1, false);
if (newStr != null) {
bd = new BigDecimal(newStr);
bd = bd.setScale(bdScale); // avoid scale change which may alter encoding
BigFloat bf = ff.getBigFloat(bd);
if (encoding.equals(ff.getEncoding(bf))) {
str = newStr;
}
else {
newStr = null; // stop compaction
}
}
}
}
// Strip trailing zeros
str = stripTrailingZeros(str, 1);
// Ensure decimal point is present
if (str.indexOf('.') < 0) {
str += ".0";
}
return str;
}
private String stripTrailingZeros(String decStr, int minDigits) {
String str = decStr;
while (true) {
String nextStr = removeFractionalDigit(str, 1, true);
if (nextStr == null) {
break;
}
str = nextStr;
}
return str;
}
private String removeFractionalDigit(String decStr, int minDigits, boolean stripZeroDigitOnly) {
int decimalPointIx = decStr.indexOf('.');
if (decimalPointIx < 0) {
return null;
}
int expIx = decStr.toUpperCase().indexOf('E');
String exp = "";
if (expIx > 0) {
exp = decStr.substring(expIx);
decStr = decStr.substring(0, expIx);
}
if (decStr.length() - decimalPointIx - 1 <= minDigits) {
return null;
}
int lastDigitIndex = decStr.length() - 1;
if (stripZeroDigitOnly && decStr.charAt(lastDigitIndex) != '0') {
return null;
}
// discard last mantissa digit
return decStr.substring(0, lastDigitIndex) + exp;
}
private static synchronized MathContext getDefaultDisplayContext(int fracBits) {
return defaultDisplayContextMap.computeIfAbsent(fracBits, n -> {
int precision = (int) (0.30103 * fracBits); // log10(2) * mantissa bits
return new MathContext(precision, RoundingMode.HALF_EVEN);
});
}
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* 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.
@ -30,6 +29,7 @@ public class FloatFormatFactory {
* Get float format * Get float format
* @param size format storage size in bytes * @param size format storage size in bytes
* @return float format or null if size is not supported * @return float format or null if size is not supported
* @throws UnsupportedFloatFormatException if specified size is unsupported
*/ */
public static synchronized FloatFormat getFloatFormat(int size) public static synchronized FloatFormat getFloatFormat(int size)
throws UnsupportedFloatFormatException { throws UnsupportedFloatFormatException {
@ -40,7 +40,6 @@ public class FloatFormatFactory {
cache.put(size, format); cache.put(size, format);
} }
return format; return format;
} }
} }

View file

@ -129,6 +129,7 @@ class DataDB extends CodeUnitDB implements Data {
} }
private void computeLength() { private void computeLength() {
// NOTE: Data intentionally does not use aligned-length
length = dataType.getLength(); length = dataType.getLength();
// undefined will never change their size // undefined will never change their size

View file

@ -36,6 +36,7 @@ class ArrayDB extends DataTypeDB implements Array {
private volatile String displayName; private volatile String displayName;
private ArrayDBAdapter adapter; private ArrayDBAdapter adapter;
private int elementLength; // lazy initialization
/** /**
* Constructor * Constructor
@ -52,6 +53,7 @@ class ArrayDB extends DataTypeDB implements Array {
@Override @Override
protected String doGetName() { protected String doGetName() {
elementLength = -1; // signal refresh by getElementLength()
return DataTypeUtilities.getName(this, true); return DataTypeUtilities.getName(this, true);
} }
@ -74,6 +76,7 @@ class ArrayDB extends DataTypeDB implements Array {
@Override @Override
protected boolean refresh() { protected boolean refresh() {
try { try {
elementLength = -1;
DBRecord rec = adapter.getRecord(key); DBRecord rec = adapter.getRecord(key);
if (rec != null) { if (rec != null) {
record = rec; record = rec;
@ -129,6 +132,11 @@ class ArrayDB extends DataTypeDB implements Array {
return getNumElements() * getElementLength(); return getNumElements() * getElementLength();
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
checkIsValid(); checkIsValid();
@ -169,15 +177,23 @@ class ArrayDB extends DataTypeDB implements Array {
@Override @Override
public int getElementLength() { public int getElementLength() {
lock.acquire();
try {
checkIsValid();
DataType dt = getDataType(); DataType dt = getDataType();
int elementLen; if (elementLength < 0) {
if (dt instanceof Dynamic) { if (dt instanceof Dynamic) {
elementLen = record.getIntValue(ArrayDBAdapter.ARRAY_ELEMENT_LENGTH_COL); elementLength = record.getIntValue(ArrayDBAdapter.ARRAY_ELEMENT_LENGTH_COL);
} }
else { else {
elementLen = dt.getLength(); elementLength = dt.getAlignedLength();
}
}
return elementLength;
}
finally {
lock.release();
} }
return elementLen;
} }
@Override @Override
@ -251,7 +267,7 @@ class ArrayDB extends DataTypeDB implements Array {
if (newDt instanceof Dynamic || newDt instanceof FactoryDataType) { if (newDt instanceof Dynamic || newDt instanceof FactoryDataType) {
newDt = DataType.DEFAULT; newDt = DataType.DEFAULT;
} }
int elementLength = newDt.getLength() < 0 ? oldElementLength : -1; elementLength = newDt.getLength() < 0 ? oldElementLength : -1;
record.setIntValue(ArrayDBAdapter.ARRAY_ELEMENT_LENGTH_COL, elementLength); record.setIntValue(ArrayDBAdapter.ARRAY_ELEMENT_LENGTH_COL, elementLength);
try { try {
adapter.updateRecord(record); adapter.updateRecord(record);
@ -288,7 +304,8 @@ class ArrayDB extends DataTypeDB implements Array {
public void dataTypeSizeChanged(DataType dt) { public void dataTypeSizeChanged(DataType dt) {
lock.acquire(); lock.acquire();
try { try {
if (checkIsValid() && dt == getDataType()) { if (checkIsValid() && dt == getDataType() && dt.getLength() > 0) {
elementLength = -1;
notifySizeChanged(true); notifySizeChanged(true);
} }
} }
@ -333,6 +350,7 @@ class ArrayDB extends DataTypeDB implements Array {
@Override @Override
public void dataTypeDeleted(DataType dt) { public void dataTypeDeleted(DataType dt) {
if (getDataType() == dt) { if (getDataType() == dt) {
elementLength = -1;
dataMgr.addDataTypeToDelete(key); dataMgr.addDataTypeToDelete(key);
} }
} }

View file

@ -59,6 +59,11 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
*/ */
protected abstract void initialize(); protected abstract void initialize();
@Override
public final int getAlignedLength() {
return getLength();
}
/** /**
* Get the preferred length for a new component. For Unions and packed * Get the preferred length for a new component. For Unions and packed
* structures the preferred component length for a fixed-length dataType * structures the preferred component length for a fixed-length dataType
@ -78,18 +83,7 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
if ((isPackingEnabled() || (this instanceof Union)) && !(dataType instanceof Dynamic)) { if ((isPackingEnabled() || (this instanceof Union)) && !(dataType instanceof Dynamic)) {
length = -1; // force use of datatype size length = -1; // force use of datatype size
} }
int dtLength = dataType.getLength(); return DataTypeComponentImpl.getPreferredComponentLength(dataType, length);
if (length <= 0) {
length = dtLength;
}
else if (dtLength > 0 && dtLength < length) {
length = dtLength;
}
if (length <= 0) {
throw new IllegalArgumentException("Positive length must be specified for " +
dataType.getDisplayName() + " component");
}
return length;
} }
@Override @Override

View file

@ -23,6 +23,7 @@ import ghidra.app.util.SymbolPathParser;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum; import ghidra.program.model.data.Enum;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.Namespace;
import ghidra.util.UniversalID; import ghidra.util.UniversalID;

View file

@ -453,6 +453,11 @@ class EnumDB extends DataTypeDB implements Enum {
} }
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
lock.acquire(); lock.acquire();

View file

@ -254,6 +254,11 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
return -1; return -1;
} }
@Override
public int getAlignedLength() {
return -1;
}
@Override @Override
public String getDescription() { public String getDescription() {
return "Function Signature Data Type"; return "Function Signature Data Type";

View file

@ -207,6 +207,12 @@ class PointerDB extends DataTypeDB implements Pointer {
} }
} }
@Override
public int getAlignedLength() {
// assume pointers are never padded
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
lock.acquire(); lock.acquire();

View file

@ -1709,7 +1709,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
DataTypeComponent dtc = otherComponents[i]; DataTypeComponent dtc = otherComponents[i];
DataType dt = resolvedDts[i]; // ancestry check already performed by caller DataType dt = resolvedDts[i]; // ancestry check already performed by caller
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength(); int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getAlignedLength();
if (length < 0 || dtc.isBitFieldComponent()) { if (length < 0 || dtc.isBitFieldComponent()) {
// TODO: bitfield truncation/expansion may be an issue if data organization changes // TODO: bitfield truncation/expansion may be an issue if data organization changes
length = dtc.getLength(); length = dtc.getLength();
@ -1817,7 +1817,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
if (dtc.getDataType() == dt) { if (dtc.getDataType() == dt) {
// assume no impact to bitfields since base types should not change size // assume no impact to bitfields since base types should not change size
int dtcLen = dtc.getLength(); int dtcLen = dtc.getLength();
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength(); int length =
DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getAlignedLength();
if (length < 0) { if (length < 0) {
length = dtcLen; length = dtcLen;
} }
@ -1875,7 +1876,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
forceRepack |= isPacked; forceRepack |= isPacked;
continue; continue;
} }
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength(); int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getAlignedLength();
if (length < 0) { if (length < 0) {
continue; // illegal condition - skip continue; // illegal condition - skip
} }
@ -2304,7 +2305,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
int nextIndex) throws IOException { int nextIndex) throws IOException {
int oldLen = comp.getLength(); int oldLen = comp.getLength();
int len = DataTypeComponent.usesZeroLengthComponent(newDt) ? 0 : newDt.getLength(); int len = DataTypeComponent.usesZeroLengthComponent(newDt) ? 0 : newDt.getAlignedLength();
if (len < 0) { if (len < 0) {
len = oldLen; len = oldLen;
} }

View file

@ -154,6 +154,11 @@ class TypedefDB extends DataTypeDB implements TypeDef {
return getDataType().getLength(); return getDataType().getLength();
} }
@Override
public int getAlignedLength() {
return getDataType().getAlignedLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
return getDataType().getDescription(); return getDataType().getDescription();

View file

@ -487,7 +487,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
if (dt instanceof BitFieldDataType) { if (dt instanceof BitFieldDataType) {
dt = adjustBitField(dt); // in case base type changed dt = adjustBitField(dt); // in case base type changed
} }
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength(); int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getAlignedLength();
if (length < 0) { if (length < 0) {
continue; // illegal condition - skip continue; // illegal condition - skip
} }
@ -533,7 +533,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
boolean changed = false; boolean changed = false;
for (DataTypeComponentDB dtc : components) { for (DataTypeComponentDB dtc : components) {
if (dtc.getDataType() == dt) { if (dtc.getDataType() == dt) {
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength(); int length =
DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getAlignedLength();
if (length >= 0 && length != dtc.getLength()) { if (length >= 0 && length != dtc.getLength()) {
dtc.setLength(length, true); dtc.setLength(length, true);
changed = true; changed = true;
@ -824,7 +825,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
} }
else { else {
int len = DataTypeComponent.usesZeroLengthComponent(newDt) ? 0 int len = DataTypeComponent.usesZeroLengthComponent(newDt) ? 0
: newDt.getLength(); : newDt.getAlignedLength();
if (len < 0) { if (len < 0) {
len = dtc.getLength(); len = dtc.getLength();
} }

View file

@ -19,6 +19,7 @@ import java.math.BigDecimal;
import generic.complex.Complex; import generic.complex.Complex;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
import ghidra.program.model.data.floats.AbstractFloatDataType;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.WrappedMemBuffer; import ghidra.program.model.mem.WrappedMemBuffer;
@ -86,9 +87,15 @@ public abstract class AbstractComplexDataType extends BuiltIn {
return floatType.getLength() * 2; return floatType.getLength() * 2;
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
return "The data type for a complex number: a + bi"; return "The data type for a complex number: a + bi; consisting of two " +
floatType.getName() + " values";
} }
private static double toDouble(Object obj) { private static double toDouble(Object obj) {

View file

@ -78,6 +78,25 @@ public abstract class AbstractDataType implements DataType {
: DataOrganizationImpl.getDefaultOrganization(); : DataOrganizationImpl.getDefaultOrganization();
} }
/**
* Get the {@link DataOrganization} which should be used by a {@link AbstractDataType} when
* associated with a specified {@link DataTypeManager dataMgr}. If a null
* {@code dataMgr} is specified the default {@link DataOrganization} will be returned.
* @param dataMgr datatype manager
* @return the {@link DataOrganization} which should be used by a {@link AbstractDataType}
* instance.
*/
protected static DataOrganization getDataOrganization(DataTypeManager dataMgr) {
DataOrganization dataOrganization = null;
if (dataMgr != null) {
dataOrganization = dataMgr.getDataOrganization();
}
if (dataOrganization == null) {
dataOrganization = DataOrganizationImpl.getDefaultOrganization();
}
return dataOrganization;
}
@Override @Override
public DataTypePath getDataTypePath() { public DataTypePath getDataTypePath() {
// use methods instead of fields since they mey be overriden // use methods instead of fields since they mey be overriden

View file

@ -150,6 +150,11 @@ public abstract class AbstractPointerTypedefBuiltIn extends BuiltIn implements T
return modelTypedef.getLength(); return modelTypedef.getLength();
} }
@Override
public int getAlignedLength() {
return modelTypedef.getAlignedLength();
}
@Override @Override
public DataType getDataType() { public DataType getDataType() {
return modelTypedef.getDataType(); return modelTypedef.getDataType();

View file

@ -299,7 +299,7 @@ class AlignedComponentPacker {
int minOffset) { int minOffset) {
DataType componentDt = dataTypeComponent.getDataType(); DataType componentDt = dataTypeComponent.getDataType();
int dtSize = componentDt.isZeroLength() ? 0 : componentDt.getLength(); int dtSize = componentDt.isZeroLength() ? 0 : componentDt.getAlignedLength();
if (dtSize < 0) { if (dtSize < 0) {
dtSize = dataTypeComponent.getLength(); dtSize = dataTypeComponent.getLength();
} }

View file

@ -56,6 +56,10 @@ public class ArrayDataType extends DataTypeImpl implements Array {
public ArrayDataType(DataType dataType, int numElements, int elementLength, public ArrayDataType(DataType dataType, int numElements, int elementLength,
DataTypeManager dtm) { DataTypeManager dtm) {
super(dataType.getCategoryPath(), "array", dtm); super(dataType.getCategoryPath(), "array", dtm);
if (dataType instanceof FactoryDataType) {
throw new IllegalArgumentException(
"Factory data type not permitted");
}
if (numElements < 0) { if (numElements < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Number of array elements may not be negative [" + numElements + "]"); "Number of array elements may not be negative [" + numElements + "]");
@ -75,6 +79,9 @@ public class ArrayDataType extends DataTypeImpl implements Array {
} }
this.elementLength = elementLength; this.elementLength = elementLength;
} }
else {
this.elementLength = dataType.getAlignedLength();
}
this.dataType = dataType; this.dataType = dataType;
this.numElements = numElements; this.numElements = numElements;
name = DataTypeUtilities.getName(this, true); name = DataTypeUtilities.getName(this, true);
@ -168,6 +175,11 @@ public class ArrayDataType extends DataTypeImpl implements Array {
return numElements * getElementLength(); return numElements * getElementLength();
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
return "Array of " + dataType.getDisplayName(); return "Array of " + dataType.getDisplayName();
@ -193,7 +205,8 @@ public class ArrayDataType extends DataTypeImpl implements Array {
@Override @Override
public void dataTypeSizeChanged(DataType dt) { public void dataTypeSizeChanged(DataType dt) {
if (dt == dataType) { if (dt == dataType && dt.getLength() > 0) {
elementLength = dataType.getAlignedLength();
notifySizeChanged(); notifySizeChanged();
} }
} }
@ -217,7 +230,7 @@ public class ArrayDataType extends DataTypeImpl implements Array {
@Override @Override
public int getElementLength() { public int getElementLength() {
return (dataType instanceof Dynamic) ? elementLength : dataType.getLength(); return elementLength;
} }
@Override @Override
@ -246,7 +259,9 @@ public class ArrayDataType extends DataTypeImpl implements Array {
dataType.removeParent(this); dataType.removeParent(this);
dataType = newDt; dataType = newDt;
dataType.addParent(this); dataType.addParent(this);
elementLength = newDt.getLength() < 0 ? oldElementLength : -1; if (dataType.getLength() >= 0) {
elementLength = dataType.getAlignedLength();
}
if (!getName().equals(oldName)) { if (!getName().equals(oldName)) {
notifyNameChanged(oldName); notifyNameChanged(oldName);
} }

View file

@ -15,9 +15,8 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import java.util.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*;
import ghidra.docking.settings.*; import ghidra.docking.settings.*;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
@ -336,6 +335,11 @@ public class BitFieldDataType extends AbstractDataType {
return storageSize; return storageSize;
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDescription() { public String getDescription() {
StringBuffer sbuf = new StringBuffer(); StringBuffer sbuf = new StringBuffer();

View file

@ -15,8 +15,10 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.Float64DataType;
/** /**
* Provides a definition of a {@code complex} built-in data type consisting of two 8 byte floating point * Provides a definition of a {@code complex} built-in data type consisting of two 64-bit floating point
* numbers in the IEEE 754 double precision format. * numbers in the IEEE 754 double precision format.
*/ */
public class Complex16DataType extends AbstractComplexDataType { public class Complex16DataType extends AbstractComplexDataType {
@ -28,7 +30,7 @@ public class Complex16DataType extends AbstractComplexDataType {
} }
public Complex16DataType(DataTypeManager dtm) { public Complex16DataType(DataTypeManager dtm) {
super("complex16", Float8DataType.dataType, dtm); super("complex16", Float64DataType.dataType, dtm);
} }
@Override @Override

View file

@ -15,8 +15,10 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.Float128DataType;
/** /**
* Provides a definition of a {@code complex} built-in data type consisting of two 16 byte floating point * Provides a definition of a {@code complex} built-in data type consisting of two 128-bit floating point
* numbers in the IEEE 754 double precision format. * numbers in the IEEE 754 double precision format.
*/ */
public class Complex32DataType extends AbstractComplexDataType { public class Complex32DataType extends AbstractComplexDataType {
@ -28,7 +30,7 @@ public class Complex32DataType extends AbstractComplexDataType {
} }
public Complex32DataType(DataTypeManager dtm) { public Complex32DataType(DataTypeManager dtm) {
super("complex32", Float16DataType.dataType, dtm); super("complex32", Float128DataType.dataType, dtm);
} }
@Override @Override

View file

@ -15,8 +15,10 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.Float32DataType;
/** /**
* Provides a definition of a {@code complex} built-in data type consisting of two 4 byte floating point * Provides a definition of a {@code complex} built-in data type consisting of two 32-bit floating point
* numbers in the IEEE 754 double precision format. * numbers in the IEEE 754 double precision format.
*/ */
@ -29,7 +31,7 @@ public class Complex8DataType extends AbstractComplexDataType {
} }
public Complex8DataType(DataTypeManager dtm) { public Complex8DataType(DataTypeManager dtm) {
super("complex8", Float4DataType.dataType, dtm); super("complex8", Float32DataType.dataType, dtm);
} }
@Override @Override

View file

@ -62,6 +62,11 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
description = ""; description = "";
} }
@Override
public final int getAlignedLength() {
return getLength();
}
@Override @Override
public int getStoredPackingValue() { public int getStoredPackingValue() {
return packing; return packing;
@ -96,18 +101,7 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
if ((isPackingEnabled() || (this instanceof Union)) && !(dataType instanceof Dynamic)) { if ((isPackingEnabled() || (this instanceof Union)) && !(dataType instanceof Dynamic)) {
length = -1; // force use of datatype size length = -1; // force use of datatype size
} }
int dtLength = dataType.getLength(); return DataTypeComponentImpl.getPreferredComponentLength(dataType, length);
if (length <= 0) {
length = dtLength;
}
else if (dtLength > 0 && dtLength < length) {
length = dtLength;
}
if (length <= 0) {
throw new IllegalArgumentException("Positive length must be specified for " +
dataType.getDisplayName() + " component");
}
return length;
} }
@Override @Override

View file

@ -79,7 +79,7 @@ public abstract class CountedDynamicDataType extends DynamicDataType {
int n = (int) getCount(memory, start.add(counterOffset)); int n = (int) getCount(memory, start.add(counterOffset));
DataTypeComponent[] comps = new DataTypeComponent[n + 1]; DataTypeComponent[] comps = new DataTypeComponent[n + 1];
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(header, buf); DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(header, buf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + buf.getAddress()); Msg.error(this, "ERROR: problem with data at " + buf.getAddress());
@ -94,7 +94,7 @@ public abstract class CountedDynamicDataType extends DynamicDataType {
try { try {
newBuf.advance(countSize); newBuf.advance(countSize);
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {
dti = DataTypeInstance.getDataTypeInstance(baseStruct, buf); dti = DataTypeInstance.getDataTypeInstance(baseStruct, buf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + buf.getAddress()); Msg.error(this, "ERROR: problem with data at " + buf.getAddress());
return null; return null;

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.util.exception.NoValueException; import java.util.Arrays;
public interface DataOrganization { public interface DataOrganization {
@ -75,17 +75,17 @@ public interface DataOrganization {
int getLongLongSize(); int getLongLongSize();
/** /**
* @return the size of a float primitive data type in bytes. * @return the encoding size of a float primitive data type in bytes.
*/ */
int getFloatSize(); int getFloatSize();
/** /**
* @return the size of a double primitive data type in bytes. * @return the encoding size of a double primitive data type in bytes.
*/ */
int getDoubleSize(); int getDoubleSize();
/** /**
* @return the size of a long double primitive data type in bytes. * @return the encoding size of a long double primitive data type in bytes.
*/ */
int getLongDoubleSize(); int getLongDoubleSize();
@ -119,12 +119,14 @@ public interface DataOrganization {
int getDefaultPointerAlignment(); int getDefaultPointerAlignment();
/** /**
* Gets the alignment that is defined for a data type of the indicated size if one is defined. * Gets the primitive data alignment that is defined for the specified size. If no entry has
* @param size the size of the data type * been defined for the specified size alignment of the next smaller map entry will be returned.
* If the map is empty the {@link #getDefaultAlignment() default alignment}. The returned
* value will not exceed the {@link #getAbsoluteMaxAlignment() defined maximum alignment}.
* @param size the primitive data size
* @return the alignment of the data type. * @return the alignment of the data type.
* @throws NoValueException if there isn't an alignment defined for the indicated size.
*/ */
int getSizeAlignment(int size) throws NoValueException; int getSizeAlignment(int size);
/** /**
* Get the composite bitfield packing information associated with this data organization. * Get the composite bitfield packing information associated with this data organization.
@ -139,8 +141,8 @@ public interface DataOrganization {
int getSizeAlignmentCount(); int getSizeAlignmentCount();
/** /**
* Gets the sizes that have an alignment specified. * Gets the ordered list of sizes that have an alignment specified.
* @return the sizes with alignments mapped to them. * @return the ordered list of sizes with alignments mapped to them.
*/ */
int[] getSizes(); int[] getSizes();
@ -213,19 +215,14 @@ public interface DataOrganization {
} }
int[] keys = getSizes(); int[] keys = getSizes();
int[] op2keys = obj.getSizes(); int[] op2keys = obj.getSizes();
if (keys.length != op2keys.length) { if (!Arrays.equals(keys, op2keys)) {
return false; return false;
} }
try {
for (int k : keys) { for (int k : keys) {
if (getSizeAlignment(k) != obj.getSizeAlignment(k)) { if (getSizeAlignment(k) != obj.getSizeAlignment(k)) {
return false; return false;
} }
} }
}
catch (NoValueException ex) {
return false;
}
return true; return true;
} }
} }

View file

@ -20,11 +20,11 @@ import static ghidra.program.model.pcode.ElementId.*;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import ghidra.program.database.DBStringMapAdapter; import ghidra.program.database.DBStringMapAdapter;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.pcode.Encoder; import ghidra.program.model.pcode.Encoder;
import ghidra.util.exception.NoValueException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -48,9 +48,9 @@ public class DataOrganizationImpl implements DataOrganization {
public static final int DEFAULT_INT_SIZE = 4; public static final int DEFAULT_INT_SIZE = 4;
public static final int DEFAULT_LONG_SIZE = 4; public static final int DEFAULT_LONG_SIZE = 4;
public static final int DEFAULT_LONG_LONG_SIZE = 8; public static final int DEFAULT_LONG_LONG_SIZE = 8;
public static final int DEFAULT_FLOAT_SIZE = 4; public static final int DEFAULT_FLOAT_SIZE = 4; // encoding size only
public static final int DEFAULT_DOUBLE_SIZE = 8; public static final int DEFAULT_DOUBLE_SIZE = 8; // encoding size only
public static final int DEFAULT_LONG_DOUBLE_SIZE = 8; public static final int DEFAULT_LONG_DOUBLE_SIZE = 8; // encoding size only
// DBStringMapAdapter save/restore keys // DBStringMapAdapter save/restore keys
private static final String BIG_ENDIAN_NAME = "big_endian"; private static final String BIG_ENDIAN_NAME = "big_endian";
@ -83,7 +83,7 @@ public class DataOrganizationImpl implements DataOrganization {
/* /*
* Map for determining the alignment of a data type based upon its size. * Map for determining the alignment of a data type based upon its size.
*/ */
private final HashMap<Integer, Integer> sizeAlignmentMap = new HashMap<>(); private final TreeMap<Integer, Integer> sizeAlignmentMap = new TreeMap<>();
/** /**
* Creates a new default DataOrganization. This has a mapping which defines the alignment * Creates a new default DataOrganization. This has a mapping which defines the alignment
@ -294,7 +294,7 @@ public class DataOrganizationImpl implements DataOrganization {
} }
/** /**
* Defines the size of a float primitive data type. * Defines the encoding size of a float primitive data type.
* @param floatSize the size of a float. * @param floatSize the size of a float.
*/ */
public void setFloatSize(int floatSize) { public void setFloatSize(int floatSize) {
@ -305,7 +305,7 @@ public class DataOrganizationImpl implements DataOrganization {
} }
/** /**
* Defines the size of a double primitive data type. * Defines the encoding size of a double primitive data type.
* @param doubleSize the size of a double. * @param doubleSize the size of a double.
*/ */
public void setDoubleSize(int doubleSize) { public void setDoubleSize(int doubleSize) {
@ -319,7 +319,7 @@ public class DataOrganizationImpl implements DataOrganization {
} }
/** /**
* Defines the size of a long double primitive data type. * Defines the encoding size of a long double primitive data type.
* @param longDoubleSize the size of a long double. * @param longDoubleSize the size of a long double.
*/ */
public void setLongDoubleSize(int longDoubleSize) { public void setLongDoubleSize(int longDoubleSize) {
@ -409,15 +409,14 @@ public class DataOrganizationImpl implements DataOrganization {
this.defaultPointerAlignment = defaultPointerAlignment; this.defaultPointerAlignment = defaultPointerAlignment;
} }
/**
* Gets the alignment that is defined for a data type of the indicated size if one is defined.
* @param size the size of the data type
* @return the alignment of the data type.
* @throws NoValueException if there isn't an alignment defined for the indicated size.
*/
@Override @Override
public int getSizeAlignment(int size) throws NoValueException { public int getSizeAlignment(int size) {
return sizeAlignmentMap.get(size); Entry<Integer, Integer> floorEntry = sizeAlignmentMap.floorEntry(size);
int alignment = floorEntry != null ? floorEntry.getValue() : defaultAlignment;
if (absoluteMaxAlignment != 0) {
return Math.min(alignment, absoluteMaxAlignment);
}
return alignment;
} }
/** /**
@ -500,7 +499,7 @@ public class DataOrganizationImpl implements DataOrganization {
@Override @Override
public int getAlignment(DataType dataType) { public int getAlignment(DataType dataType) {
int dtSize = dataType.getLength(); int dtSize = dataType.getAlignedLength();
if (dataType instanceof Dynamic || dataType instanceof FactoryDataType || dtSize <= 0) { if (dataType instanceof Dynamic || dataType instanceof FactoryDataType || dtSize <= 0) {
return 1; return 1;
} }
@ -525,18 +524,15 @@ public class DataOrganizationImpl implements DataOrganization {
BitFieldDataType bitfieldDt = (BitFieldDataType) dataType; BitFieldDataType bitfieldDt = (BitFieldDataType) dataType;
return getAlignment(bitfieldDt.getBaseDataType()); return getAlignment(bitfieldDt.getBaseDataType());
} }
// Otherwise get the alignment based on the size.
if (sizeAlignmentMap.containsKey(dtSize)) { // If pointer size not found in size alignment map use default pointer alignment
int sizeAlignment = sizeAlignmentMap.get(dtSize); // TODO: this should probably be re-evaluated for its neccessity
return ((absoluteMaxAlignment == 0) || (sizeAlignment < absoluteMaxAlignment)) if (!sizeAlignmentMap.containsKey(dtSize) && dataType instanceof Pointer) {
? sizeAlignment
: absoluteMaxAlignment;
}
if (dataType instanceof Pointer) {
return getDefaultPointerAlignment(); return getDefaultPointerAlignment();
} }
// Otherwise just assume the default alignment.
return getDefaultAlignment(); // Otherwise get the alignment based on the size.
return getSizeAlignment(dtSize);
} }
/** /**
@ -551,7 +547,7 @@ public class DataOrganizationImpl implements DataOrganization {
if (alignment <= 0) { if (alignment <= 0) {
return minimumOffset; return minimumOffset;
} }
if ((alignment & 1) == 0) { if (isPowerOfTwo(alignment)) {
// handle alignment which is a power-of-2 // handle alignment which is a power-of-2
return alignment + ((minimumOffset - 1) & ~(alignment - 1)); return alignment + ((minimumOffset - 1) & ~(alignment - 1));
} }
@ -560,6 +556,10 @@ public class DataOrganizationImpl implements DataOrganization {
return minimumOffset + adj; return minimumOffset + adj;
} }
private static boolean isPowerOfTwo(int n) {
return (n & (n - 1)) == 0;
}
/** /**
* Determines the least (lowest) common multiple of two numbers. * Determines the least (lowest) common multiple of two numbers.
* @param value1 the first number * @param value1 the first number
@ -689,14 +689,9 @@ public class DataOrganizationImpl implements DataOrganization {
} }
for (int size : dataOrg.getSizes()) { for (int size : dataOrg.getSizes()) {
try {
String key = keyPrefix + ELEM_SIZE_ALIGNMENT_MAP.name() + "." + size; String key = keyPrefix + ELEM_SIZE_ALIGNMENT_MAP.name() + "." + size;
dataMap.put(key, Integer.toString(dataOrg.getSizeAlignment(size))); dataMap.put(key, Integer.toString(dataOrg.getSizeAlignment(size)));
} }
catch (NoValueException e) {
// skip entry
}
}
BitFieldPackingImpl.save(dataOrg.getBitFieldPacking(), dataMap, BitFieldPackingImpl.save(dataOrg.getBitFieldPacking(), dataMap,
keyPrefix + ELEM_BITFIELD_PACKING.name() + "."); keyPrefix + ELEM_BITFIELD_PACKING.name() + ".");

View file

@ -15,9 +15,8 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import java.util.Collection;
import java.net.URL; import java.net.URL;
import java.util.Collection;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition; import ghidra.docking.settings.SettingsDefinition;
@ -227,17 +226,48 @@ public interface DataType {
public String getMnemonic(Settings settings); public String getMnemonic(Settings settings);
/** /**
* Get the length (number of 8-bit bytes) of this DataType. * Get the length of this DataType as a number of 8-bit bytes.
* <p> * <p>
* NOTE: No datatype should ever return 0, even if {@link #isZeroLength()}, and only * For primitive datatypes this reflects the smallest varnode which can be used to
* {@link Dynamic} datatypes should return -1. If {@link #isZeroLength()} is true a length of 1 * contain its value (i.e., raw data length).
* should be returned. Where a zero-length datatype can be handled (e.g., {@link Composite}) the * <p>
* Example: For x86 32-bit gcc an 80-bit {@code long double} {@link #getLength() raw data length}
* of 10-bytes will fit within a floating point register while its {@link #getAlignedLength() aligned-length}
* of 12-bytes is used by the gcc compiler for data/array/component allocations to maintain alignment
* (i.e., {@code sizeof(long double)} ).
* <p>
* NOTE: Other than the {@link VoidDataType}, no datatype should ever return 0, even if
* {@link #isZeroLength()}, and only {@link Dynamic}/{@link FactoryDataType} datatypes
* should return -1. If {@link #isZeroLength()} is true a length of 1 should be returned.
* Where a zero-length datatype can be handled (e.g., {@link Composite}) the
* {@link #isZeroLength()} method should be used. * {@link #isZeroLength()} method should be used.
* *
* @return the length of this DataType * @return the length of this DataType
*/ */
public int getLength(); public int getLength();
/**
* Get the aligned-length of this datatype as a number of 8-bit bytes.
* <p>
* For primitive datatypes this is equivalent to the C/C++ "sizeof" operation within source code and
* should be used when determining {@link Array} element length or component sizing for a
* {@link Composite}. For {@link Pointer}, {@link Composite} and {@link Array} types this will
* return the same value as {@link #getLength()}.
* <p>
* Example: For x86 32-bit gcc an 80-bit {@code long double} {@link #getLength() raw data length}
* of 10-bytes will fit within a floating point register while its {@link #getAlignedLength() aligned-length}
* of 12-bytes is used by the gcc compiler for data/array/component allocations to maintain alignment
* (i.e., {@code sizeof(long double)} ).
* <p>
* NOTE: Other than the {@link VoidDataType}, no datatype should ever return 0, even if
* {@link #isZeroLength()}, and only {@link Dynamic} / {@link FactoryDataType} /
* {@link FunctionDefinition} datatypes should return -1. If {@link #isZeroLength()} is true
* a length of 1 should be returned.
*
* @return byte length of binary encoding.
*/
public int getAlignedLength();
/** /**
* Indicates this datatype is defined with a zero length. * Indicates this datatype is defined with a zero length.
* <p> * <p>

View file

@ -347,4 +347,32 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali
return InternalDataTypeComponent.toString(this); return InternalDataTypeComponent.toString(this);
} }
/**
* Get the preferred length for a new component. The length returned will be no
* larger than the specified length.
*
* @param dataType new component datatype
* @param length constrained length or -1 to force use of dataType size.
* Dynamic types such as string must have a positive length
* specified.
* @return preferred component length
*/
public static int getPreferredComponentLength(DataType dataType, int length) {
if (DataTypeComponent.usesZeroLengthComponent(dataType)) {
return 0;
}
int dtLength = dataType.getAlignedLength();
if (length <= 0) {
length = dtLength;
}
else if (dtLength > 0 && dtLength < length) {
length = dtLength;
}
if (length <= 0) {
throw new IllegalArgumentException("Positive length must be specified for " +
dataType.getDisplayName() + " component");
}
return length;
}
} }

View file

@ -36,6 +36,8 @@ public abstract class DataTypeImpl extends AbstractDataType {
// defaultSettings implementation established by its DataTypeManager. // defaultSettings implementation established by its DataTypeManager.
protected Settings defaultSettings; protected Settings defaultSettings;
private Integer alignedLength;
private List<WeakReference<DataType>> parentList; private List<WeakReference<DataType>> parentList;
private UniversalID universalID; private UniversalID universalID;
private SourceArchive sourceArchive; private SourceArchive sourceArchive;
@ -91,6 +93,43 @@ public abstract class DataTypeImpl extends AbstractDataType {
return getDataTypePath().getPath(); return getDataTypePath().getPath();
} }
/**
* Return the aligned-length for a fixed length datatype. This is intended to produce a
* result consistent with the C/C++ {@code sizeof(type)} operation. Use of this method
* with {@link TypeDef} is not allowed.
* Whereas {@link #getLength()} corresponds to the raw type size which may be moved into
* a smaller register/varnode. Example: this frequently occurs with encoded floating-point
* data such as a 10-byte/80-bit encoding which is stored in memory as 12 or 16-bytes in order
* to maintain memory alignment constraints.
* @param dataType datatype
* @return aligned-length or -1 if not a fixed-length datatype
*/
private static int computeAlignedLength(DataType dataType) {
if ((dataType instanceof TypeDef) || (dataType instanceof Composite) ||
(dataType instanceof Array)) {
// Typedefs must defer to base datatype for aligned-length determination
throw new UnsupportedOperationException();
}
int len = dataType.getLength();
if (len <= 0 || (dataType instanceof Pointer)) {
return len;
}
int align = dataType.getDataOrganization().getSizeAlignment(len);
int mod = len % align;
if (mod != 0) {
len += (align - mod);
}
return len;
}
@Override
public int getAlignedLength() {
if (alignedLength == null) {
alignedLength = computeAlignedLength(this);
}
return alignedLength;
}
@Override @Override
public int getAlignment() { public int getAlignment() {
int length = getLength(); int length = getLength();

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* 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.
@ -16,6 +15,7 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.listing.Data;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
/** /**
@ -33,6 +33,9 @@ public class DataTypeInstance {
/** /**
* Create an instance of a data type with the given length. * Create an instance of a data type with the given length.
* <br>
* NOTE: fixed-length primitive datatypes assume {@link DataType#getLength() raw datatype length}
* intended for {@link Data} use.
* *
* @param dt data type * @param dt data type
* @param length fixed length of the data type * @param length fixed length of the data type
@ -66,25 +69,44 @@ public class DataTypeInstance {
this.length = length; this.length = length;
} }
@Override
public String toString() {
return dataType.toString();
}
/** /**
* Generate a data-type instance * Generate a data-type instance
* Factory and Dynamic data-types are NOT handled. * Factory and Dynamic data-types are NOT handled.
* @param dataType * @param dataType data type
* @param buf * @param buf memory buffer
* @param useAlignedLength if true a fixed-length primitive data type will use its
* {@link DataType#getAlignedLength() aligned-length}, otherwise it will use its
* {@link DataType#getLength() raw length}. NOTE: This generally only relates to
* float datatypes whose raw encoding length may be shorter than their aligned-length
* generally corresponding to a compiler's "sizeof(type)" value. This should generally be
* true for {@link DataTypeComponent} and false for simple {@link Data} instances.
* @return data-type instance or null if one could not be determined * @return data-type instance or null if one could not be determined
*/ */
public static DataTypeInstance getDataTypeInstance(DataType dataType, MemBuffer buf) { public static DataTypeInstance getDataTypeInstance(DataType dataType, MemBuffer buf,
return getDataTypeInstance(dataType, buf, -1); boolean useAlignedLength) {
return getDataTypeInstance(dataType, buf, -1, useAlignedLength);
} }
/** /**
* Attempt to create a fixed-length data-type instance. * Attempt to create a fixed-length data-type instance.
* Factory and non-sizable Dynamic data-types are NOT handled. * Factory and non-sizable Dynamic data-types are NOT handled.
* @param dataType * @param dataType data type
* @param length length for sizable Dynamic data-types, otherwise ignored * @param length length for sizable Dynamic data-types, otherwise ignored
* @param useAlignedLength if true a fixed-length primitive data type will use its
* {@link DataType#getAlignedLength() aligned-length}, otherwise it will use its
* {@link DataType#getLength() raw length}. NOTE: This generally only relates to
* float datatypes whose raw encoding length may be shorter than their aligned-length
* generally corresponding to a compiler's "sizeof(type)" value. This should generally be
* true for {@link DataTypeComponent} and false for simple {@link Data} instances.
* @return data-type instance or null if unable to create instance. * @return data-type instance or null if unable to create instance.
*/ */
public static DataTypeInstance getDataTypeInstance(DataType dataType, int length) { public static DataTypeInstance getDataTypeInstance(DataType dataType, int length,
boolean useAlignedLength) {
if (dataType == null) { if (dataType == null) {
return null; return null;
} }
@ -105,6 +127,9 @@ public class DataTypeInstance {
return null; return null;
} }
} }
else if (useAlignedLength) {
length = dataType.getAlignedLength();
}
else { else {
length = dataType.getLength(); length = dataType.getLength();
} }
@ -116,20 +141,26 @@ public class DataTypeInstance {
return new DataTypeInstance(dataType, length); return new DataTypeInstance(dataType, length);
} }
@Override
public String toString() {
return dataType.toString();
}
/** /**
* Attempt to create a data-type instance associated with a specific memory location. * Attempt to create a data-type instance associated with a specific memory location.
* Factory and Dynamic data-types are handled. * Factory and Dynamic data-types are handled.
* <br>
* NOTE: fixed-length primitive datatypes assume {@link DataType#getLength() raw datatype length}
* intended for {@link Data} use.
*
* @param dataType * @param dataType
* @param buf memory location * @param buf memory location
* @param length length for sizable Dynamic data-types, otherwise ignored * @param length length for sizable Dynamic data-types, otherwise ignored
* @param useAlignedLength if true a fixed-length primitive data type will use its
* {@link DataType#getAlignedLength() aligned-length}, otherwise it will use its
* {@link DataType#getLength() raw length}. NOTE: This generally only relates to
* float datatypes whose raw encoding length may be shorter than their aligned-length
* generally corresponding to a compiler's "sizeof(type)" value. This should generally be
* true for {@link DataTypeComponent} and false for simple {@link Data} instances.
* @return data-type instance or null if unable to create instance. * @return data-type instance or null if unable to create instance.
*/ */
public static DataTypeInstance getDataTypeInstance(DataType dataType, MemBuffer buf, int length) { public static DataTypeInstance getDataTypeInstance(DataType dataType, MemBuffer buf, int length,
boolean useAlignedLength) {
if (dataType instanceof FactoryDataType) { if (dataType instanceof FactoryDataType) {
dataType = ((FactoryDataType) dataType).getDataType(buf); dataType = ((FactoryDataType) dataType).getDataType(buf);
length = -1; // ignore user-specified length for factory use length = -1; // ignore user-specified length for factory use
@ -151,6 +182,9 @@ public class DataTypeInstance {
Dynamic dynamicDataType = (Dynamic) dataType; Dynamic dynamicDataType = (Dynamic) dataType;
length = dynamicDataType.getLength(buf, length); length = dynamicDataType.getLength(buf, length);
} }
else if (useAlignedLength) {
length = dataType.getAlignedLength();
}
else { else {
length = dataType.getLength(); length = dataType.getLength();
} }

View file

@ -259,10 +259,10 @@ public final class DataUtilities {
DataTypeInstance dti; DataTypeInstance dti;
if (length > 0 && (realType instanceof Dynamic) && if (length > 0 && (realType instanceof Dynamic) &&
((Dynamic) realType).canSpecifyLength()) { ((Dynamic) realType).canSpecifyLength()) {
dti = DataTypeInstance.getDataTypeInstance(newType, memBuf, length); dti = DataTypeInstance.getDataTypeInstance(newType, memBuf, length, false);
} }
else { else {
dti = DataTypeInstance.getDataTypeInstance(newType, memBuf); dti = DataTypeInstance.getDataTypeInstance(newType, memBuf, false);
} }
if (dti == null) { if (dti == null) {

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.AbstractFloatDataType;
/** /**
* Provides a definition of a Double within a program. * Provides a definition of a Double within a program.
@ -31,7 +32,12 @@ public class DoubleDataType extends AbstractFloatDataType {
} }
public DoubleDataType(DataTypeManager dtm) { public DoubleDataType(DataTypeManager dtm) {
super("double", dtm); super("double", getDataOrganization(dtm).getDoubleSize(), dtm);
}
@Override
protected String buildDescription() {
return "Compiler-defined 'double' " + super.buildDescription();
} }
public DataType clone(DataTypeManager dtm) { public DataType clone(DataTypeManager dtm) {
@ -46,9 +52,4 @@ public class DoubleDataType extends AbstractFloatDataType {
return true; return true;
} }
@Override
public int getLength() {
return getDataOrganization().getDoubleSize();
}
} }

View file

@ -239,6 +239,11 @@ public class EnumDataType extends GenericDataType implements Enum {
return length; return length;
} }
@Override
public int getAlignedLength() {
return getLength();
}
public void setLength(int newLength) { public void setLength(int newLength) {
if (newLength == length) { if (newLength == length) {
return; return;

View file

@ -137,7 +137,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
protected DataTypeComponent addComponent(Structure es, DataType dt, String componentName) { protected DataTypeComponent addComponent(Structure es, DataType dt, String componentName) {
return es.add(dt, dt.getLength(), componentName, null); return es.add(dt, dt.getAlignedLength(), componentName, null);
} }
protected abstract void populateDynamicStructure(MemBuffer buf, Structure es); protected abstract void populateDynamicStructure(MemBuffer buf, Structure es);

View file

@ -1,44 +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.data;
public class Float8DataType extends AbstractFloatDataType {
public static final Float8DataType dataType = new Float8DataType();
public Float8DataType() {
this(null);
}
public Float8DataType(DataTypeManager dtm) {
super("float8", dtm);
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
}
return new Float8DataType(dtm);
}
@Override
public int getLength() {
return 8;
}
}

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.AbstractFloatDataType;
/** /**
* Provides a definition of a Float within a program. * Provides a definition of a Float within a program.
*/ */
@ -30,7 +32,12 @@ public class FloatDataType extends AbstractFloatDataType {
} }
public FloatDataType(DataTypeManager dtm) { public FloatDataType(DataTypeManager dtm) {
super("float", dtm); super("float", getDataOrganization(dtm).getFloatSize(), dtm);
}
@Override
protected String buildDescription() {
return "Compiler-defined 'float' " + super.buildDescription();
} }
@Override @Override
@ -46,9 +53,4 @@ public class FloatDataType extends AbstractFloatDataType {
return true; return true;
} }
@Override
public int getLength() {
return getDataOrganization().getFloatSize();
}
} }

View file

@ -169,7 +169,7 @@ public abstract class IndexedDynamicDataType extends DynamicDataType {
comps = new DataTypeComponent[2]; comps = new DataTypeComponent[2];
} }
MemoryBufferImpl newBuf = new MemoryBufferImpl(memory, buf.getAddress()); MemoryBufferImpl newBuf = new MemoryBufferImpl(memory, buf.getAddress());
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(header, newBuf); DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(header, newBuf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress()); Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress());
return null; return null;
@ -183,7 +183,7 @@ public abstract class IndexedDynamicDataType extends DynamicDataType {
int offset = countSize; int offset = countSize;
newBuf = new MemoryBufferImpl(memory, buf.getAddress()); newBuf = new MemoryBufferImpl(memory, buf.getAddress());
newBuf.advance(countSize); newBuf.advance(countSize);
dti = DataTypeInstance.getDataTypeInstance(data, newBuf); dti = DataTypeInstance.getDataTypeInstance(data, newBuf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress()); Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress());
return null; return null;

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.AbstractFloatDataType;
/** /**
* Provides a definition of a Long Double within a program. * Provides a definition of a Long Double within a program.
@ -31,7 +32,12 @@ public class LongDoubleDataType extends AbstractFloatDataType {
} }
public LongDoubleDataType(DataTypeManager dtm) { public LongDoubleDataType(DataTypeManager dtm) {
super("longdouble", dtm); super("longdouble", getDataOrganization(dtm).getLongDoubleSize(), dtm);
}
@Override
protected String buildDescription() {
return "Compiler-defined 'long double' " + super.buildDescription();
} }
public DataType clone(DataTypeManager dtm) { public DataType clone(DataTypeManager dtm) {
@ -50,9 +56,4 @@ public class LongDoubleDataType extends AbstractFloatDataType {
public boolean hasLanguageDependantLength() { public boolean hasLanguageDependantLength() {
return true; return true;
} }
@Override
public int getLength() {
return getDataOrganization().getLongDoubleSize();
}
} }

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import ghidra.program.model.data.floats.AbstractFloatDataType;
public enum MetaDataType { public enum MetaDataType {
// Enumerations are ordered in terms of how "specific" the data-type class is // Enumerations are ordered in terms of how "specific" the data-type class is
VOID, // "void" data-type VOID, // "void" data-type

View file

@ -31,6 +31,9 @@ import ghidra.program.model.pcode.PartialUnion;
* In a conflict, less specific data-types are replaced. * In a conflict, less specific data-types are replaced.
* After all information is collected a final Structure can be built by iterating over * After all information is collected a final Structure can be built by iterating over
* the final field entries. * the final field entries.
*
* NOTE: No attempt has been made to utilize {@link DataType#getAlignedLength()} when considering
* component type lengths.
*/ */
public class NoisyStructureBuilder { public class NoisyStructureBuilder {
private TreeMap<Long, DataType> offsetToDataTypeMap = new TreeMap<>(); private TreeMap<Long, DataType> offsetToDataTypeMap = new TreeMap<>();

View file

@ -171,6 +171,11 @@ public class PointerDataType extends BuiltIn implements Pointer {
return length <= 0 ? getDataOrganization().getPointerSize() : length; return length <= 0 ? getDataOrganization().getPointerSize() : length;
} }
@Override
public int getAlignedLength() {
return getLength();
}
@Override @Override
public String getDefaultLabelPrefix() { public String getDefaultLabelPrefix() {
return POINTER_LABEL_PREFIX; return POINTER_LABEL_PREFIX;

View file

@ -210,6 +210,11 @@ public class PointerTypedef extends GenericDataType implements TypeDef {
return modelTypedef.getLength(); return modelTypedef.getLength();
} }
@Override
public int getAlignedLength() {
return modelTypedef.getAlignedLength();
}
@Override @Override
public DataType getDataType() { public DataType getDataType() {
return modelTypedef.getDataType(); return modelTypedef.getDataType();

View file

@ -60,7 +60,8 @@ public abstract class RepeatCountDataType extends DynamicDataType {
MemoryBufferImpl newBuf = new MemoryBufferImpl(buf.getMemory(), buf.getAddress()); MemoryBufferImpl newBuf = new MemoryBufferImpl(buf.getMemory(), buf.getAddress());
newBuf.advance(countSize); newBuf.advance(countSize);
for (int i = 1; i < n; i++) { for (int i = 1; i < n; i++) {
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(repeatDataType, newBuf); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(repeatDataType, newBuf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress()); Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress());
return null; return null;

View file

@ -96,7 +96,8 @@ public abstract class RepeatedDynamicDataType extends DynamicDataType {
try { try {
newBuf.advance(countSize); newBuf.advance(countSize);
while (moreComponents(memory, newBuf.getAddress())) { while (moreComponents(memory, newBuf.getAddress())) {
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(baseStruct, newBuf); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(baseStruct, newBuf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress()); Msg.error(this, "ERROR: problem with data at " + newBuf.getAddress());
return null; return null;

View file

@ -102,7 +102,8 @@ public abstract class StructuredDynamicDataType extends DynamicDataType {
MemoryBufferImpl newBuf = new MemoryBufferImpl(memory, buf.getAddress()); MemoryBufferImpl newBuf = new MemoryBufferImpl(memory, buf.getAddress());
try { try {
for (int i = 0; i < components.size(); i++) { for (int i = 0; i < components.size(); i++) {
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(components.get(i), newBuf); DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(components.get(i), newBuf, false);
if (dti == null) { if (dti == null) {
Msg.error(this, "Invalid data at " + newBuf.getAddress()); Msg.error(this, "Invalid data at " + newBuf.getAddress());
return null; return null;

View file

@ -209,6 +209,11 @@ public class TypedefDataType extends GenericDataType implements TypeDef {
return dataType.getLength(); return dataType.getLength();
} }
@Override
public int getAlignedLength() {
return dataType.getAlignedLength();
}
@Override @Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) { public String getRepresentation(MemBuffer buf, Settings settings, int length) {
return dataType.getRepresentation(buf, settings, length); return dataType.getRepresentation(buf, settings, length);

View file

@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.program.model.data; package ghidra.program.model.data.floats;
import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.TreeMap; import java.util.TreeMap;
@ -23,6 +22,7 @@ import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition; import ghidra.docking.settings.SettingsDefinition;
import ghidra.pcode.floatformat.*; import ghidra.pcode.floatformat.*;
import ghidra.pcode.utils.Utils; import ghidra.pcode.utils.Utils;
import ghidra.program.model.data.*;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
/** /**
@ -30,61 +30,99 @@ import ghidra.program.model.mem.MemBuffer;
*/ */
public abstract class AbstractFloatDataType extends BuiltIn { public abstract class AbstractFloatDataType extends BuiltIn {
private final static long serialVersionUID = 1; // TODO: Add FloatDisplayPrecisionSettingsDefinition
private static SettingsDefinition[] SETTINGS_DEFS = {}; private static SettingsDefinition[] SETTINGS_DEFS = {};
public AbstractFloatDataType(String name, DataTypeManager dtm) { private final FloatFormat floatFormat;
super(null, name, dtm); private final int encodedLength;
}
private String description;
/** /**
* * Abstract float datatype constructor
* @see ghidra.program.model.data.DataType#getMnemonic(Settings) * @param name name of the float datatype.
* @param encodedLength the floating encoding length as number of 8-bit bytes.
* @param dtm associated datatype manager which dictates the {@link DataOrganization} to
* be used. This argument may be null to adopt the default data organization.
*/ */
public AbstractFloatDataType(String name, int encodedLength, DataTypeManager dtm) {
super(null, name, dtm);
if (encodedLength < 1) {
throw new IllegalArgumentException("Invalid encoded length: " + encodedLength);
}
this.encodedLength = encodedLength;
FloatFormat format = null;
try {
// Establish float format
format = FloatFormatFactory.getFloatFormat(getLength());
}
catch (UnsupportedFloatFormatException e) {
// ignore
}
floatFormat = format;
}
@Override @Override
public String getMnemonic(Settings settings) { public String getMnemonic(Settings settings) {
return name; return name;
} }
/** protected final String buildIEEE754StandardDescription() {
* StringBuilder buf = new StringBuilder("IEEE 754 floating-point type (");
* @see ghidra.program.model.data.DataType#getDescription() int bitLen = encodedLength * 8;
*/ buf.append(Integer.toString(bitLen));
buf.append("-bit / ");
buf.append(Integer.toString(encodedLength));
buf.append("-byte format, aligned-length is ");
buf.append(Integer.toString(getAlignedLength()));
buf.append("-bytes)");
return buf.toString();
}
protected String buildDescription() {
return buildIEEE754StandardDescription();
}
@Override @Override
public String getDescription() { public final String getDescription() {
return "IEEE-754 Float"; if (description == null) {
description = buildDescription();
}
return description;
}
@Override
public Class<?> getValueClass(Settings settings) {
return BigFloat.class;
} }
/** /**
* Get the encoded length (number of 8-bit bytes) of this float datatype.
* *
* @see ghidra.program.model.data.DataType#getValue(ghidra.program.model.mem.MemBuffer, * @return encoded length of this float datatype.
* ghidra.docking.settings.Settings, int)
*/ */
@Override @Override
public Object getValue(MemBuffer buf, Settings settings, int length) { public final int getLength() {
return encodedLength;
}
@Override
public BigFloat getValue(MemBuffer buf, Settings settings, int length) {
try { try {
int len = getLength(); // use type length (ignore length arg) int len = getLength(); // use type length (ignore length arg)
FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(len); if (floatFormat == null) {
return null;
}
byte[] bytes = new byte[len]; byte[] bytes = new byte[len];
if (buf.getBytes(bytes, 0) != len) { if (buf.getBytes(bytes, 0) != len) {
return null; return null;
} }
if (len <= 8) { if (len <= 8) {
long value = Utils.bytesToLong(bytes, len, buf.isBigEndian()); long value = Utils.bytesToLong(bytes, len, buf.isBigEndian());
double doubleValue = floatFormat.getHostFloat(value); return floatFormat.decodeBigFloat(value);
switch (len) {
case 2:
// TODO: GP-1379
return (short) doubleValue;
case 4:
return (float) doubleValue;
}
return doubleValue;
} }
BigInteger value = Utils.bytesToBigInteger(bytes, len, buf.isBigEndian(), false); BigInteger value = Utils.bytesToBigInteger(bytes, len, buf.isBigEndian(), false);
BigDecimal decValue = floatFormat.round(floatFormat.getHostFloat(value)); return floatFormat.decodeBigFloat(value);
return decValue;
} }
catch (UnsupportedFloatFormatException e) { catch (UnsupportedFloatFormatException e) {
return null; return null;
@ -93,31 +131,25 @@ public abstract class AbstractFloatDataType extends BuiltIn {
@Override @Override
public boolean isEncodable() { public boolean isEncodable() {
int length = getLength(); return floatFormat != null;
return length == 4 || length == 8;
} }
@Override @Override
public byte[] encodeValue(Object value, MemBuffer buf, Settings settings, int length) public byte[] encodeValue(Object value, MemBuffer buf, Settings settings, int length)
throws DataTypeEncodeException { throws DataTypeEncodeException {
// value expected as Number or BigFloat object
try { try {
int len = getLength(); int len = getLength();
if (length != -1 && length != len) { if (floatFormat == null) {
throw new DataTypeEncodeException("Length mismatch", value, this);
}
FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(len);
if (len == 8 || len == 4) {
if (!(value instanceof Number)) {
throw new DataTypeEncodeException( throw new DataTypeEncodeException(
"length-" + len + " float requires Number type", value, this); "Unsupported float format (" + len + " bytes)", value, this);
} }
if ((len == 8 || len == 4) && (value instanceof Number)) {
double doubleValue = ((Number) value).doubleValue(); double doubleValue = ((Number) value).doubleValue();
long encoding = floatFormat.getEncoding(doubleValue); long encoding = floatFormat.getEncoding(doubleValue);
return Utils.longToBytes(encoding, len, buf.isBigEndian()); return Utils.longToBytes(encoding, len, buf.isBigEndian());
} }
if (!(value instanceof BigFloat)) { if (!(value instanceof BigFloat)) {
// TODO: BigFloat really ought to have a valueOf(double) method, or --
// TODO: -- or BigFloat really ought to have a valueOf(BigDecimal) method
throw new DataTypeEncodeException( throw new DataTypeEncodeException(
"non-standard float length requires BigFloat type", value, this); "non-standard float length requires BigFloat type", value, this);
} }
@ -132,17 +164,13 @@ public abstract class AbstractFloatDataType extends BuiltIn {
} }
} }
/**
*
* @see ghidra.program.model.data.DataType#getRepresentation(MemBuffer, Settings, int)
*/
@Override @Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) { public String getRepresentation(MemBuffer buf, Settings settings, int length) {
Object obj = getValue(buf, settings, length); BigFloat value = getValue(buf, settings, length);
if (obj == null) { if (value == null) {
return "??"; return "??";
} }
return obj.toString(); return floatFormat != null ? floatFormat.toDecimalString(value, true) : value.toString();
} }
@Override @Override
@ -150,16 +178,17 @@ public abstract class AbstractFloatDataType extends BuiltIn {
throws DataTypeEncodeException { throws DataTypeEncodeException {
try { try {
int len = getLength(); int len = getLength();
if (length != -1 && length != len) { if (floatFormat == null) {
throw new DataTypeEncodeException("Length mismatch", repr, this); throw new DataTypeEncodeException(
"Unsupported float format (" + len + " bytes)", repr, this);
} }
if (length == 8 || length == 4) { if (length == 8 || length == 4) {
double doubleValue = Double.parseDouble(repr); double doubleValue = Double.parseDouble(repr);
return encodeValue(doubleValue, buf, settings, length); return encodeValue(doubleValue, buf, settings, length);
} }
// TODO: BigFloat ought to have a parse(String) method, or valueOf(BigDecimal) BigFloat bf = floatFormat.getBigFloat(repr);
throw new DataTypeEncodeException( floatFormat.round(bf);
"Cannot yet parse values of non-standard float length", repr, this); return encodeValue(bf, buf, settings, length);
} }
catch (DataTypeEncodeException e) { catch (DataTypeEncodeException e) {
throw e; throw e;
@ -169,9 +198,6 @@ public abstract class AbstractFloatDataType extends BuiltIn {
} }
} }
/**
* @see ghidra.program.model.data.BuiltIn#getBuiltInSettingsDefinitions()
*/
@Override @Override
protected SettingsDefinition[] getBuiltInSettingsDefinitions() { protected SettingsDefinition[] getBuiltInSettingsDefinitions() {
return SETTINGS_DEFS; return SETTINGS_DEFS;
@ -184,6 +210,8 @@ public abstract class AbstractFloatDataType extends BuiltIn {
@Override @Override
public String getCTypeDeclaration(DataOrganization dataOrganization) { public String getCTypeDeclaration(DataOrganization dataOrganization) {
// NOTE: There are a variety of naming conventions for fixed-length floats
// so we will just use our name and rely on user to edit to suit there needs.
return hasLanguageDependantLength() ? null : name; return hasLanguageDependantLength() ? null : name;
} }
@ -196,53 +224,60 @@ public abstract class AbstractFloatDataType extends BuiltIn {
if (floatTypes == null) { if (floatTypes == null) {
// unsupported sizes filled-in with a null // unsupported sizes filled-in with a null
floatTypes = new TreeMap<Integer, AbstractFloatDataType>(); floatTypes = new TreeMap<Integer, AbstractFloatDataType>();
floatTypes.put(2, Float2DataType.dataType); floatTypes.put(Float16DataType.dataType.getLength(), Float16DataType.dataType);
floatTypes.put(4, Float4DataType.dataType); floatTypes.put(Float32DataType.dataType.getLength(), Float32DataType.dataType);
floatTypes.put(8, Float8DataType.dataType); floatTypes.put(Float64DataType.dataType.getLength(), Float64DataType.dataType);
floatTypes.put(10, Float10DataType.dataType); floatTypes.put(Float80DataType.dataType.getLength(), Float80DataType.dataType);
floatTypes.put(16, Float16DataType.dataType); floatTypes.put(Float128DataType.dataType.getLength(), Float128DataType.dataType);
} }
return floatTypes; return floatTypes;
} }
/** /**
* Get a Float data-type instance of the requested size * Get a Float data-type instance with the requested raw format size in bytes. It is important that the
* "raw" format size is specified since the {@link DataType#getAlignedLength() aligned-length}
* used by compilers (e.g., {@code sizeof()}) may be larger and duplicated across different
* float formats. Example: an 80-bit (10-byte) float may have an aligned-length of 12 or 16-bytes
* based upon alignment requirements of a given compiler. This can result in multiple float
* types having the same aligned-length.
* *
* @param size data type size, unsupported sizes will cause an undefined type to be returned. * @param rawFormatByteSize raw float format size, unsupported sizes will cause an undefined
* type to be returned.
* @param dtm optional program data-type manager, if specified a generic data-type will be * @param dtm optional program data-type manager, if specified a generic data-type will be
* returned if possible (i.e., float, double, long double). * returned if possible (i.e., float, double, long double).
* @return float data type of specified size * @return float data type of specified size
*/ */
public static DataType getFloatDataType(int size, DataTypeManager dtm) { public static DataType getFloatDataType(int rawFormatByteSize, DataTypeManager dtm) {
if (size < 1) { if (rawFormatByteSize < 1) {
return DefaultDataType.dataType; return DefaultDataType.dataType;
} }
if (dtm != null) { if (dtm != null) {
DataOrganization dataOrganization = dtm.getDataOrganization(); DataOrganization dataOrganization = dtm.getDataOrganization();
if (dataOrganization != null) { if (dataOrganization != null) {
if (size == dataOrganization.getFloatSize()) { if (rawFormatByteSize == dataOrganization.getFloatSize()) {
return FloatDataType.dataType.clone(dtm); return FloatDataType.dataType.clone(dtm);
} }
if (size == dataOrganization.getDoubleSize()) { if (rawFormatByteSize == dataOrganization.getDoubleSize()) {
return DoubleDataType.dataType.clone(dtm); return DoubleDataType.dataType.clone(dtm);
} }
if (size == dataOrganization.getLongDoubleSize()) { if (rawFormatByteSize == dataOrganization.getLongDoubleSize()) {
return LongDoubleDataType.dataType.clone(dtm); return LongDoubleDataType.dataType.clone(dtm);
} }
} }
} }
DataType dt = getFloatTypes().get(size); DataType dt = getFloatTypes().get(rawFormatByteSize);
if (dt == null) { if (dt == null) {
return Undefined.getUndefinedDataType(size); return Undefined.getUndefinedDataType(rawFormatByteSize);
} }
return dt; return dt;
} }
/** /**
* Returns all built-in float data-types * Returns all built-in floating-point data types
* *
* @param dtm optional program data-type manager, if specified generic data-types will be * @param dtm optional program data-type manager, if specified generic data-types will be
* returned in place of fixed-sized data-types. * returned in place of fixed-sized data-types.
* @return array of floating-point data types
*/ */
public static AbstractFloatDataType[] getFloatDataTypes(DataTypeManager dtm) { public static AbstractFloatDataType[] getFloatDataTypes(DataTypeManager dtm) {
TreeMap<Integer, AbstractFloatDataType> floatMap = getFloatTypes(); TreeMap<Integer, AbstractFloatDataType> floatMap = getFloatTypes();

View file

@ -0,0 +1,48 @@
/* ###
* 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.floats;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.classfinder.ClassTranslator;
public class Float128DataType extends AbstractFloatDataType {
static {
// remap old byte-sized float to this bit-sized equivalent
ClassTranslator.put(
"ghidra.program.model.data.Float16DataType", Float128DataType.class.getName());
}
public static final Float128DataType dataType = new Float128DataType();
public Float128DataType() {
this(null);
}
public Float128DataType(DataTypeManager dtm) {
super("float128", 16, dtm);
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
}
return new Float128DataType(dtm);
}
}

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* 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.
@ -14,10 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.program.model.data; package ghidra.program.model.data.floats;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.classfinder.ClassTranslator;
public class Float16DataType extends AbstractFloatDataType { public class Float16DataType extends AbstractFloatDataType {
static {
// remap old byte-sized float to this bit-sized equivalent
ClassTranslator.put(
"ghidra.program.model.data.Float2DataType", Float16DataType.class.getName());
}
public static final Float16DataType dataType = new Float16DataType(); public static final Float16DataType dataType = new Float16DataType();
public Float16DataType() { public Float16DataType() {
@ -25,7 +34,7 @@ public class Float16DataType extends AbstractFloatDataType {
} }
public Float16DataType(DataTypeManager dtm) { public Float16DataType(DataTypeManager dtm) {
super("float16", dtm); super("float16", 2, dtm);
} }
@Override @Override
@ -36,9 +45,4 @@ public class Float16DataType extends AbstractFloatDataType {
return new Float16DataType(dtm); return new Float16DataType(dtm);
} }
@Override
public int getLength() {
return 16;
}
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* 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.
@ -14,18 +13,28 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.program.model.data; package ghidra.program.model.data.floats;
public class Float10DataType extends AbstractFloatDataType { import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.classfinder.ClassTranslator;
public static final Float10DataType dataType = new Float10DataType(); public class Float32DataType extends AbstractFloatDataType {
public Float10DataType() { static {
// remap old byte-sized float to this bit-sized equivalent
ClassTranslator.put(
"ghidra.program.model.data.Float4DataType", Float32DataType.class.getName());
}
public static final Float32DataType dataType = new Float32DataType();
public Float32DataType() {
this(null); this(null);
} }
public Float10DataType(DataTypeManager dtm) { public Float32DataType(DataTypeManager dtm) {
super("float10", dtm); super("float32", 4, dtm);
} }
@Override @Override
@ -33,12 +42,7 @@ public class Float10DataType extends AbstractFloatDataType {
if (dtm == getDataTypeManager()) { if (dtm == getDataTypeManager()) {
return this; return this;
} }
return new Float10DataType(dtm); return new Float32DataType(dtm);
}
@Override
public int getLength() {
return 10;
} }
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* 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.
@ -14,18 +13,28 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package ghidra.program.model.data; package ghidra.program.model.data.floats;
public class Float2DataType extends AbstractFloatDataType { import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.classfinder.ClassTranslator;
public static final Float2DataType dataType = new Float2DataType(); public class Float64DataType extends AbstractFloatDataType {
public Float2DataType() { static {
// remap old byte-sized float to this bit-sized equivalent
ClassTranslator.put(
"ghidra.program.model.data.Float8DataType", Float64DataType.class.getName());
}
public static final Float64DataType dataType = new Float64DataType();
public Float64DataType() {
this(null); this(null);
} }
public Float2DataType(DataTypeManager dtm) { public Float64DataType(DataTypeManager dtm) {
super("float2", dtm); super("float64", 8, dtm);
} }
@Override @Override
@ -33,12 +42,7 @@ public class Float2DataType extends AbstractFloatDataType {
if (dtm == getDataTypeManager()) { if (dtm == getDataTypeManager()) {
return this; return this;
} }
return new Float2DataType(dtm); return new Float64DataType(dtm);
}
@Override
public int getLength() {
return 2;
} }
} }

Some files were not shown because too many files have changed in this diff Show more