Merge remote-tracking branch 'origin/GP-3190_dev747368_remove_numberutils'

This commit is contained in:
Ryan Kurtz 2023-03-22 11:25:08 -04:00
commit 3da82f9ff9
7 changed files with 89 additions and 230 deletions

View file

@ -29,7 +29,6 @@ import ghidra.app.util.bin.format.dwarf4.encoding.*;
import ghidra.app.util.bin.format.dwarf4.expression.*; import ghidra.app.util.bin.format.dwarf4.expression.*;
import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram; import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.NumberUtil;
/** /**
* DIEAggregate groups related {@link DebugInfoEntry} records together in a single interface * DIEAggregate groups related {@link DebugInfoEntry} records together in a single interface
@ -487,14 +486,13 @@ public class DIEAggregate {
} }
DWARFAttributeValue attr = attrInfo.attr; DWARFAttributeValue attr = attrInfo.attr;
if (attr instanceof DWARFNumericAttribute) { if (attr instanceof DWARFNumericAttribute dnum) {
return assertValidInt(((DWARFNumericAttribute) attr).getValue()); return assertValidInt(dnum.getValue());
} }
else if (attr instanceof DWARFBlobAttribute) { else if (attr instanceof DWARFBlobAttribute dblob) {
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes(); byte[] exprBytes = dblob.getBytes();
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment()); DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression expr = DWARFExpression expr = evaluator.readExpr(exprBytes);
evaluator.readExpr(exprBytes);
evaluator.evaluate(expr, 0); evaluator.evaluate(expr, 0);
return assertValidInt(evaluator.pop()); return assertValidInt(evaluator.pop());
@ -523,11 +521,11 @@ public class DIEAggregate {
} }
DWARFAttributeValue attr = attrInfo.attr; DWARFAttributeValue attr = attrInfo.attr;
if (attr instanceof DWARFNumericAttribute) { if (attr instanceof DWARFNumericAttribute dnum) {
return ((DWARFNumericAttribute) attr).getUnsignedValue(); return dnum.getUnsignedValue();
} }
else if (attr instanceof DWARFBlobAttribute) { else if (attr instanceof DWARFBlobAttribute dblob) {
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes(); byte[] exprBytes = dblob.getBytes();
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment()); DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
DWARFExpression expr = evaluator.readExpr(exprBytes); DWARFExpression expr = evaluator.readExpr(exprBytes);
@ -573,14 +571,13 @@ public class DIEAggregate {
} }
DWARFAttributeValue attr = attrInfo.attr; DWARFAttributeValue attr = attrInfo.attr;
if (attr instanceof DWARFNumericAttribute) { if (attr instanceof DWARFNumericAttribute dnum) {
return assertValidUInt(((DWARFNumericAttribute) attr).getUnsignedValue()); return assertValidUInt(dnum.getUnsignedValue());
} }
else if (attr instanceof DWARFBlobAttribute) { else if (attr instanceof DWARFBlobAttribute dblob) {
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes(); byte[] exprBytes = dblob.getBytes();
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment()); DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression expr = DWARFExpression expr = evaluator.readExpr(exprBytes);
evaluator.readExpr(exprBytes);
// DW_AT_data_member_location expects the address of the containing object // DW_AT_data_member_location expects the address of the containing object
// to be on the stack before evaluation starts. We don't have that so we // to be on the stack before evaluation starts. We don't have that so we
@ -609,13 +606,13 @@ public class DIEAggregate {
public List<DWARFLocation> getAsLocation(int attribute) throws IOException { public List<DWARFLocation> getAsLocation(int attribute) throws IOException {
AttrInfo attrInfo = findAttribute(attribute); AttrInfo attrInfo = findAttribute(attribute);
if (attrInfo == null) { if (attrInfo == null) {
return Collections.EMPTY_LIST; return List.of();
} }
else if (attrInfo.attr instanceof DWARFNumericAttribute) { else if (attrInfo.attr instanceof DWARFNumericAttribute dnum) {
return readDebugLocList(((DWARFNumericAttribute) attrInfo.attr).getUnsignedValue()); return readDebugLocList(dnum.getUnsignedValue());
} }
else if (attrInfo.attr instanceof DWARFBlobAttribute) { else if (attrInfo.attr instanceof DWARFBlobAttribute dblob) {
return _exprBytesAsLocation((DWARFBlobAttribute) attrInfo.attr); return _exprBytesAsLocation(dblob);
} }
else { else {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
@ -643,6 +640,10 @@ public class DIEAggregate {
/** /**
* Return a list of DWARF locations read from the debug_loc section. * Return a list of DWARF locations read from the debug_loc section.
* <p>
* The deserialization done here is very similar to {@link #parseDebugRange(int)}, but in this
* case also contains a blob payload per location.
*
* @param offset offset into the debug_loc section * @param offset offset into the debug_loc section
* @return list of DWARF locations (address range and location expression) * @return list of DWARF locations (address range and location expression)
* @throws IOException if an I/O error occurs * @throws IOException if an I/O error occurs
@ -650,9 +651,9 @@ public class DIEAggregate {
private List<DWARFLocation> readDebugLocList(long offset) throws IOException { private List<DWARFLocation> readDebugLocList(long offset) throws IOException {
BinaryReader debug_loc = getCompilationUnit().getProgram().getDebugLocation(); BinaryReader debug_loc = getCompilationUnit().getProgram().getDebugLocation();
List<DWARFLocation> ranges = new ArrayList<>(); List<DWARFLocation> results = new ArrayList<>();
if (debug_loc == null) { if (debug_loc == null) {
return ranges; return results;
} }
debug_loc.setPointerIndex(offset); debug_loc.setPointerIndex(offset);
@ -666,22 +667,22 @@ public class DIEAggregate {
// Loop through the debug_loc entry // Loop through the debug_loc entry
while (debug_loc.getPointerIndex() < debug_loc.length()) { while (debug_loc.getPointerIndex() < debug_loc.length()) {
Number beginning = DWARFUtil.readAddress(debug_loc, pointerSize); long beginning = DWARFUtil.readAddressAsLong(debug_loc, pointerSize);
Number ending = DWARFUtil.readAddress(debug_loc, pointerSize); long ending = DWARFUtil.readAddressAsLong(debug_loc, pointerSize);
// List end // List end
if (beginning.longValue() == 0 && ending.longValue() == 0) { if (beginning == 0 && ending == 0) {
break; break;
} }
// Check to see if this is a base address entry // Check to see if this is a base address entry
if (NumberUtil.equalsMaxUnsignedValue(beginning)) { if (beginning == -1) {
baseAddressOffset = ending.longValue(); baseAddressOffset = ending;
continue; continue;
} }
// Size is 2 bytes // Size is 2 bytes
int size = debug_loc.readNextShort() & NumberUtil.UNSIGNED_SHORT_MASK; int size = debug_loc.readNextUnsignedShort();
// Read the location description // Read the location description
byte[] location = debug_loc.readNextByteArray(size); byte[] location = debug_loc.readNextByteArray(size);
@ -690,19 +691,19 @@ public class DIEAggregate {
// greater-than the compunit's lowpc. This indicates the 'offset' isn't // greater-than the compunit's lowpc. This indicates the 'offset' isn't
// an offset, but already an absolute value. This occurs in some // an offset, but already an absolute value. This occurs in some
// gcc dwarf compilation flag combinations. // gcc dwarf compilation flag combinations.
boolean isBadOffset = (beginning.longValue() > cuBase); boolean isBadOffset = (beginning > cuBase);
long absStart = beginning.longValue(); long absStart = beginning;
long absEnd = ending.longValue(); long absEnd = ending;
if (!isBadOffset) { if (!isBadOffset) {
absStart += baseAddressOffset; absStart += baseAddressOffset;
absEnd += baseAddressOffset; absEnd += baseAddressOffset;
} }
// TODO: verify end addr calc with DWARFstd.pdf, inclusive vs exclusive // TODO: verify end addr calc with DWARFstd.pdf, inclusive vs exclusive
ranges.add(new DWARFLocation(new DWARFRange(absStart, absEnd + 1), location)); results.add(new DWARFLocation(new DWARFRange(absStart, absEnd + 1), location));
} }
return ranges; return results;
} }
private List<DWARFLocation> _exprBytesAsLocation(DWARFBlobAttribute attr) { private List<DWARFLocation> _exprBytesAsLocation(DWARFBlobAttribute attr) {
@ -844,30 +845,29 @@ public class DIEAggregate {
reader.setPointerIndex(offset); reader.setPointerIndex(offset);
List<DWARFRange> ranges = new ArrayList<>(); List<DWARFRange> ranges = new ArrayList<>();
long baseAddress = getCompilationUnit().getCompileUnit() != null && DWARFCompileUnit dcu = getCompilationUnit().getCompileUnit();
getCompilationUnit().getCompileUnit().getLowPC() != null long baseAddress = dcu != null && dcu.getLowPC() != null
? getCompilationUnit().getCompileUnit().getLowPC().longValue() ? dcu.getLowPC().longValue()
: 0L; : 0L;
while (reader.hasNext()) { while (reader.hasNext()) {
// Read the beginning and ending addresses // Read the beginning and ending addresses
Number beginning = DWARFUtil.readAddress(reader, pointerSize); long beginning = DWARFUtil.readAddressAsLong(reader, pointerSize);
Number ending = DWARFUtil.readAddress(reader, pointerSize); // dwarf end addrs are exclusive long ending = DWARFUtil.readAddressAsLong(reader, pointerSize); // dwarf end addrs are exclusive
// End of the list // End of the list
if (beginning.longValue() == 0 && ending.longValue() == 0) { if (beginning == 0 && ending == 0) {
break; break;
} }
// Check to see if this is a base address entry // Check to see if this is a base address entry
if (NumberUtil.equalsMaxUnsignedValue(beginning)) { if (beginning == -1) {
baseAddress = ending.longValue(); baseAddress = ending;
continue; continue;
} }
// Add the range to the list // Add the range to the list
ranges.add(new DWARFRange(baseAddress + beginning.longValue(), ranges.add(new DWARFRange(baseAddress + beginning, baseAddress + ending));
baseAddress + ending.longValue()));
} }
Collections.sort(ranges); Collections.sort(ranges);
return ranges; return ranges;
@ -896,9 +896,7 @@ public class DIEAggregate {
*/ */
public long getHighPC() throws IOException { public long getHighPC() throws IOException {
AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc); AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc);
if (high != null && high.attr instanceof DWARFNumericAttribute) { if (high != null && high.attr instanceof DWARFNumericAttribute highVal) {
DWARFNumericAttribute highVal = (DWARFNumericAttribute) high.attr;
// if the DWARF attr was a DW_FORM_addr, it doesn't need fixing up // if the DWARF attr was a DW_FORM_addr, it doesn't need fixing up
if (high.form == DWARFForm.DW_FORM_addr) { if (high.form == DWARFForm.DW_FORM_addr) {
return highVal.getUnsignedValue() + getProgram().getProgramBaseAddressFixup() - 1; return highVal.getUnsignedValue() + getProgram().getProgramBaseAddressFixup() - 1;
@ -935,11 +933,11 @@ public class DIEAggregate {
AttrInfo low = findAttribute(DWARFAttribute.DW_AT_low_pc); AttrInfo low = findAttribute(DWARFAttribute.DW_AT_low_pc);
AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc); AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc);
if (low != null && high != null && low.form == high.form && if (low != null && high != null && low.form == high.form &&
low.attr instanceof DWARFNumericAttribute && low.attr instanceof DWARFNumericAttribute lowVal &&
high.attr instanceof DWARFNumericAttribute) { high.attr instanceof DWARFNumericAttribute highVal) {
DWARFNumericAttribute lowVal = (DWARFNumericAttribute) low.attr;
DWARFNumericAttribute highVal = (DWARFNumericAttribute) high.attr;
return lowVal.getValue() == highVal.getValue(); return lowVal.getValue() == highVal.getValue();
} }
return false; return false;
} }

View file

@ -519,29 +519,6 @@ public class DWARFUtil {
throw new IOException("Unsupported variable-sized int: " + size); throw new IOException("Unsupported variable-sized int: " + size);
} }
/**
* Read the value of an address.
* @param reader BinaryReader pointing to the value to read
* @param pointerSize the size of a pointer
* @return the address value
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if an unknown pointer size is given
*/
public static Number readAddress(BinaryReader reader, byte pointerSize) throws IOException {
switch (pointerSize) {
case 1:
return Byte.valueOf(reader.readNextByte());
case 2:
return Short.valueOf(reader.readNextShort());
case 4:
return Integer.valueOf(reader.readNextInt());
case 8:
return Long.valueOf(reader.readNextLong());
}
throw new IllegalArgumentException(
"Unknown pointer size: 0x" + Integer.toHexString(pointerSize));
}
/** /**
* Reads a variable-sized unsigned 'address' value from a {@link BinaryReader} and * Reads a variable-sized unsigned 'address' value from a {@link BinaryReader} and
* returns it as a 64 bit java long. * returns it as a 64 bit java long.
@ -588,8 +565,9 @@ public class DWARFUtil {
DWARFAttributeValue dwATObjectPointer = DWARFAttributeValue dwATObjectPointer =
paramDIEA.getParent().getAttribute(DWARFAttribute.DW_AT_object_pointer); paramDIEA.getParent().getAttribute(DWARFAttribute.DW_AT_object_pointer);
return dwATObjectPointer != null && dwATObjectPointer instanceof DWARFNumericAttribute && return dwATObjectPointer != null &&
paramDIEA.hasOffset(((DWARFNumericAttribute) dwATObjectPointer).getUnsignedValue()); dwATObjectPointer instanceof DWARFNumericAttribute dnum &&
paramDIEA.hasOffset(dnum.getUnsignedValue());
} }
/** /**

View file

@ -1,49 +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.util.bin.format.dwarf4.attribs;
/**
* Stores a integer value (with ambiguous signedness) in a long, with a mask that will
* allow the consumer at a later time to treat the value as signed or unsigned.
* <p>
* When supplied with a long value that was originally a smaller integer with its high-bit
* set, java will sign-extend the value to 64 bits. To treat this as an unsigned
* value, the mask needs to match the bitwidth of the supplied value, and is used to return
* the relevant number of bits from the value. (See NumberUtil.UNSIGNED_BYTE_MASK, etc)
* <p>
* This allows us to simplify the storage of a variable sized int value
* (1 byte, 2 byte, 4 byte, 8 byte) using just a 8 byte long and an 8 byte mask.
*/
public class DWARFAmbigNumericAttribute extends DWARFNumericAttribute {
private final long mask;
public DWARFAmbigNumericAttribute(long value, long mask) {
super(value);
this.mask = mask;
}
@Override
public long getUnsignedValue() {
return value & mask;
}
@Override
public String toString() {
return String.format("DWARFAmbigNumericAttribute: natural=%d [%08x], unsigned=%s [%08x]",
value, value, Long.toUnsignedString(getUnsignedValue()), getUnsignedValue());
}
}

View file

@ -24,7 +24,6 @@ import ghidra.app.util.bin.format.dwarf4.encoding.DWARFForm;
import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram; import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram;
import ghidra.app.util.bin.format.dwarf4.next.StringTable; import ghidra.app.util.bin.format.dwarf4.next.StringTable;
import ghidra.program.model.data.LEB128; import ghidra.program.model.data.LEB128;
import ghidra.util.NumberUtil;
/** /**
* A factory for deserializing {@link DWARFAttributeValue dwarf attribute} from * A factory for deserializing {@link DWARFAttributeValue dwarf attribute} from
@ -57,21 +56,21 @@ public class DWARFAttributeFactory {
switch (form) { switch (form) {
case DW_FORM_addr: case DW_FORM_addr:
return new DWARFNumericAttribute( return new DWARFNumericAttribute(
DWARFUtil.readVarSizedULong(reader, unit.getPointerSize())); reader.readNextUnsignedValue(unit.getPointerSize()));
case DW_FORM_ref1: { case DW_FORM_ref1: {
long uoffset = DWARFUtil.readVarSizedULong(reader, 1); long uoffset = reader.readNextUnsignedValue(1);
return new DWARFNumericAttribute(uoffset + unit.getStartOffset()); return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
} }
case DW_FORM_ref2: { case DW_FORM_ref2: {
long uoffset = DWARFUtil.readVarSizedULong(reader, 2); long uoffset = reader.readNextUnsignedValue(2);
return new DWARFNumericAttribute(uoffset + unit.getStartOffset()); return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
} }
case DW_FORM_ref4: { case DW_FORM_ref4: {
long uoffset = DWARFUtil.readVarSizedULong(reader, 4); long uoffset = reader.readNextUnsignedValue(4);
return new DWARFNumericAttribute(uoffset + unit.getStartOffset()); return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
} }
case DW_FORM_ref8: { case DW_FORM_ref8: {
long uoffset = DWARFUtil.readVarSizedULong(reader, 8); long uoffset = reader.readNextUnsignedValue(8);
return new DWARFNumericAttribute(uoffset + unit.getStartOffset()); return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
} }
case DW_FORM_ref_udata: { case DW_FORM_ref_udata: {
@ -112,20 +111,17 @@ public class DWARFAttributeFactory {
return new DWARFBlobAttribute(reader.readNextByteArray(length)); return new DWARFBlobAttribute(reader.readNextByteArray(length));
} }
case DW_FORM_data1: case DW_FORM_data1:
return new DWARFAmbigNumericAttribute(reader.readNextByte(), return new DWARFNumericAttribute(8, reader.readNextByte(), true);
NumberUtil.UNSIGNED_BYTE_MASK);
case DW_FORM_data2: case DW_FORM_data2:
return new DWARFAmbigNumericAttribute(reader.readNextShort(), return new DWARFNumericAttribute(16, reader.readNextShort(), true);
NumberUtil.UNSIGNED_SHORT_MASK);
case DW_FORM_data4: case DW_FORM_data4:
return new DWARFAmbigNumericAttribute(reader.readNextInt(), return new DWARFNumericAttribute(32, reader.readNextInt(), true);
NumberUtil.UNSIGNED_INT_MASK);
case DW_FORM_data8: case DW_FORM_data8:
return new DWARFNumericAttribute(reader.readNextLong()); return new DWARFNumericAttribute(64, reader.readNextLong(), true);
case DW_FORM_sdata: case DW_FORM_sdata:
return new DWARFNumericAttribute(reader.readNext(LEB128::signed)); return new DWARFNumericAttribute(64, reader.readNext(LEB128::signed), true);
case DW_FORM_udata: case DW_FORM_udata:
return new DWARFNumericAttribute(reader.readNext(LEB128::unsigned)); return new DWARFNumericAttribute(64, reader.readNext(LEB128::unsigned), false);
case DW_FORM_exprloc: { case DW_FORM_exprloc: {
int length = reader.readNextUnsignedVarIntExact(LEB128::unsigned); int length = reader.readNextUnsignedVarIntExact(LEB128::unsigned);

View file

@ -15,32 +15,35 @@
*/ */
package ghidra.app.util.bin.format.dwarf4.attribs; package ghidra.app.util.bin.format.dwarf4.attribs;
import ghidra.program.model.scalar.Scalar;
/** /**
* DWARF numeric attribute. * DWARF numeric attribute.
* <p>
* Use this class instead of {@link DWARFAmbigNumericAttribute} when the signed-ness
* of the raw value is known when deserializing the attribute from a stream.
* <p>
* Use {@link DWARFAmbigNumericAttribute} when the signed-ness of the raw value is only know
* to the code that is using the attribute value.
*/ */
public class DWARFNumericAttribute implements DWARFAttributeValue { public class DWARFNumericAttribute extends Scalar implements DWARFAttributeValue {
protected final long value;
/**
* Creates a new numeric value, using 64 bits and marked as signed
*
* @param value long 64 bit value
*/
public DWARFNumericAttribute(long value) { public DWARFNumericAttribute(long value) {
this.value = value; this(64, value, true);
} }
public long getValue() { /**
return value; * Creates a new numeric value, using the specific bitLength and value.
} *
* @param bitLength number of bits, valid values are 1..64, or 0 if value is also 0
public long getUnsignedValue() { * @param value value of the scalar, any bits that are set above bitLength will be ignored
return value; * @param signed true for a signed value, false for an unsigned value.
*/
public DWARFNumericAttribute(int bitLength, long value, boolean signed) {
super(bitLength, value, signed);
} }
@Override @Override
public String toString() { public String toString() {
return String.format("DWARFNumericAttribute: %d [%08x]", value, value); return String.format("DWARFNumericAttribute: %d [%08x]", getValue(), getValue());
} }
} }

View file

@ -24,7 +24,7 @@ import java.io.IOException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import ghidra.util.NumberUtil; import ghidra.util.NumericUtilities;
public class BinaryReaderTest { public class BinaryReaderTest {
@ -149,8 +149,7 @@ public class BinaryReaderTest {
assertEquals(1, br.readUnsignedShort(0)); assertEquals(1, br.readUnsignedShort(0));
assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readUnsignedShort(2)); assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readUnsignedShort(2));
assertEquals(NumberUtil.UNSIGNED_SHORT_MASK /* ie. UNSIGNED_SHORT_MAX, 0xffff*/, assertEquals(0xffff, br.readUnsignedShort(4));
br.readUnsignedShort(4));
assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readUnsignedShort(6)); assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readUnsignedShort(6));
try { try {
br.readUnsignedShort(8); br.readUnsignedShort(8);
@ -184,8 +183,7 @@ public class BinaryReaderTest {
assertEquals(1, br.readNextUnsignedShort()); assertEquals(1, br.readNextUnsignedShort());
assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readNextUnsignedShort()); assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readNextUnsignedShort());
assertEquals(NumberUtil.UNSIGNED_SHORT_MASK /* ie. UNSIGNED_SHORT_MAX, 0xffff*/, assertEquals(0xffff, br.readNextUnsignedShort());
br.readNextUnsignedShort());
assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readNextUnsignedShort()); assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readNextUnsignedShort());
try { try {
br.readNextUnsignedShort(); br.readNextUnsignedShort();
@ -225,8 +223,7 @@ public class BinaryReaderTest {
assertEquals(1, br.readUnsignedInt(0)); assertEquals(1, br.readUnsignedInt(0));
assertEquals(Integer.MAX_VALUE, br.readUnsignedInt(4)); assertEquals(Integer.MAX_VALUE, br.readUnsignedInt(4));
assertEquals(NumberUtil.UNSIGNED_INT_MASK /*ie. UNSIGNED_INT_MAX, 0xff_ff_ff_ff*/, assertEquals(NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG, br.readUnsignedInt(8));
br.readUnsignedInt(8));
assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readUnsignedInt(12)); assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readUnsignedInt(12));
try { try {
br.readUnsignedInt(16); br.readUnsignedInt(16);
@ -262,8 +259,7 @@ public class BinaryReaderTest {
assertEquals(1, br.readNextUnsignedInt()); assertEquals(1, br.readNextUnsignedInt());
assertEquals(Integer.MAX_VALUE, br.readNextUnsignedInt()); assertEquals(Integer.MAX_VALUE, br.readNextUnsignedInt());
assertEquals(NumberUtil.UNSIGNED_INT_MASK /*ie. UNSIGNED_INT_MAX, 0xff_ff_ff_ff*/, assertEquals(NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG, br.readNextUnsignedInt());
br.readNextUnsignedInt());
assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readNextUnsignedInt()); assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readNextUnsignedInt());
try { try {
br.readNextUnsignedInt(); br.readNextUnsignedInt();

View file

@ -1,63 +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.util;
public class NumberUtil {
public static final int UNSIGNED_BYTE_MASK = 0xff;
public static final int UNSIGNED_SHORT_MASK = 0xffff;
public static final long UNSIGNED_INT_MASK = 0xffffffffL;
//public static final long UNSIGNED_LONG_MASK = 0xffffffffffffffffL;
/**
* Get the unsigned value of a number.
* @param value the value stored in a signed number
* @return the unsigned value of the number
*/
public static Number getUnsignedValue(Number value) {
if (value instanceof Byte) {
return value.byteValue() & UNSIGNED_BYTE_MASK;
}
else if (value instanceof Short) {
return value.shortValue() & UNSIGNED_SHORT_MASK;
}
else if (value instanceof Integer) {
return value.intValue() & UNSIGNED_INT_MASK;
}
else if (value instanceof Long) {
// TODO: Is this valid?
if (value.longValue() < 0) {
return value.longValue() & 0xffffffffffffffffL;
}
return value;
}
throw new UnsupportedOperationException("Number instance not handled!");
}
/**
* Compare to the maximum unsigned value that the current number is holding.
* @param value the value stored in a signed number
* @return true if equal to the maximum and false otherwise
*/
public static boolean equalsMaxUnsignedValue(Number value) {
// All number types should be the max when equal to signed value -1 in two's complement
if (value.longValue() == -1) {
return true;
}
return false;
}
}