mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-3190_dev747368_remove_numberutils'
This commit is contained in:
commit
3da82f9ff9
7 changed files with 89 additions and 230 deletions
|
@ -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.next.DWARFProgram;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.NumberUtil;
|
||||
|
||||
/**
|
||||
* DIEAggregate groups related {@link DebugInfoEntry} records together in a single interface
|
||||
|
@ -487,14 +486,13 @@ public class DIEAggregate {
|
|||
}
|
||||
|
||||
DWARFAttributeValue attr = attrInfo.attr;
|
||||
if (attr instanceof DWARFNumericAttribute) {
|
||||
return assertValidInt(((DWARFNumericAttribute) attr).getValue());
|
||||
if (attr instanceof DWARFNumericAttribute dnum) {
|
||||
return assertValidInt(dnum.getValue());
|
||||
}
|
||||
else if (attr instanceof DWARFBlobAttribute) {
|
||||
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes();
|
||||
else if (attr instanceof DWARFBlobAttribute dblob) {
|
||||
byte[] exprBytes = dblob.getBytes();
|
||||
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
|
||||
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression expr =
|
||||
evaluator.readExpr(exprBytes);
|
||||
DWARFExpression expr = evaluator.readExpr(exprBytes);
|
||||
|
||||
evaluator.evaluate(expr, 0);
|
||||
return assertValidInt(evaluator.pop());
|
||||
|
@ -523,11 +521,11 @@ public class DIEAggregate {
|
|||
}
|
||||
|
||||
DWARFAttributeValue attr = attrInfo.attr;
|
||||
if (attr instanceof DWARFNumericAttribute) {
|
||||
return ((DWARFNumericAttribute) attr).getUnsignedValue();
|
||||
if (attr instanceof DWARFNumericAttribute dnum) {
|
||||
return dnum.getUnsignedValue();
|
||||
}
|
||||
else if (attr instanceof DWARFBlobAttribute) {
|
||||
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes();
|
||||
else if (attr instanceof DWARFBlobAttribute dblob) {
|
||||
byte[] exprBytes = dblob.getBytes();
|
||||
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
|
||||
DWARFExpression expr = evaluator.readExpr(exprBytes);
|
||||
|
||||
|
@ -573,14 +571,13 @@ public class DIEAggregate {
|
|||
}
|
||||
|
||||
DWARFAttributeValue attr = attrInfo.attr;
|
||||
if (attr instanceof DWARFNumericAttribute) {
|
||||
return assertValidUInt(((DWARFNumericAttribute) attr).getUnsignedValue());
|
||||
if (attr instanceof DWARFNumericAttribute dnum) {
|
||||
return assertValidUInt(dnum.getUnsignedValue());
|
||||
}
|
||||
else if (attr instanceof DWARFBlobAttribute) {
|
||||
byte[] exprBytes = ((DWARFBlobAttribute) attr).getBytes();
|
||||
else if (attr instanceof DWARFBlobAttribute dblob) {
|
||||
byte[] exprBytes = dblob.getBytes();
|
||||
DWARFExpressionEvaluator evaluator = DWARFExpressionEvaluator.create(getHeadFragment());
|
||||
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression expr =
|
||||
evaluator.readExpr(exprBytes);
|
||||
DWARFExpression expr = evaluator.readExpr(exprBytes);
|
||||
|
||||
// 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
|
||||
|
@ -609,13 +606,13 @@ public class DIEAggregate {
|
|||
public List<DWARFLocation> getAsLocation(int attribute) throws IOException {
|
||||
AttrInfo attrInfo = findAttribute(attribute);
|
||||
if (attrInfo == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
return List.of();
|
||||
}
|
||||
else if (attrInfo.attr instanceof DWARFNumericAttribute) {
|
||||
return readDebugLocList(((DWARFNumericAttribute) attrInfo.attr).getUnsignedValue());
|
||||
else if (attrInfo.attr instanceof DWARFNumericAttribute dnum) {
|
||||
return readDebugLocList(dnum.getUnsignedValue());
|
||||
}
|
||||
else if (attrInfo.attr instanceof DWARFBlobAttribute) {
|
||||
return _exprBytesAsLocation((DWARFBlobAttribute) attrInfo.attr);
|
||||
else if (attrInfo.attr instanceof DWARFBlobAttribute dblob) {
|
||||
return _exprBytesAsLocation(dblob);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(
|
||||
|
@ -643,6 +640,10 @@ public class DIEAggregate {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* @return list of DWARF locations (address range and location expression)
|
||||
* @throws IOException if an I/O error occurs
|
||||
|
@ -650,9 +651,9 @@ public class DIEAggregate {
|
|||
private List<DWARFLocation> readDebugLocList(long offset) throws IOException {
|
||||
BinaryReader debug_loc = getCompilationUnit().getProgram().getDebugLocation();
|
||||
|
||||
List<DWARFLocation> ranges = new ArrayList<>();
|
||||
List<DWARFLocation> results = new ArrayList<>();
|
||||
if (debug_loc == null) {
|
||||
return ranges;
|
||||
return results;
|
||||
}
|
||||
|
||||
debug_loc.setPointerIndex(offset);
|
||||
|
@ -666,22 +667,22 @@ public class DIEAggregate {
|
|||
|
||||
// Loop through the debug_loc entry
|
||||
while (debug_loc.getPointerIndex() < debug_loc.length()) {
|
||||
Number beginning = DWARFUtil.readAddress(debug_loc, pointerSize);
|
||||
Number ending = DWARFUtil.readAddress(debug_loc, pointerSize);
|
||||
long beginning = DWARFUtil.readAddressAsLong(debug_loc, pointerSize);
|
||||
long ending = DWARFUtil.readAddressAsLong(debug_loc, pointerSize);
|
||||
|
||||
// List end
|
||||
if (beginning.longValue() == 0 && ending.longValue() == 0) {
|
||||
if (beginning == 0 && ending == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if this is a base address entry
|
||||
if (NumberUtil.equalsMaxUnsignedValue(beginning)) {
|
||||
baseAddressOffset = ending.longValue();
|
||||
if (beginning == -1) {
|
||||
baseAddressOffset = ending;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Size is 2 bytes
|
||||
int size = debug_loc.readNextShort() & NumberUtil.UNSIGNED_SHORT_MASK;
|
||||
int size = debug_loc.readNextUnsignedShort();
|
||||
|
||||
// Read the location description
|
||||
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
|
||||
// an offset, but already an absolute value. This occurs in some
|
||||
// gcc dwarf compilation flag combinations.
|
||||
boolean isBadOffset = (beginning.longValue() > cuBase);
|
||||
boolean isBadOffset = (beginning > cuBase);
|
||||
|
||||
long absStart = beginning.longValue();
|
||||
long absEnd = ending.longValue();
|
||||
long absStart = beginning;
|
||||
long absEnd = ending;
|
||||
if (!isBadOffset) {
|
||||
absStart += baseAddressOffset;
|
||||
absEnd += baseAddressOffset;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -844,30 +845,29 @@ public class DIEAggregate {
|
|||
reader.setPointerIndex(offset);
|
||||
List<DWARFRange> ranges = new ArrayList<>();
|
||||
|
||||
long baseAddress = getCompilationUnit().getCompileUnit() != null &&
|
||||
getCompilationUnit().getCompileUnit().getLowPC() != null
|
||||
? getCompilationUnit().getCompileUnit().getLowPC().longValue()
|
||||
DWARFCompileUnit dcu = getCompilationUnit().getCompileUnit();
|
||||
long baseAddress = dcu != null && dcu.getLowPC() != null
|
||||
? dcu.getLowPC().longValue()
|
||||
: 0L;
|
||||
|
||||
while (reader.hasNext()) {
|
||||
// Read the beginning and ending addresses
|
||||
Number beginning = DWARFUtil.readAddress(reader, pointerSize);
|
||||
Number ending = DWARFUtil.readAddress(reader, pointerSize); // dwarf end addrs are exclusive
|
||||
long beginning = DWARFUtil.readAddressAsLong(reader, pointerSize);
|
||||
long ending = DWARFUtil.readAddressAsLong(reader, pointerSize); // dwarf end addrs are exclusive
|
||||
|
||||
// End of the list
|
||||
if (beginning.longValue() == 0 && ending.longValue() == 0) {
|
||||
if (beginning == 0 && ending == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if this is a base address entry
|
||||
if (NumberUtil.equalsMaxUnsignedValue(beginning)) {
|
||||
baseAddress = ending.longValue();
|
||||
if (beginning == -1) {
|
||||
baseAddress = ending;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the range to the list
|
||||
ranges.add(new DWARFRange(baseAddress + beginning.longValue(),
|
||||
baseAddress + ending.longValue()));
|
||||
ranges.add(new DWARFRange(baseAddress + beginning, baseAddress + ending));
|
||||
}
|
||||
Collections.sort(ranges);
|
||||
return ranges;
|
||||
|
@ -896,9 +896,7 @@ public class DIEAggregate {
|
|||
*/
|
||||
public long getHighPC() throws IOException {
|
||||
AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc);
|
||||
if (high != null && high.attr instanceof DWARFNumericAttribute) {
|
||||
DWARFNumericAttribute highVal = (DWARFNumericAttribute) high.attr;
|
||||
|
||||
if (high != null && high.attr instanceof DWARFNumericAttribute highVal) {
|
||||
// if the DWARF attr was a DW_FORM_addr, it doesn't need fixing up
|
||||
if (high.form == DWARFForm.DW_FORM_addr) {
|
||||
return highVal.getUnsignedValue() + getProgram().getProgramBaseAddressFixup() - 1;
|
||||
|
@ -935,11 +933,11 @@ public class DIEAggregate {
|
|||
AttrInfo low = findAttribute(DWARFAttribute.DW_AT_low_pc);
|
||||
AttrInfo high = findAttribute(DWARFAttribute.DW_AT_high_pc);
|
||||
if (low != null && high != null && low.form == high.form &&
|
||||
low.attr instanceof DWARFNumericAttribute &&
|
||||
high.attr instanceof DWARFNumericAttribute) {
|
||||
DWARFNumericAttribute lowVal = (DWARFNumericAttribute) low.attr;
|
||||
DWARFNumericAttribute highVal = (DWARFNumericAttribute) high.attr;
|
||||
low.attr instanceof DWARFNumericAttribute lowVal &&
|
||||
high.attr instanceof DWARFNumericAttribute highVal) {
|
||||
|
||||
return lowVal.getValue() == highVal.getValue();
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -519,29 +519,6 @@ public class DWARFUtil {
|
|||
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
|
||||
* returns it as a 64 bit java long.
|
||||
|
@ -588,8 +565,9 @@ public class DWARFUtil {
|
|||
|
||||
DWARFAttributeValue dwATObjectPointer =
|
||||
paramDIEA.getParent().getAttribute(DWARFAttribute.DW_AT_object_pointer);
|
||||
return dwATObjectPointer != null && dwATObjectPointer instanceof DWARFNumericAttribute &&
|
||||
paramDIEA.hasOffset(((DWARFNumericAttribute) dwATObjectPointer).getUnsignedValue());
|
||||
return dwATObjectPointer != null &&
|
||||
dwATObjectPointer instanceof DWARFNumericAttribute dnum &&
|
||||
paramDIEA.hasOffset(dnum.getUnsignedValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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.StringTable;
|
||||
import ghidra.program.model.data.LEB128;
|
||||
import ghidra.util.NumberUtil;
|
||||
|
||||
/**
|
||||
* A factory for deserializing {@link DWARFAttributeValue dwarf attribute} from
|
||||
|
@ -57,21 +56,21 @@ public class DWARFAttributeFactory {
|
|||
switch (form) {
|
||||
case DW_FORM_addr:
|
||||
return new DWARFNumericAttribute(
|
||||
DWARFUtil.readVarSizedULong(reader, unit.getPointerSize()));
|
||||
reader.readNextUnsignedValue(unit.getPointerSize()));
|
||||
case DW_FORM_ref1: {
|
||||
long uoffset = DWARFUtil.readVarSizedULong(reader, 1);
|
||||
long uoffset = reader.readNextUnsignedValue(1);
|
||||
return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
|
||||
}
|
||||
case DW_FORM_ref2: {
|
||||
long uoffset = DWARFUtil.readVarSizedULong(reader, 2);
|
||||
long uoffset = reader.readNextUnsignedValue(2);
|
||||
return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
|
||||
}
|
||||
case DW_FORM_ref4: {
|
||||
long uoffset = DWARFUtil.readVarSizedULong(reader, 4);
|
||||
long uoffset = reader.readNextUnsignedValue(4);
|
||||
return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
|
||||
}
|
||||
case DW_FORM_ref8: {
|
||||
long uoffset = DWARFUtil.readVarSizedULong(reader, 8);
|
||||
long uoffset = reader.readNextUnsignedValue(8);
|
||||
return new DWARFNumericAttribute(uoffset + unit.getStartOffset());
|
||||
}
|
||||
case DW_FORM_ref_udata: {
|
||||
|
@ -112,20 +111,17 @@ public class DWARFAttributeFactory {
|
|||
return new DWARFBlobAttribute(reader.readNextByteArray(length));
|
||||
}
|
||||
case DW_FORM_data1:
|
||||
return new DWARFAmbigNumericAttribute(reader.readNextByte(),
|
||||
NumberUtil.UNSIGNED_BYTE_MASK);
|
||||
return new DWARFNumericAttribute(8, reader.readNextByte(), true);
|
||||
case DW_FORM_data2:
|
||||
return new DWARFAmbigNumericAttribute(reader.readNextShort(),
|
||||
NumberUtil.UNSIGNED_SHORT_MASK);
|
||||
return new DWARFNumericAttribute(16, reader.readNextShort(), true);
|
||||
case DW_FORM_data4:
|
||||
return new DWARFAmbigNumericAttribute(reader.readNextInt(),
|
||||
NumberUtil.UNSIGNED_INT_MASK);
|
||||
return new DWARFNumericAttribute(32, reader.readNextInt(), true);
|
||||
case DW_FORM_data8:
|
||||
return new DWARFNumericAttribute(reader.readNextLong());
|
||||
return new DWARFNumericAttribute(64, reader.readNextLong(), true);
|
||||
case DW_FORM_sdata:
|
||||
return new DWARFNumericAttribute(reader.readNext(LEB128::signed));
|
||||
return new DWARFNumericAttribute(64, reader.readNext(LEB128::signed), true);
|
||||
case DW_FORM_udata:
|
||||
return new DWARFNumericAttribute(reader.readNext(LEB128::unsigned));
|
||||
return new DWARFNumericAttribute(64, reader.readNext(LEB128::unsigned), false);
|
||||
|
||||
case DW_FORM_exprloc: {
|
||||
int length = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
|
||||
|
|
|
@ -15,32 +15,35 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.dwarf4.attribs;
|
||||
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
protected final long value;
|
||||
public class DWARFNumericAttribute extends Scalar implements DWARFAttributeValue {
|
||||
|
||||
/**
|
||||
* Creates a new numeric value, using 64 bits and marked as signed
|
||||
*
|
||||
* @param value long 64 bit value
|
||||
*/
|
||||
public DWARFNumericAttribute(long value) {
|
||||
this.value = value;
|
||||
this(64, value, true);
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getUnsignedValue() {
|
||||
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
|
||||
* @param value value of the scalar, any bits that are set above bitLength will be ignored
|
||||
* @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
|
||||
public String toString() {
|
||||
return String.format("DWARFNumericAttribute: %d [%08x]", value, value);
|
||||
return String.format("DWARFNumericAttribute: %d [%08x]", getValue(), getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.io.IOException;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.util.NumberUtil;
|
||||
import ghidra.util.NumericUtilities;
|
||||
|
||||
public class BinaryReaderTest {
|
||||
|
||||
|
@ -149,8 +149,7 @@ public class BinaryReaderTest {
|
|||
|
||||
assertEquals(1, br.readUnsignedShort(0));
|
||||
assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readUnsignedShort(2));
|
||||
assertEquals(NumberUtil.UNSIGNED_SHORT_MASK /* ie. UNSIGNED_SHORT_MAX, 0xffff*/,
|
||||
br.readUnsignedShort(4));
|
||||
assertEquals(0xffff, br.readUnsignedShort(4));
|
||||
assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readUnsignedShort(6));
|
||||
try {
|
||||
br.readUnsignedShort(8);
|
||||
|
@ -184,8 +183,7 @@ public class BinaryReaderTest {
|
|||
|
||||
assertEquals(1, br.readNextUnsignedShort());
|
||||
assertEquals(Short.MAX_VALUE /* 0x7fff */, br.readNextUnsignedShort());
|
||||
assertEquals(NumberUtil.UNSIGNED_SHORT_MASK /* ie. UNSIGNED_SHORT_MAX, 0xffff*/,
|
||||
br.readNextUnsignedShort());
|
||||
assertEquals(0xffff, br.readNextUnsignedShort());
|
||||
assertEquals(Short.MAX_VALUE + 1 /* 0x8000 */, br.readNextUnsignedShort());
|
||||
try {
|
||||
br.readNextUnsignedShort();
|
||||
|
@ -225,8 +223,7 @@ public class BinaryReaderTest {
|
|||
|
||||
assertEquals(1, br.readUnsignedInt(0));
|
||||
assertEquals(Integer.MAX_VALUE, br.readUnsignedInt(4));
|
||||
assertEquals(NumberUtil.UNSIGNED_INT_MASK /*ie. UNSIGNED_INT_MAX, 0xff_ff_ff_ff*/,
|
||||
br.readUnsignedInt(8));
|
||||
assertEquals(NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG, br.readUnsignedInt(8));
|
||||
assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readUnsignedInt(12));
|
||||
try {
|
||||
br.readUnsignedInt(16);
|
||||
|
@ -262,8 +259,7 @@ public class BinaryReaderTest {
|
|||
|
||||
assertEquals(1, br.readNextUnsignedInt());
|
||||
assertEquals(Integer.MAX_VALUE, br.readNextUnsignedInt());
|
||||
assertEquals(NumberUtil.UNSIGNED_INT_MASK /*ie. UNSIGNED_INT_MAX, 0xff_ff_ff_ff*/,
|
||||
br.readNextUnsignedInt());
|
||||
assertEquals(NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG, br.readNextUnsignedInt());
|
||||
assertEquals((long) Integer.MAX_VALUE + 1 /* 0x80_00_00_00 */, br.readNextUnsignedInt());
|
||||
try {
|
||||
br.readNextUnsignedInt();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue