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.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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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