mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-25 19:46:01 +08:00
GP-6400 refactor DWARF attribute code
Clean up / rename classes. Move attribute definition info out of attribute value class. Add a handful of missing GNU attribute id values.
This commit is contained in:
+118
-132
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -277,35 +277,25 @@ public class DIEAggregate {
|
||||
return getProgram().getParentDepth(getHeadFragment().getIndex());
|
||||
}
|
||||
|
||||
private FoundAttribute findAttribute(DWARFAttribute attribute) {
|
||||
for (DebugInfoEntry die : fragments) {
|
||||
DWARFAttributeValue attrVal = die.findAttribute(attribute);
|
||||
if (attrVal != null) {
|
||||
return new FoundAttribute(attrVal, die);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an attribute that is present in this {@link DIEAggregate}, or in any of its
|
||||
* direct children (of a specific type)
|
||||
*
|
||||
* @param <T> attribute value type
|
||||
* @param attribute the attribute to find
|
||||
* @param attrId the attribute to find
|
||||
* @param childTag the type of children to search
|
||||
* @param clazz type of the attribute to return
|
||||
* @return attribute value, or null if not found
|
||||
*/
|
||||
public <T extends DWARFAttributeValue> T findAttributeInChildren(DWARFAttribute attribute,
|
||||
public <T extends DWARFAttributeValue> T findAttributeInChildren(DWARFAttributeId attrId,
|
||||
DWARFTag childTag, Class<T> clazz) {
|
||||
T attributeValue = getAttribute(attribute, clazz);
|
||||
T attributeValue = findValue(attrId, clazz);
|
||||
if (attributeValue != null) {
|
||||
return attributeValue;
|
||||
}
|
||||
for (DebugInfoEntry childDIE : getChildren(childTag)) {
|
||||
DIEAggregate childDIEA = getProgram().getAggregate(childDIE);
|
||||
attributeValue = childDIEA.getAttribute(attribute, clazz);
|
||||
attributeValue = childDIEA.findValue(attrId, clazz);
|
||||
if (attributeValue != null) {
|
||||
return attributeValue;
|
||||
}
|
||||
@@ -314,48 +304,64 @@ public class DIEAggregate {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a {@link DWARFAttributeValue attribute} with a matching {@link DWARFAttribute} id.
|
||||
* {@return the matching attribute, by id, or null if not found}
|
||||
* @param attrId {@link DWARFAttributeId} DW_AT_xyz
|
||||
*/
|
||||
public DWARFAttribute findAttribute(DWARFAttributeId attrId) {
|
||||
for (DebugInfoEntry die : fragments) {
|
||||
DWARFAttribute attr = die.findAttribute(attrId);
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a {@link DWARFAttributeValue attribute value} with a matching
|
||||
* {@link DWARFAttributeId} id.
|
||||
* <p>
|
||||
* Returns null if the attribute does not exist or is wrong java class type.
|
||||
* <p>
|
||||
* Attributes are searched for in each fragment in this aggregate, starting with the
|
||||
* 'head' fragment, progressing toward the 'decl' fragment.
|
||||
*
|
||||
* @param attribute See {@link DWARFAttribute}
|
||||
* @param clazz must be derived from {@link DWARFAttributeValue}
|
||||
* @return DWARFAttributeValue or subclass as specified by the clazz, or null if not found
|
||||
* @param attrId See {@link DWARFAttributeId}
|
||||
* @param valueClass must be derived from {@link DWARFAttributeValue}
|
||||
* @return DWARFAttributeValue or subclass as specified by the valueClass, or null if not found
|
||||
*/
|
||||
public <T extends DWARFAttributeValue> T getAttribute(DWARFAttribute attribute,
|
||||
Class<T> clazz) {
|
||||
FoundAttribute attrInfo = findAttribute(attribute);
|
||||
return attrInfo != null ? attrInfo.getValue(clazz) : null;
|
||||
public <T extends DWARFAttributeValue> T findValue(DWARFAttributeId attrId,
|
||||
Class<T> valueClass) {
|
||||
DWARFAttribute attr = findAttribute(attrId);
|
||||
return attr != null ? attr.getValue(valueClass) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a {@link DWARFAttributeValue attribute} with a matching {@link DWARFAttribute} id.
|
||||
* Finds a {@link DWARFAttributeValue attribute value} with a matching
|
||||
* {@link DWARFAttributeId} id.
|
||||
* <p>
|
||||
* Returns null if the attribute does not exist.
|
||||
* <p>
|
||||
* Attributes are searched for in each fragment in this aggregate, starting with the
|
||||
* 'head' fragment, progressing toward the 'decl' fragment.
|
||||
*
|
||||
* @param attribute See {@link DWARFAttribute}
|
||||
* @param attrId See {@link DWARFAttributeId}
|
||||
* @return DWARFAttributeValue, or null if not found
|
||||
*/
|
||||
public DWARFAttributeValue getAttribute(DWARFAttribute attribute) {
|
||||
return getAttribute(attribute, DWARFAttributeValue.class);
|
||||
public DWARFAttributeValue findValue(DWARFAttributeId attrId) {
|
||||
return findValue(attrId, DWARFAttributeValue.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the requested attribute, or -defaultValue- if the
|
||||
* attribute is missing.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return long value, or the defaultValue if attribute not present
|
||||
*/
|
||||
public long getLong(DWARFAttribute attribute, long defaultValue) {
|
||||
DWARFNumericAttribute attr = getAttribute(attribute, DWARFNumericAttribute.class);
|
||||
public long getLong(DWARFAttributeId attrId, long defaultValue) {
|
||||
DWARFNumericAttribute attr = findValue(attrId, DWARFNumericAttribute.class);
|
||||
return (attr != null) ? attr.getValue() : defaultValue;
|
||||
}
|
||||
|
||||
@@ -363,12 +369,12 @@ public class DIEAggregate {
|
||||
* Returns the boolean value of the requested attribute, or -defaultValue- if
|
||||
* the attribute is missing or not the correct type.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return boolean value, or the defaultValue if attribute is not present
|
||||
*/
|
||||
public boolean getBool(DWARFAttribute attribute, boolean defaultValue) {
|
||||
DWARFBooleanAttribute val = getAttribute(attribute, DWARFBooleanAttribute.class);
|
||||
public boolean getBool(DWARFAttributeId attrId, boolean defaultValue) {
|
||||
DWARFBooleanAttribute val = findValue(attrId, DWARFBooleanAttribute.class);
|
||||
return (val != null) ? val.getValue() : defaultValue;
|
||||
}
|
||||
|
||||
@@ -376,20 +382,19 @@ public class DIEAggregate {
|
||||
* Returns the string value of the requested attribute, or -defaultValue- if
|
||||
* the attribute is missing or not the correct type.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return String value, or the defaultValue if attribute is not present
|
||||
*/
|
||||
public String getString(DWARFAttribute attribute, String defaultValue) {
|
||||
FoundAttribute attrInfo = findAttribute(attribute);
|
||||
if (attrInfo == null || !(attrInfo.attr instanceof DWARFStringAttribute strAttr)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return strAttr.getValue(attrInfo.die.getCompilationUnit());
|
||||
public String getString(DWARFAttributeId attrId, String defaultValue) {
|
||||
DWARFAttribute attr = findAttribute(attrId);
|
||||
return attr != null && attr.getValue() instanceof DWARFStringAttribute sval
|
||||
? sval.getValue(attr.getDIE().getCompilationUnit())
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string value of the {@link DWARFAttribute#DW_AT_name dw_at_name} attribute,
|
||||
* Returns the string value of the {@link DWARFAttributeId#DW_AT_name DW_AT_name} attribute,
|
||||
* or null if it is missing.
|
||||
*
|
||||
* @return name of this DIE aggregate, or null if missing
|
||||
@@ -407,28 +412,29 @@ public class DIEAggregate {
|
||||
* <p>
|
||||
* The -defaultValue- parameter can accept a negative value.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return unsigned long value, or the defaultValue if attribute is not present
|
||||
*/
|
||||
public long getUnsignedLong(DWARFAttribute attribute, long defaultValue) {
|
||||
DWARFNumericAttribute attr = getAttribute(attribute, DWARFNumericAttribute.class);
|
||||
public long getUnsignedLong(DWARFAttributeId attrId, long defaultValue) {
|
||||
DWARFNumericAttribute attr = findValue(attrId, DWARFNumericAttribute.class);
|
||||
return (attr != null) ? attr.getUnsignedValue() : defaultValue;
|
||||
}
|
||||
|
||||
private DebugInfoEntry getRefDIE(DWARFAttribute attribute) {
|
||||
FoundAttribute foundAttr = findAttribute(attribute);
|
||||
if (foundAttr == null || !(foundAttr.attr instanceof DWARFNumericAttribute val)) {
|
||||
private DebugInfoEntry getRefDIE(DWARFAttributeId attrId) {
|
||||
DWARFAttribute foundAttr = findAttribute(attrId);
|
||||
if (foundAttr == null || !(foundAttr.getValue() instanceof DWARFNumericAttribute val)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return getProgram().getDIE(val.getAttributeForm(), val.getUnsignedValue(),
|
||||
foundAttr.die.getCompilationUnit());
|
||||
return getProgram().getDIE(foundAttr.getAttributeForm(), val.getUnsignedValue(),
|
||||
foundAttr.getDIE().getCompilationUnit());
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.warn(this, "Invalid reference from DIE 0x%x to 0x%x (%s)".formatted(
|
||||
foundAttr.die.getOffset(), val.getUnsignedValue(), val.getAttributeForm()));
|
||||
foundAttr.getDIE().getOffset(), val.getUnsignedValue(),
|
||||
foundAttr.getAttributeForm()));
|
||||
Msg.debug(this, this.toString());
|
||||
}
|
||||
return null;
|
||||
@@ -438,11 +444,11 @@ public class DIEAggregate {
|
||||
* Returns the {@link DIEAggregate diea} instance pointed to by the requested attribute,
|
||||
* or null if the attribute does not exist.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @return {@link DIEAggregate}, or the null if attribute is not present
|
||||
*/
|
||||
public DIEAggregate getRef(DWARFAttribute attribute) {
|
||||
DebugInfoEntry die = getRefDIE(attribute);
|
||||
public DIEAggregate getRef(DWARFAttributeId attrId) {
|
||||
DebugInfoEntry die = getRefDIE(attrId);
|
||||
return getProgram().getAggregate(die);
|
||||
}
|
||||
|
||||
@@ -465,7 +471,7 @@ public class DIEAggregate {
|
||||
* @return name of file this item was declared in, or null if info not available
|
||||
*/
|
||||
public String getSourceFile() {
|
||||
FoundAttribute attrInfo = findAttribute(DW_AT_decl_file);
|
||||
DWARFAttribute attrInfo = findAttribute(DW_AT_decl_file);
|
||||
if (attrInfo == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -475,7 +481,7 @@ public class DIEAggregate {
|
||||
}
|
||||
try {
|
||||
int fileNum = attr.getUnsignedIntExact();
|
||||
DWARFLine line = attrInfo.die.getCompilationUnit().getLine();
|
||||
DWARFLine line = attrInfo.getDIE().getCompilationUnit().getLine();
|
||||
DWARFFile file = line.getFile(fileNum);
|
||||
return file.getName();
|
||||
}
|
||||
@@ -497,11 +503,11 @@ public class DIEAggregate {
|
||||
/**
|
||||
* Returns true if the specified attribute is present.
|
||||
*
|
||||
* @param attribute attribute id
|
||||
* @param attrId attribute id
|
||||
* @return boolean true if value is present
|
||||
*/
|
||||
public boolean hasAttribute(DWARFAttribute attribute) {
|
||||
return findAttribute(attribute) != null;
|
||||
public boolean hasAttribute(DWARFAttributeId attrId) {
|
||||
return findAttribute(attrId) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,12 +518,12 @@ public class DIEAggregate {
|
||||
* abstract portion
|
||||
*/
|
||||
public DIEAggregate getAbstractInstance() {
|
||||
FoundAttribute aoAttr = findAttribute(DW_AT_abstract_origin);
|
||||
DWARFAttribute aoAttr = findAttribute(DW_AT_abstract_origin);
|
||||
if (aoAttr == null) {
|
||||
return null;
|
||||
}
|
||||
for (int aoIndex = 0; aoIndex < fragments.length; aoIndex++) {
|
||||
if (fragments[aoIndex] == aoAttr.die) {
|
||||
if (fragments[aoIndex] == aoAttr.getDIE()) {
|
||||
DebugInfoEntry[] partialFrags = new DebugInfoEntry[fragments.length - aoIndex - 1];
|
||||
System.arraycopy(fragments, aoIndex + 1, partialFrags, 0, partialFrags.length);
|
||||
return new DIEAggregate(partialFrags);
|
||||
@@ -530,15 +536,15 @@ public class DIEAggregate {
|
||||
* Returns the signed integer value of the requested attribute after resolving
|
||||
* any DWARF expression opcodes.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return int value, or the defaultValue if attribute is not present
|
||||
* @throws IOException if error reading value or invalid value type
|
||||
* @throws DWARFExpressionException if error evaluating a DWARF expression
|
||||
*/
|
||||
public int parseInt(DWARFAttribute attribute, int defaultValue)
|
||||
public int parseInt(DWARFAttributeId attrId, int defaultValue)
|
||||
throws IOException, DWARFExpressionException {
|
||||
DWARFAttributeValue attr = getAttribute(attribute);
|
||||
DWARFAttributeValue attr = findValue(attrId);
|
||||
if (attr == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -560,32 +566,29 @@ public class DIEAggregate {
|
||||
* Returns the unsigned integer value of the requested attribute after resolving
|
||||
* any DWARF expression opcodes.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return unsigned long value, or the defaultValue if attribute is not present
|
||||
* @throws IOException if error reading value or invalid value type
|
||||
* @throws DWARFExpressionException if error evaluating a DWARF expression
|
||||
*/
|
||||
public long parseUnsignedLong(DWARFAttribute attribute, long defaultValue)
|
||||
public long parseUnsignedLong(DWARFAttributeId attrId, long defaultValue)
|
||||
throws IOException, DWARFExpressionException {
|
||||
FoundAttribute attrInfo = findAttribute(attribute);
|
||||
if (attrInfo == null) {
|
||||
DWARFAttribute attr = findAttribute(attrId);
|
||||
if (attr == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
DWARFAttributeValue attr = attrInfo.attr;
|
||||
if (attr instanceof DWARFNumericAttribute dnum) {
|
||||
return dnum.getUnsignedValue();
|
||||
}
|
||||
else if (attr instanceof DWARFBlobAttribute dblob) {
|
||||
DWARFExpressionEvaluator evaluator =
|
||||
new DWARFExpressionEvaluator(attrInfo.die().getCompilationUnit());
|
||||
evaluator.evaluate(dblob.getBytes(), 0);
|
||||
return evaluator.popLong();
|
||||
}
|
||||
else {
|
||||
throw new IOException("Not integer attribute: %s".formatted(attr));
|
||||
}
|
||||
return switch (attr.getValue()) {
|
||||
case DWARFNumericAttribute dnum -> dnum.getUnsignedValue();
|
||||
case DWARFBlobAttribute dblob -> {
|
||||
DWARFExpressionEvaluator evaluator =
|
||||
new DWARFExpressionEvaluator(attr.getDIE().getCompilationUnit());
|
||||
evaluator.evaluate(dblob.getBytes(), 0);
|
||||
yield evaluator.popLong();
|
||||
}
|
||||
default -> throw new IOException("Not integer attribute: %s".formatted(attr));
|
||||
};
|
||||
}
|
||||
|
||||
private int assertValidInt(long l) throws DWARFException {
|
||||
@@ -606,61 +609,61 @@ public class DIEAggregate {
|
||||
* Returns the unsigned integer value of the requested attribute after resolving
|
||||
* any DWARF expression opcodes.
|
||||
*
|
||||
* @param attribute {@link DWARFAttribute} id
|
||||
* @param attrId {@link DWARFAttributeId} id
|
||||
* @param defaultValue value to return if attribute is not present
|
||||
* @return unsigned int value, or the defaultValue if attribute is not present
|
||||
* @throws IOException if error reading value or invalid value type
|
||||
* @throws DWARFExpressionException if error evaluating a DWARF expression
|
||||
*/
|
||||
public int parseDataMemberOffset(DWARFAttribute attribute, int defaultValue)
|
||||
public int parseDataMemberOffset(DWARFAttributeId attrId, int defaultValue)
|
||||
throws DWARFExpressionException, IOException {
|
||||
|
||||
DWARFAttributeValue attr = getAttribute(attribute);
|
||||
DWARFAttribute attr = findAttribute(attrId);
|
||||
if (attr == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (attr instanceof DWARFNumericAttribute dnum) {
|
||||
return dnum.getUnsignedIntExact();
|
||||
}
|
||||
else if (attr instanceof DWARFBlobAttribute dblob) {
|
||||
DWARFExpressionEvaluator evaluator = new DWARFExpressionEvaluator(getCompilationUnit());
|
||||
return switch (attr.getValue()) {
|
||||
case DWARFNumericAttribute dnum -> dnum.getUnsignedIntExact();
|
||||
case DWARFBlobAttribute dblob -> {
|
||||
DWARFExpressionEvaluator evaluator =
|
||||
new DWARFExpressionEvaluator(getCompilationUnit());
|
||||
|
||||
// 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
|
||||
// fake it with zero.
|
||||
evaluator.evaluate(dblob.getBytes(), 0);
|
||||
return assertValidUInt(evaluator.popLong());
|
||||
}
|
||||
else {
|
||||
throw new DWARFException("DWARF attribute form not valid for data member offset: %s"
|
||||
.formatted(attr.getAttributeForm()));
|
||||
}
|
||||
// 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
|
||||
// fake it with zero.
|
||||
evaluator.evaluate(dblob.getBytes(), 0);
|
||||
yield assertValidUInt(evaluator.popLong());
|
||||
}
|
||||
default -> throw new DWARFException(
|
||||
"DWARF attribute form not valid for data member offset: %s"
|
||||
.formatted(attr.getAttributeForm()));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a location attribute value, which can be a single expression that is valid for any
|
||||
* PC, or a list of expressions that are tied to specific ranges.
|
||||
*
|
||||
* @param attribute typically {@link DWARFAttribute#DW_AT_location}
|
||||
* @param attrId typically {@link DWARFAttributeId#DW_AT_location}
|
||||
* @return a {@link DWARFLocationList}, never null, possibly empty
|
||||
* @throws IOException if error reading data
|
||||
*/
|
||||
public DWARFLocationList getLocationList(DWARFAttribute attribute) throws IOException {
|
||||
return getProgram().getLocationList(this, attribute);
|
||||
public DWARFLocationList getLocationList(DWARFAttributeId attrId) throws IOException {
|
||||
return getProgram().getLocationList(this, attrId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a location attribute value, and returns the {@link DWARFLocation} instance that
|
||||
* covers the specified pc.
|
||||
*
|
||||
* @param attribute typically {@link DWARFAttribute#DW_AT_location}
|
||||
* @param attrId typically {@link DWARFAttributeId#DW_AT_location}
|
||||
* @param pc program counter
|
||||
* @return a {@link DWARFLocationList}, never null, possibly empty
|
||||
* @throws IOException if error reading data
|
||||
*/
|
||||
public DWARFLocation getLocation(DWARFAttribute attribute, long pc) throws IOException {
|
||||
DWARFLocationList locList = getLocationList(attribute);
|
||||
public DWARFLocation getLocation(DWARFAttributeId attrId, long pc) throws IOException {
|
||||
DWARFLocationList locList = getLocationList(attrId);
|
||||
return locList.getLocationContaining(pc);
|
||||
}
|
||||
|
||||
@@ -700,12 +703,12 @@ public class DIEAggregate {
|
||||
/**
|
||||
* Parses a range list.
|
||||
*
|
||||
* @param attribute attribute eg {@link DWARFAttribute#DW_AT_ranges}
|
||||
* @param attrId attribute eg {@link DWARFAttributeId#DW_AT_ranges}
|
||||
* @return list of ranges, or null if attribute is not present
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
public DWARFRangeList getRangeList(DWARFAttribute attribute) throws IOException {
|
||||
return getProgram().getRangeList(this, attribute);
|
||||
public DWARFRangeList getRangeList(DWARFAttributeId attrId) throws IOException {
|
||||
return getProgram().getRangeList(this, attrId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -715,23 +718,23 @@ public class DIEAggregate {
|
||||
* not present
|
||||
*/
|
||||
public DWARFRange getPCRange() {
|
||||
DWARFNumericAttribute lowPc = getAttribute(DW_AT_low_pc, DWARFNumericAttribute.class);
|
||||
if (lowPc != null) {
|
||||
DWARFAttribute lowPc = findAttribute(DW_AT_low_pc);
|
||||
if (lowPc != null && lowPc.getValue() instanceof DWARFNumericAttribute lowPcAttrVal) {
|
||||
try {
|
||||
// TODO: previous code excluded lowPc values that were == 0 as invalid.
|
||||
long rawLowPc = lowPc.getUnsignedValue();
|
||||
long rawLowPc = lowPcAttrVal.getUnsignedValue();
|
||||
long lowPcOffset = getProgram().getAddress(lowPc.getAttributeForm(), rawLowPc,
|
||||
getCompilationUnit());
|
||||
long highPcOffset = lowPcOffset;
|
||||
|
||||
DWARFNumericAttribute highPc =
|
||||
getAttribute(DW_AT_high_pc, DWARFNumericAttribute.class);
|
||||
if (highPc != null) {
|
||||
DWARFAttribute highPc = findAttribute(DW_AT_high_pc);
|
||||
if (highPc != null &&
|
||||
highPc.getValue() instanceof DWARFNumericAttribute highPcAttrVal) {
|
||||
if (highPc.getAttributeForm() == DWARFForm.DW_FORM_addr) {
|
||||
highPcOffset = highPc.getUnsignedValue();
|
||||
highPcOffset = highPcAttrVal.getUnsignedValue();
|
||||
}
|
||||
else {
|
||||
highPcOffset = highPc.getUnsignedValue();
|
||||
highPcOffset = highPcAttrVal.getUnsignedValue();
|
||||
highPcOffset = lowPcOffset + highPcOffset;
|
||||
}
|
||||
}
|
||||
@@ -797,23 +800,6 @@ public class DIEAggregate {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple class used by findAttribute() to return the found attribute, along with
|
||||
* the DIE it was found in, and the DWARFForm type of the raw attribute.
|
||||
*
|
||||
* @param attr attribute value
|
||||
* @param die DIE the value was found in
|
||||
*/
|
||||
record FoundAttribute(DWARFAttributeValue attr, DebugInfoEntry die) {
|
||||
<T extends DWARFAttributeValue> T getValue(Class<T> clazz) {
|
||||
if (attr != null && clazz.isAssignableFrom(attr.getClass())) {
|
||||
return clazz.cast(attr);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
||||
+8
-8
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -20,7 +20,7 @@ import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.*;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.AttrDef;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.AttrDef;
|
||||
import ghidra.program.model.data.LEB128;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -78,11 +78,11 @@ public class DWARFAbbreviation {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void warnIfMismatchedForms(DWARFAttribute.AttrDef attrSpec) {
|
||||
private static void warnIfMismatchedForms(DWARFAttributeId.AttrDef attrSpec) {
|
||||
DWARFForm form = attrSpec.getAttributeForm();
|
||||
DWARFAttribute attribute = attrSpec.getAttributeId();
|
||||
if (attribute != null && !form.getFormClasses().isEmpty() &&
|
||||
!attribute.getAttributeClass().isEmpty()) {
|
||||
DWARFAttributeId attrId = attrSpec.getAttributeId();
|
||||
if (attrId != null && !form.getFormClasses().isEmpty() &&
|
||||
!attrId.getAttributeClass().isEmpty()) {
|
||||
EnumSet<DWARFAttributeClass> tmp =
|
||||
EnumSet.copyOf(attrSpec.getAttributeForm().getFormClasses());
|
||||
tmp.retainAll(attrSpec.getAttributeId().getAttributeClass());
|
||||
@@ -192,7 +192,7 @@ public class DWARFAbbreviation {
|
||||
* @param attributeId attribute key
|
||||
* @return attribute specification
|
||||
*/
|
||||
public AttrDef findAttribute(DWARFAttribute attributeId) {
|
||||
public AttrDef findAttribute(DWARFAttributeId attributeId) {
|
||||
for (AttrDef spec : this.attributes) {
|
||||
if (spec.getAttributeId() == attributeId) {
|
||||
return spec;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
+3
-4
@@ -62,11 +62,10 @@ public class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if src can overwrite the target composite based on size
|
||||
* {@return true if src can overwrite the target composite based on size}
|
||||
*
|
||||
* @param src
|
||||
* @param target
|
||||
* @return
|
||||
* @param src {@link Composite} data type
|
||||
* @param target {@link Composite} data type
|
||||
*/
|
||||
private boolean isSizeCompatible(Composite src, Composite target) {
|
||||
return target.isNotYetDefined() || (src.getLength() == target.getLength());
|
||||
|
||||
+19
-20
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -51,8 +51,8 @@ public class DWARFDataTypeImporter {
|
||||
private DWARFDataType voidDDT;
|
||||
|
||||
/**
|
||||
* Tracks which {@link DIEAggregate DIEAs} have been visited by {@link #getDataTypeWorker(DIEAggregate, DataType)}
|
||||
* during the current {@link #getDataType(DIEAggregate, DWARFDataType)} session.
|
||||
* Tracks which {@link DIEAggregate DIEAs} have already been visited by
|
||||
* {@link #getDataType(DIEAggregate, DWARFDataType)} during the current session.
|
||||
* <p>
|
||||
* Some recursive calls are permitted to handle loops in the data types, but are limited
|
||||
* to 2 recursions.
|
||||
@@ -398,9 +398,9 @@ public class DWARFDataTypeImporter {
|
||||
/**
|
||||
* Simple passthru, returns whatever type this "const" modifier applies to.
|
||||
*
|
||||
* @param diea
|
||||
* @throws IOException
|
||||
* @throws DWARFExpressionException
|
||||
* @param diea {@link DIEAggregate}
|
||||
* @throws IOException if error
|
||||
* @throws DWARFExpressionException if error with dwarf expression
|
||||
*/
|
||||
private DWARFDataType makeDataTypeForConst(DIEAggregate diea)
|
||||
throws IOException, DWARFExpressionException {
|
||||
@@ -421,8 +421,8 @@ public class DWARFDataTypeImporter {
|
||||
* This method takes liberties with the normal{@literal DWARF->Ghidra Impl DataType->Ghidra DB DataType}
|
||||
* workflow to be able to merge values into previous db enum datatypes.
|
||||
*
|
||||
* @param diea
|
||||
* @return
|
||||
* @param diea {@link DIEAggregate}
|
||||
* @return {@link DWARFDataType} with enum data type
|
||||
*/
|
||||
private DWARFDataType makeDataTypeForEnum(DIEAggregate diea) {
|
||||
|
||||
@@ -471,7 +471,7 @@ public class DWARFDataTypeImporter {
|
||||
String valueName = childDIEA.getName();
|
||||
|
||||
DWARFNumericAttribute enumValAttr = childDIEA
|
||||
.getAttribute(DW_AT_const_value, DWARFNumericAttribute.class);
|
||||
.findValue(DW_AT_const_value, DWARFNumericAttribute.class);
|
||||
if (enumValAttr != null) {
|
||||
long enumVal = enumValAttr.getValueWithSignednessHint(defaultSignedness);
|
||||
|
||||
@@ -521,11 +521,10 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are no values in destEnum that conflict with srcEnum.
|
||||
* {@return true if there are no values in destEnum that conflict with srcEnum }
|
||||
*
|
||||
* @param srcEnum
|
||||
* @param destEnum
|
||||
* @return
|
||||
* @param srcEnum {@link Enum}
|
||||
* @param destEnum {@link Enum}
|
||||
*/
|
||||
private boolean isCompatEnumValues(Enum srcEnum, Enum destEnum) {
|
||||
for (String srcKey : srcEnum.getNames()) {
|
||||
@@ -547,16 +546,16 @@ public class DWARFDataTypeImporter {
|
||||
/**
|
||||
* Creates an empty stub structure/union for the DIEA.
|
||||
* <p>
|
||||
* Use {@link #finishStruct(DIEAggregate, DataType)} (which calls
|
||||
* {@link #populateStubStruct(StructureDataType, DIEAggregate)} and
|
||||
* {@link #populateStubEnum(Enum, DIEAggregate)}) to fill in the fields of the structure.
|
||||
* Use {@link #finishStruct(DIEAggregate, DWARFDataType)} (which calls
|
||||
* {@link #populateStubStruct(DWARFDataType, DIEAggregate)} and
|
||||
* {@link #populateStubEnum(Enum, DIEAggregate, boolean)}) to fill in the fields of the structure.
|
||||
* <p>
|
||||
* This is done in two steps to enable ending recursive loops by publishing the empty
|
||||
* struct in the {@link #dieOffsetToDataTypeMap} map, where it will be found and returned by
|
||||
* {@link #getDataTypeWorker(DIEAggregate, DataType)}, instead of calling back
|
||||
* into this method.
|
||||
* @param diea
|
||||
* @return
|
||||
* any recursive calls back into {@link #getDataType(DIEAggregate, DWARFDataType)}.
|
||||
*
|
||||
* @param diea {@link DIEAggregate}
|
||||
* @return {@link DWARFDataType} with empty composite that needs to be populated
|
||||
*/
|
||||
private DWARFDataType makeDataTypeForStruct(DIEAggregate diea) {
|
||||
|
||||
|
||||
+10
-10
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -276,8 +276,8 @@ public class DWARFDataTypeManager {
|
||||
* Iterate all {@link DataType}s that match the CategoryPath / name given
|
||||
* in the {@link DataTypePath} parameter, including "conflict" datatypes
|
||||
* that have a ".CONFLICTxx" suffix.
|
||||
* @param dtp
|
||||
* @return
|
||||
* @param dtp {@link DataTypePath}
|
||||
* @return {@link Iterable} of DataTypes that match
|
||||
*/
|
||||
public Iterable<DataType> forAllConflicts(DataTypePath dtp) {
|
||||
Category cat = dataTypeManager.getCategory(dtp.getCategoryPath());
|
||||
@@ -312,8 +312,8 @@ public class DWARFDataTypeManager {
|
||||
* Returns a Ghidra {@link DataType datatype} that corresponds to a type
|
||||
* that can be used to represent an offset.
|
||||
*
|
||||
* @param size
|
||||
* @return
|
||||
* @param size (in bytes) of desired offset type
|
||||
* @return DataType that can be used as an offset value
|
||||
*/
|
||||
public DataType getOffsetType(int size) {
|
||||
return findMatchingDataTypeBySize(baseDataTypeUntyped, size);
|
||||
@@ -383,16 +383,16 @@ public class DWARFDataTypeManager {
|
||||
* Any newly created Ghidra data types will be cached and the same instance will be returned
|
||||
* if the same DWARF named base type is requested again.
|
||||
*
|
||||
* @param name
|
||||
* @param dwarfSize
|
||||
* @param dwarfEncoding
|
||||
* @param isBigEndian
|
||||
* @param name name of DWARF base type
|
||||
* @param dwarfSize size of DWARF base type
|
||||
* @param dwarfEncoding from {@link DWARFEncoding} const 'enum'
|
||||
* @param isBigEndian boolean flag, true = BE, false = LE
|
||||
* @param isExplictSize boolean flag, if true the returned data type will not be linked to
|
||||
* the dataOrganization's compiler specified data types (eg. if type is something like int32_t,
|
||||
* the returned type should never change size, even if the dataOrg changes). If false,
|
||||
* the returned type will be linked to the dataOrg's compiler specified data types if possible,
|
||||
* except for data types that have a name that include a bitsize in the name, such as "int64_t".
|
||||
* @return
|
||||
* @return DataType that corresponds to the named DWARF base type
|
||||
*/
|
||||
public DataType getBaseType(String name, int dwarfSize, int dwarfEncoding,
|
||||
boolean isBigEndian, boolean isExplictSize) {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
+36
-42
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -62,7 +62,7 @@ public class DWARFProgram implements Closeable {
|
||||
public static final String DWARF_BOOKMARK_CAT = "DWARF";
|
||||
private static final int NAME_HASH_REPLACEMENT_SIZE = 8 + 2 + 2;
|
||||
private static final String ELLIPSES_STR = "...";
|
||||
protected static final EnumSet<DWARFAttribute> REF_ATTRS =
|
||||
protected static final EnumSet<DWARFAttributeId> REF_ATTRS =
|
||||
EnumSet.of(DW_AT_abstract_origin, DW_AT_specification);
|
||||
|
||||
/**
|
||||
@@ -139,7 +139,7 @@ public class DWARFProgram implements Closeable {
|
||||
private FixedSizeHashMap<Long, DWARFName> dniCache =
|
||||
new FixedSizeHashMap<>(100, maxDNICacheSize);
|
||||
|
||||
private Map<DWARFAttribute.AttrDef, DWARFAttribute.AttrDef> attributeSpecIntern =
|
||||
private Map<DWARFAttributeId.AttrDef, DWARFAttributeId.AttrDef> attributeSpecIntern =
|
||||
new HashMap<>();
|
||||
|
||||
private DWARFRegisterMappings dwarfRegisterMappings;
|
||||
@@ -447,12 +447,12 @@ public class DWARFProgram implements Closeable {
|
||||
}
|
||||
|
||||
DIEAggregate diea = DIEAggregate.createSingle(die);
|
||||
for (DWARFAttribute attr : REF_ATTRS) {
|
||||
DWARFNumericAttribute attrval =
|
||||
diea.getAttribute(attr, DWARFNumericAttribute.class);
|
||||
if (attrval != null) {
|
||||
long refdOffset = getLocalDIEOffset(attrval.getAttributeForm(),
|
||||
attrval.getUnsignedValue(), cu);
|
||||
for (DWARFAttributeId attrId : REF_ATTRS) {
|
||||
DWARFAttribute refAttr = diea.findAttribute(attrId);
|
||||
if (refAttr != null &&
|
||||
refAttr.getValue() instanceof DWARFNumericAttribute refVal) {
|
||||
long refdOffset = getLocalDIEOffset(refAttr.getAttributeForm(),
|
||||
refVal.getUnsignedValue(), cu);
|
||||
aggrTargets.add(refdOffset);
|
||||
}
|
||||
}
|
||||
@@ -1148,12 +1148,12 @@ public class DWARFProgram implements Closeable {
|
||||
* @return {@link DWARFRangeList}, or null if attribute is not present
|
||||
* @throws IOException if error reading range list
|
||||
*/
|
||||
public DWARFRangeList getRangeList(DIEAggregate diea, DWARFAttribute attribute)
|
||||
public DWARFRangeList getRangeList(DIEAggregate diea, DWARFAttributeId attribute)
|
||||
throws IOException {
|
||||
|
||||
DWARFNumericAttribute rngListAttr =
|
||||
diea.getAttribute(attribute, DWARFNumericAttribute.class);
|
||||
if (rngListAttr == null) {
|
||||
DWARFAttribute rngListAttr = diea.findAttribute(attribute);
|
||||
if (rngListAttr == null ||
|
||||
!(rngListAttr.getValue() instanceof DWARFNumericAttribute rngListVal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1161,7 +1161,7 @@ public class DWARFProgram implements Closeable {
|
||||
|
||||
switch (rngListAttr.getAttributeForm()) {
|
||||
case DW_FORM_rnglistx: { // assumes v5
|
||||
int index = rngListAttr.getUnsignedIntExact();
|
||||
int index = rngListVal.getUnsignedIntExact();
|
||||
long rnglistOffset = rangeListTable.getOffset(index, cu);
|
||||
debugRngLists.setPointerIndex(rnglistOffset);
|
||||
return DWARFRangeList.readV5(debugRngLists, cu);
|
||||
@@ -1170,7 +1170,7 @@ public class DWARFProgram implements Closeable {
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_data8: {
|
||||
long rnglistOffset = rngListAttr.getValue();
|
||||
long rnglistOffset = rngListVal.getValue();
|
||||
short dwarfVersion = cu.getDWARFVersion();
|
||||
if (dwarfVersion < 5) {
|
||||
debugRanges.setPointerIndex(rnglistOffset);
|
||||
@@ -1256,49 +1256,45 @@ public class DWARFProgram implements Closeable {
|
||||
* Returns the {@link DWARFLocationList} pointed to by the specified attribute value.
|
||||
*
|
||||
* @param diea {@link DIEAggregate}
|
||||
* @param attribute attribute id that points to the location list
|
||||
* @param attrId attribute id that points to the location list
|
||||
* @return {@link DWARFLocationList}, never null
|
||||
* @throws IOException if specified attribute is not the correct type, or if other error reading
|
||||
* data
|
||||
*/
|
||||
public DWARFLocationList getLocationList(DIEAggregate diea, DWARFAttribute attribute)
|
||||
public DWARFLocationList getLocationList(DIEAggregate diea, DWARFAttributeId attrId)
|
||||
throws IOException {
|
||||
DWARFAttributeValue attrib = diea.getAttribute(attribute);
|
||||
DWARFAttribute attrib = diea.findAttribute(attrId);
|
||||
if (attrib == null) {
|
||||
return DWARFLocationList.EMPTY;
|
||||
}
|
||||
if (attrib instanceof DWARFNumericAttribute dnum) {
|
||||
return readLocationList(dnum, diea.getCompilationUnit());
|
||||
}
|
||||
else if (attrib instanceof DWARFBlobAttribute dblob) {
|
||||
return DWARFLocationList.withWildcardRange(dblob.getBytes());
|
||||
}
|
||||
else {
|
||||
throw new IOException("Unsupported form %s.".formatted(attrib));
|
||||
}
|
||||
|
||||
return switch (attrib.getValue()) {
|
||||
case DWARFNumericAttribute dnum -> readLocationList(attrib, dnum);
|
||||
case DWARFBlobAttribute dblob -> DWARFLocationList.withWildcardRange(dblob.getBytes());
|
||||
default -> throw new IOException("Unsupported form %s.".formatted(attrib));
|
||||
};
|
||||
}
|
||||
|
||||
private DWARFLocationList readLocationList(DWARFNumericAttribute loclistAttr,
|
||||
DWARFCompilationUnit cu) throws IOException {
|
||||
private DWARFLocationList readLocationList(DWARFAttribute attr, DWARFNumericAttribute val)
|
||||
throws IOException {
|
||||
try {
|
||||
switch (loclistAttr.getAttributeForm()) {
|
||||
DWARFCompilationUnit cu = attr.getCU();
|
||||
switch (attr.getAttributeForm()) {
|
||||
case DW_FORM_sec_offset:
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_data8:
|
||||
int dwarfVer = cu.getDWARFVersion();
|
||||
if (dwarfVer < 5) {
|
||||
debugLocation.setPointerIndex(loclistAttr.getUnsignedValue());
|
||||
debugLocation.setPointerIndex(val.getUnsignedValue());
|
||||
return DWARFLocationList.readV4(debugLocation, cu);
|
||||
}
|
||||
else if (dwarfVer == 5) {
|
||||
debugLocLists.setPointerIndex(loclistAttr.getUnsignedValue());
|
||||
debugLocLists.setPointerIndex(val.getUnsignedValue());
|
||||
return DWARFLocationList.readV5(debugLocLists, cu);
|
||||
}
|
||||
break;
|
||||
case DW_FORM_loclistx:
|
||||
int index = loclistAttr.getUnsignedIntExact();
|
||||
int index = val.getUnsignedIntExact();
|
||||
long locOffset = locationListTable.getOffset(index, cu);
|
||||
debugLocLists.setPointerIndex(locOffset);
|
||||
return DWARFLocationList.readV5(debugLocLists, cu);
|
||||
@@ -1308,11 +1304,9 @@ public class DWARFProgram implements Closeable {
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
throw new IOException(
|
||||
"Failed to read location list specified by %s".formatted(loclistAttr.toString()),
|
||||
e);
|
||||
"Failed to read location list specified by %s".formatted(attr.toString()), e);
|
||||
}
|
||||
throw new IOException(
|
||||
"Unsupported loclist form %s".formatted(loclistAttr.getAttributeForm()));
|
||||
throw new IOException("Unsupported loclist form %s".formatted(attr.getAttributeForm()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1323,8 +1317,8 @@ public class DWARFProgram implements Closeable {
|
||||
* @return {@link DWARFLine}, never null, see {@link DWARFLine#empty()}
|
||||
* @throws IOException if error reading line data
|
||||
*/
|
||||
public DWARFLine getLine(DIEAggregate diea, DWARFAttribute attribute) throws IOException {
|
||||
DWARFNumericAttribute attrib = diea.getAttribute(attribute, DWARFNumericAttribute.class);
|
||||
public DWARFLine getLine(DIEAggregate diea, DWARFAttributeId attribute) throws IOException {
|
||||
DWARFNumericAttribute attrib = diea.findValue(attribute, DWARFNumericAttribute.class);
|
||||
if (attrib == null || debugLineBR == null) {
|
||||
return DWARFLine.empty();
|
||||
}
|
||||
@@ -1402,8 +1396,8 @@ public class DWARFProgram implements Closeable {
|
||||
return program.getAddressFactory().getStackSpace();
|
||||
}
|
||||
|
||||
public DWARFAttribute.AttrDef internAttributeSpec(DWARFAttribute.AttrDef das) {
|
||||
DWARFAttribute.AttrDef inDAS = attributeSpecIntern.get(das);
|
||||
public DWARFAttributeId.AttrDef internAttributeSpec(DWARFAttributeId.AttrDef das) {
|
||||
DWARFAttributeId.AttrDef inDAS = attributeSpecIntern.get(das);
|
||||
if (inDAS == null) {
|
||||
inDAS = das;
|
||||
attributeSpecIntern.put(inDAS, inDAS);
|
||||
|
||||
+3
-4
@@ -17,7 +17,8 @@ package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -175,14 +176,12 @@ public class DWARFRegisterMappingsManager {
|
||||
* Reads and populates map of dwarf reg numbers to ghidra register objects, and returns
|
||||
* the index of the dwarf stack pointer register.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static int readMappingsElem(Element regMappingsElem, Language lang,
|
||||
Map<Integer, Register> dwarfRegisterMap) throws IOException {
|
||||
|
||||
int stackPointerIndex = -1;
|
||||
|
||||
for (Element regMappingElem : (List<Element>) regMappingsElem.getChildren(
|
||||
"register_mapping")) {
|
||||
for (Element regMappingElem : regMappingsElem.getChildren("register_mapping")) {
|
||||
|
||||
int dwarfRegNum =
|
||||
XmlUtilities.parseBoundedIntAttr(regMappingElem, "dwarf", 0, Integer.MAX_VALUE);
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFNumericAttribute;
|
||||
|
||||
|
||||
+3
-2
@@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.dwarf;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFForm;
|
||||
import ghidra.app.util.bin.format.dwarf.sectionprovider.DWARFSectionNames;
|
||||
|
||||
@@ -29,7 +29,7 @@ import ghidra.app.util.bin.format.dwarf.sectionprovider.DWARFSectionNames;
|
||||
* Elements in the table are referred to by index via {@link DWARFForm#DW_FORM_strx} and friends.
|
||||
* <p>
|
||||
* The table's {@link #getFirstElementOffset()} is referred to by a compUnit's
|
||||
* {@link DWARFAttribute#DW_AT_str_offsets_base} value.
|
||||
* {@link DWARFAttributeId#DW_AT_str_offsets_base} value.
|
||||
*/
|
||||
public class DWARFStringOffsetTableHeader extends DWARFIndirectTableHeader {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class DWARFStringOffsetTableHeader extends DWARFIndirectTableHeader {
|
||||
* Reads a string offset table header (found in the .debug_str_offsets section)
|
||||
*
|
||||
* @param reader {@link BinaryReader}
|
||||
* @param defaultIntSize size in bytes of integers
|
||||
* @return new {@link DWARFStringOffsetTableHeader} instance
|
||||
* @throws IOException if error reading
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -59,9 +59,9 @@ public class DWARFUtil {
|
||||
* <p>
|
||||
* Can be thought of as an enum numeric value to do a name lookup.
|
||||
*
|
||||
* @param clazz
|
||||
* @param value
|
||||
* @return
|
||||
* @param clazz 'enum' class that contains the "public static final" values
|
||||
* @param value value to lookup
|
||||
* @return string name of value 'enum'
|
||||
*/
|
||||
public static String toString(Class<?> clazz, long value) {
|
||||
Field field = getStaticFinalFieldWithValue(clazz, value);
|
||||
@@ -107,8 +107,8 @@ public class DWARFUtil {
|
||||
* For example, "_ZN19class1_inline_funcs3fooEv" ->
|
||||
* [19 chars]'class1_inline_funcs', [3 chars]'foo'
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
* @param s mangled string
|
||||
* @return list of elements extracted from mangled string
|
||||
*/
|
||||
public static List<String> parseMangledNestings(String s) {
|
||||
List<String> results = new ArrayList<>();
|
||||
@@ -140,7 +140,7 @@ public class DWARFUtil {
|
||||
/**
|
||||
* Try to find gnu mangled name nesting info in a DIE's children's linkage strings.
|
||||
*
|
||||
* @param die
|
||||
* @param die {@link DebugInfoEntry} record
|
||||
* @return a list of string of nesting names, ending with what should be the DIE parameter's
|
||||
* name.
|
||||
*/
|
||||
@@ -393,7 +393,7 @@ public class DWARFUtil {
|
||||
}
|
||||
|
||||
DIEAggregate funcDIEA = paramDIEA.getParent();
|
||||
DWARFAttributeValue dwATObjectPointer = funcDIEA.getAttribute(DW_AT_object_pointer);
|
||||
DWARFAttributeValue dwATObjectPointer = funcDIEA.findValue(DW_AT_object_pointer);
|
||||
if (dwATObjectPointer != null && dwATObjectPointer instanceof DWARFNumericAttribute dnum &&
|
||||
paramDIEA.hasOffset(dnum.getUnsignedValue())) {
|
||||
return true;
|
||||
|
||||
+2
-3
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute;
|
||||
import ghidra.app.util.bin.format.dwarf.expression.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
@@ -321,7 +320,7 @@ public class DWARFVariable {
|
||||
return false;
|
||||
}
|
||||
if (res.getAddress().getOffset() == 0) {
|
||||
if (diea.hasAttribute(DWARFAttribute.DW_AT_const_value)) {
|
||||
if (diea.hasAttribute(DW_AT_const_value)) {
|
||||
// skip without complaining global vars with a const value and bad location expression
|
||||
return false;
|
||||
}
|
||||
|
||||
+32
-30
@@ -20,7 +20,7 @@ import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.*;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.AttrDef;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.AttrDef;
|
||||
import ghidra.program.model.data.LEB128;
|
||||
|
||||
/**
|
||||
@@ -185,15 +185,19 @@ public class DebugInfoEntry {
|
||||
*
|
||||
* @param attribIndex index (0..count)
|
||||
* @return {@link DWARFAttributeValue}
|
||||
* @throws IOException if error reading the value
|
||||
*/
|
||||
public DWARFAttributeValue getAttributeValue(int attribIndex) throws IOException {
|
||||
public DWARFAttributeValue getAttributeValue(int attribIndex) {
|
||||
if (attributes[attribIndex] == null) {
|
||||
BinaryReader reader = getProgram().getReaderForCompUnit(compilationUnit)
|
||||
.clone(offset + attrOffsets[attribIndex]);
|
||||
DWARFFormContext context = new DWARFFormContext(reader, compilationUnit,
|
||||
abbreviation.getAttributeAt(attribIndex));
|
||||
attributes[attribIndex] = context.def().getAttributeForm().readValue(context);
|
||||
try {
|
||||
attributes[attribIndex] = context.def().getAttributeForm().readValue(context);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return new DWARFMissingAttributeValue();
|
||||
}
|
||||
}
|
||||
return attributes[attribIndex];
|
||||
}
|
||||
@@ -202,34 +206,41 @@ public class DebugInfoEntry {
|
||||
attributes[index] = attrVal;
|
||||
}
|
||||
|
||||
private DWARFAttributeValue getAttributeValueUnchecked(int attribIndex) {
|
||||
try {
|
||||
return getAttributeValue(attribIndex);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the list of attributes for a specific attribute, by id.
|
||||
*
|
||||
* @param attributeId {@link DWARFAttribute}
|
||||
* @return {@link DWARFAttributeValue}, or null if not found
|
||||
* @param attrId {@link DWARFAttributeId}
|
||||
* @return {@link DWARFAttribute}, or null if not found
|
||||
*/
|
||||
public DWARFAttributeValue findAttribute(DWARFAttribute attributeId) {
|
||||
public DWARFAttribute findAttribute(DWARFAttributeId attrId) {
|
||||
AttrDef[] attrDefs = abbreviation.getAttributes();
|
||||
for (int i = 0; i < attrDefs.length; i++) {
|
||||
AttrDef attrDef = attrDefs[i];
|
||||
if (attrDef.getAttributeId() == attributeId) {
|
||||
return getAttributeValueUnchecked(i);
|
||||
if (attrDef.getAttributeId() == attrId) {
|
||||
return new DWARFAttribute(this, attrDef, getAttributeValue(i));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the abbreviation of this DIE.
|
||||
* {@return the specified DWARFAttribute, by index}
|
||||
* @param index 0..count
|
||||
*/
|
||||
public DWARFAttribute getAttribute(int index) {
|
||||
return new DWARFAttribute(this, getAttributeDef(index), getAttributeValue(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the DWARFAttributeDef of the specified attribute, by index}
|
||||
* @param index 0..count
|
||||
*/
|
||||
public AttrDef getAttributeDef(int index) {
|
||||
return abbreviation.getAttributeAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the abbreviation (schema) of this DIE.
|
||||
* @return the abbreviation of this DIE
|
||||
*/
|
||||
public DWARFAbbreviation getAbbreviation() {
|
||||
@@ -290,17 +301,8 @@ public class DebugInfoEntry {
|
||||
}
|
||||
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
buffer.append("\t\t");
|
||||
DWARFAttributeValue attribVal = getAttributeValueUnchecked(i);
|
||||
if (attribVal != null) {
|
||||
buffer.append(attribVal.toString(compilationUnit));
|
||||
}
|
||||
else {
|
||||
AttrDef attrDef = abbreviation.getAttributeAt(i);
|
||||
buffer.append("%s : %s = <missing>".formatted(attrDef.getAttributeName(),
|
||||
attrDef.getAttributeForm()));
|
||||
}
|
||||
buffer.append("\n");
|
||||
DWARFAttribute tmp = getAttribute(i);
|
||||
buffer.append("\t\t").append(tmp.toString()).append("\n");
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
|
||||
+80
-229
@@ -15,251 +15,102 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf.attribs;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeClass.*;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
import ghidra.app.util.bin.format.dwarf.DebugInfoEntry;
|
||||
|
||||
/**
|
||||
* Defines the names and numeric ids of known DWARF attributes. Well-known attributes are also
|
||||
* constrained to certain value types (see {@link DWARFAttributeClass}).
|
||||
* <p>
|
||||
* Users of this enum should be tolerant of unknown attribute id values. See
|
||||
* {@link AttrDef#getRawAttributeId()}.
|
||||
* Represents an attribute contained in a DIE.
|
||||
*/
|
||||
public enum DWARFAttribute {
|
||||
DW_AT_sibling(0x1, reference),
|
||||
DW_AT_location(0x2, exprloc, loclist, block, constant),
|
||||
DW_AT_name(0x3, string),
|
||||
DW_AT_ordering(0x9, constant),
|
||||
//DW_AT_subscr_data(0xa),
|
||||
DW_AT_byte_size(0xb, constant, exprloc, reference),
|
||||
DW_AT_bit_offset(0xc), // dwarf-3
|
||||
DW_AT_bit_size(0xd, constant, exprloc, reference),
|
||||
//DW_AT_element_list(0xf),
|
||||
DW_AT_stmt_list(0x10, lineptr, constant),
|
||||
DW_AT_low_pc(0x11, address),
|
||||
DW_AT_high_pc(0x12, address, constant),
|
||||
DW_AT_language(0x13, constant),
|
||||
//DW_AT_member(0x14),
|
||||
DW_AT_discr(0x15, reference),
|
||||
DW_AT_discr_value(0x16, constant),
|
||||
DW_AT_visibility(0x17, constant),
|
||||
DW_AT_import(0x18, reference),
|
||||
DW_AT_string_length(0x19, exprloc, loclist, reference),
|
||||
DW_AT_common_reference(0x1a, reference),
|
||||
DW_AT_comp_dir(0x1b, string),
|
||||
DW_AT_const_value(0x1c, block, constant, string),
|
||||
DW_AT_containing_type(0x1d, reference),
|
||||
DW_AT_default_value(0x1e, constant, reference, flag),
|
||||
DW_AT_inline(0x20, constant),
|
||||
DW_AT_is_optional(0x21, flag),
|
||||
DW_AT_lower_bound(0x22, constant, exprloc, reference),
|
||||
DW_AT_producer(0x25, string),
|
||||
DW_AT_prototyped(0x27, flag),
|
||||
DW_AT_return_addr(0x2a, exprloc, loclist),
|
||||
DW_AT_start_scope(0x2c, constant, rnglist),
|
||||
DW_AT_bit_stride(0x2e, constant, exprloc, reference),
|
||||
DW_AT_upper_bound(0x2f, constant, exprloc, reference),
|
||||
DW_AT_abstract_origin(0x31, reference),
|
||||
DW_AT_accessibility(0x32, constant),
|
||||
DW_AT_address_class(0x33, constant),
|
||||
DW_AT_artificial(0x34, flag),
|
||||
DW_AT_base_types(0x35, reference),
|
||||
DW_AT_calling_convention(0x36, constant),
|
||||
DW_AT_count(0x37, constant, exprloc, reference),
|
||||
DW_AT_data_member_location(0x38, constant, exprloc, loclist, block),
|
||||
DW_AT_decl_column(0x39, constant),
|
||||
DW_AT_decl_file(0x3a, constant),
|
||||
DW_AT_decl_line(0x3b, constant),
|
||||
DW_AT_declaration(0x3c, flag),
|
||||
DW_AT_discr_list(0x3d, block),
|
||||
DW_AT_encoding(0x3e, constant),
|
||||
DW_AT_external(0x3f, flag),
|
||||
DW_AT_frame_base(0x40, exprloc, loclist, block, constant),
|
||||
DW_AT_friend(0x41, reference),
|
||||
DW_AT_identifier_case(0x42, constant),
|
||||
DW_AT_macro_info(0x43, macptr),
|
||||
DW_AT_namelist_item(0x44, reference),
|
||||
DW_AT_priority(0x45, reference),
|
||||
DW_AT_segment(0x46, exprloc, loclist),
|
||||
DW_AT_specification(0x47, reference),
|
||||
DW_AT_static_link(0x48, exprloc, loclist),
|
||||
DW_AT_type(0x49, reference),
|
||||
DW_AT_use_location(0x4a, exprloc, loclist),
|
||||
DW_AT_variable_parameter(0x4b, flag),
|
||||
DW_AT_virtuality(0x4c, constant),
|
||||
DW_AT_vtable_elem_location(0x4d, exprloc, loclist, block),
|
||||
DW_AT_allocated(0x4e, constant, exprloc, reference),
|
||||
DW_AT_associated(0x4f, constant, exprloc, reference),
|
||||
DW_AT_data_location(0x50, exprloc),
|
||||
DW_AT_byte_stride(0x51, constant, exprloc, reference),
|
||||
DW_AT_entry_pc(0x52, address, constant),
|
||||
DW_AT_use_UTF8(0x53, flag),
|
||||
DW_AT_extension(0x54, reference),
|
||||
DW_AT_ranges(0x55, rnglist, constant),
|
||||
DW_AT_trampoline(0x56, address, flag, reference, string),
|
||||
DW_AT_call_column(0x57, constant),
|
||||
DW_AT_call_file(0x58, constant),
|
||||
DW_AT_call_line(0x59, constant),
|
||||
DW_AT_description(0x5a, string),
|
||||
DW_AT_binary_scale(0x5b, constant),
|
||||
DW_AT_decimal_scale(0x5c, constant),
|
||||
DW_AT_small(0x5d, reference),
|
||||
DW_AT_decimal_sign(0x5e, constant),
|
||||
DW_AT_digit_count(0x5f, constant),
|
||||
DW_AT_picture_string(0x60, string),
|
||||
DW_AT_mutable(0x61, flag),
|
||||
DW_AT_threads_scaled(0x62, flag),
|
||||
DW_AT_explicit(0x63, flag),
|
||||
DW_AT_object_pointer(0x64, reference),
|
||||
DW_AT_endianity(0x65, constant),
|
||||
DW_AT_elemental(0x66, flag),
|
||||
DW_AT_pure(0x67, flag),
|
||||
DW_AT_recursive(0x68, flag),
|
||||
DW_AT_signature(0x69, reference),
|
||||
DW_AT_main_subprogram(0x6a, flag),
|
||||
DW_AT_data_bit_offset(0x6b, constant),
|
||||
DW_AT_const_expr(0x6c, flag),
|
||||
DW_AT_enum_class(0x6d, flag),
|
||||
DW_AT_linkage_name(0x6e, string),
|
||||
DW_AT_string_length_bit_size(0x6f, constant),
|
||||
DW_AT_string_length_byte_size(0x70, constant),
|
||||
DW_AT_rank(0x71, constant, exprloc),
|
||||
DW_AT_str_offsets_base(0x72, stroffsetsptr),
|
||||
DW_AT_addr_base(0x73, addrptr),
|
||||
DW_AT_rnglists_base(0x74, rnglistsptr),
|
||||
// 0x75 reserved, unused
|
||||
DW_AT_dwo_name(0x76, string),
|
||||
DW_AT_reference(0x77, flag),
|
||||
DW_AT_rvalue_reference(0x78, flag),
|
||||
DW_AT_macros(0x79, macptr),
|
||||
DW_AT_call_all_calls(0x7a, flag),
|
||||
DW_AT_call_all_source_calls(0x7b, flag),
|
||||
DW_AT_call_all_tail_calls(0x7c, flag),
|
||||
DW_AT_call_return_pc(0x7d, address),
|
||||
DW_AT_call_value(0x7e, exprloc),
|
||||
DW_AT_call_origin(0x7f, reference),
|
||||
DW_AT_call_parameter(0x80, reference),
|
||||
DW_AT_call_pc(0x81, address),
|
||||
DW_AT_call_tail_call(0x82, flag),
|
||||
DW_AT_call_target(0x83, exprloc),
|
||||
DW_AT_call_target_clobbered(0x84, exprloc),
|
||||
DW_AT_call_data_location(0x85, exprloc),
|
||||
DW_AT_call_data_value(0x86, exprloc),
|
||||
DW_AT_noreturn(0x87, flag),
|
||||
DW_AT_alignment(0x88, constant),
|
||||
DW_AT_export_symbols(0x89, flag),
|
||||
DW_AT_deleted(0x8a, flag),
|
||||
DW_AT_defaulted(0x8b, constant),
|
||||
DW_AT_loclists_base(0x8c, loclistsptr),
|
||||
public class DWARFAttribute {
|
||||
|
||||
DW_AT_lo_user(0x2000),
|
||||
DW_AT_hi_user(0x3fff),
|
||||
DW_AT_MIPS_linkage_name(0x2007),
|
||||
protected final DebugInfoEntry die;
|
||||
protected final DWARFAttributeId.AttrDef def;
|
||||
protected final DWARFAttributeValue value;
|
||||
|
||||
// GNU DebugFission stuff
|
||||
DW_AT_GNU_dwo_name(0x2130),
|
||||
DW_AT_GNU_dwo_id(0x2131),
|
||||
DW_AT_GNU_ranges_base(0x2132),
|
||||
DW_AT_GNU_addr_base(0x2133),
|
||||
DW_AT_GNU_pubnames(0x2134),
|
||||
DW_AT_GNU_pubtypes(0x2135),
|
||||
// end GNU DebugFission
|
||||
|
||||
// Golang
|
||||
DW_AT_go_kind(0x2900),
|
||||
DW_AT_go_key(0x2901),
|
||||
DW_AT_go_elem(0x2902),
|
||||
DW_AT_go_embedded_field(0x2903),
|
||||
DW_AT_go_runtime_type(0x2904),
|
||||
DW_AT_go_package_name(0x2905),
|
||||
DW_AT_go_dict_index(0x2906),
|
||||
// end Golang
|
||||
|
||||
// Apple proprietary tags
|
||||
DW_AT_APPLE_ptrauth_key(0x3e04),
|
||||
DW_AT_APPLE_ptrauth_address_discriminated(0x3e05),
|
||||
DW_AT_APPLE_ptrauth_extra_discriminator(0x3e06),
|
||||
DW_AT_APPLE_omit_frame_ptr(0x3fe7),
|
||||
DW_AT_APPLE_optimized(0x3fe1);
|
||||
// end Apple proprietary tags
|
||||
|
||||
private int id;
|
||||
private Set<DWARFAttributeClass> attributeClass;
|
||||
|
||||
DWARFAttribute(int id, DWARFAttributeClass... attributeClass) {
|
||||
this.id = id;
|
||||
this.attributeClass = EnumSet.noneOf(DWARFAttributeClass.class);
|
||||
this.attributeClass.addAll(List.of(attributeClass));
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Set<DWARFAttributeClass> getAttributeClass() {
|
||||
return attributeClass;
|
||||
}
|
||||
|
||||
public static final int EOL = 0; // value used as end of attributespec list
|
||||
|
||||
public static DWARFAttribute of(int attributeInt) {
|
||||
return lookupMap.get(attributeInt);
|
||||
}
|
||||
|
||||
private static Map<Integer, DWARFAttribute> lookupMap = buildLookup();
|
||||
|
||||
private static Map<Integer, DWARFAttribute> buildLookup() {
|
||||
Map<Integer, DWARFAttribute> result = new HashMap<>();
|
||||
for (DWARFAttribute attr : values()) {
|
||||
result.put(attr.id, attr);
|
||||
}
|
||||
return result;
|
||||
public DWARFAttribute(DebugInfoEntry die, DWARFAttributeId.AttrDef def,
|
||||
DWARFAttributeValue value) {
|
||||
this.die = die;
|
||||
this.def = def;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents how a specific DWARF attribute is stored in a DIE record.
|
||||
* {@return the DIE that contains this attribute}
|
||||
*/
|
||||
public static class AttrDef extends DWARFAttributeDef<DWARFAttribute> {
|
||||
public DebugInfoEntry getDIE() {
|
||||
return die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a {@link DWARFAttribute.AttrDef} instance from the {@link BinaryReader reader}.
|
||||
* <p>
|
||||
* Returns a null if its a end-of-list marker.
|
||||
*
|
||||
* @param reader {@link BinaryReader} abbr stream
|
||||
* @return new {@link AttrDef}, or null if end-of-list
|
||||
* @throws IOException if error reading
|
||||
*/
|
||||
public static AttrDef read(BinaryReader reader) throws IOException {
|
||||
DWARFAttributeDef<DWARFAttribute> tmp =
|
||||
DWARFAttributeDef.read(reader, DWARFAttribute::of);
|
||||
if (tmp == null) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* {@return the compilation unit that contains the attribute's DIE}
|
||||
*/
|
||||
public DWARFCompilationUnit getCU() {
|
||||
return die.getCompilationUnit();
|
||||
}
|
||||
|
||||
return new AttrDef(tmp.getAttributeId(), tmp.getRawAttributeId(),
|
||||
tmp.getAttributeForm(), tmp.getImplicitValue());
|
||||
/**
|
||||
* {@return the value of this attribute}
|
||||
*/
|
||||
public DWARFAttributeValue getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the value of this attribute, as a specific type}
|
||||
* @param <T> expected type of the attribute value
|
||||
* @param clazz class of the expected type of the attribute value
|
||||
*/
|
||||
public <T extends DWARFAttributeValue> T getValue(Class<T> clazz) {
|
||||
if (clazz.isAssignableFrom(value.getClass())) {
|
||||
return clazz.cast(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttrDef(DWARFAttribute attributeId, int rawAttributeId,
|
||||
DWARFForm attributeForm, long implicitValue) {
|
||||
super(attributeId, rawAttributeId, attributeForm, implicitValue);
|
||||
/**
|
||||
* {@return string name of this attribute's identifier (eg. "DW_AT_high_pc")}
|
||||
*/
|
||||
public String getAttributeName() {
|
||||
return def.getAttributeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the serialization format identifier of this attribute (eg. DW_FORM_ref4)}
|
||||
*/
|
||||
public DWARFForm getAttributeForm() {
|
||||
return def.getAttributeForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the value of this attribute, as a formatted string}
|
||||
*/
|
||||
public String getValueString() {
|
||||
return value.getValueString(die.getCompilationUnit(), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s : %s = %s".formatted(getAttributeName(), getAttributeForm(), getValueString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(def, die, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRawAttributeIdDescription() {
|
||||
return "DW_AT_???? %d (0x%x)".formatted(rawAttributeId, rawAttributeId);
|
||||
if (!(obj instanceof DWARFAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttrDef withForm(DWARFForm newForm) {
|
||||
return new AttrDef(attributeId, rawAttributeId, newForm, implicitValue);
|
||||
}
|
||||
|
||||
DWARFAttribute other = (DWARFAttribute) obj;
|
||||
return Objects.equals(def, other.def) && Objects.equals(die, other.die) &&
|
||||
Objects.equals(value, other.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf.attribs;
|
||||
|
||||
/**
|
||||
* Categories that a DWARF attribute value may belong to.
|
||||
* Categories that a DWARF attribute id may belong to.
|
||||
*/
|
||||
public enum DWARFAttributeClass {
|
||||
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class DWARFAttributeDef<E extends Enum<E>> {
|
||||
int attributeId = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
|
||||
int formId = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
|
||||
|
||||
if (attributeId == DWARFAttribute.EOL && formId == DWARFForm.EOL) {
|
||||
if (attributeId == DWARFAttributeId.EOL && formId == DWARFForm.EOL) {
|
||||
// end of attributespec list
|
||||
return null;
|
||||
}
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
/* ###
|
||||
* 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.dwarf.attribs;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeClass.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
|
||||
/**
|
||||
* Defines the names and numeric ids of known DWARF attributes. Well-known attributes are also
|
||||
* constrained to certain value types (see {@link DWARFAttributeClass}).
|
||||
* <p>
|
||||
* Users of this enum should be tolerant of unknown attribute id values. See
|
||||
* {@link AttrDef#getRawAttributeId()}.
|
||||
*/
|
||||
public enum DWARFAttributeId {
|
||||
DW_AT_sibling(0x1, reference),
|
||||
DW_AT_location(0x2, exprloc, loclist, block, constant),
|
||||
DW_AT_name(0x3, string),
|
||||
DW_AT_ordering(0x9, constant),
|
||||
//DW_AT_subscr_data(0xa),
|
||||
DW_AT_byte_size(0xb, constant, exprloc, reference),
|
||||
DW_AT_bit_offset(0xc), // dwarf-3
|
||||
DW_AT_bit_size(0xd, constant, exprloc, reference),
|
||||
//DW_AT_element_list(0xf),
|
||||
DW_AT_stmt_list(0x10, lineptr, constant),
|
||||
DW_AT_low_pc(0x11, address),
|
||||
DW_AT_high_pc(0x12, address, constant),
|
||||
DW_AT_language(0x13, constant),
|
||||
//DW_AT_member(0x14),
|
||||
DW_AT_discr(0x15, reference),
|
||||
DW_AT_discr_value(0x16, constant),
|
||||
DW_AT_visibility(0x17, constant),
|
||||
DW_AT_import(0x18, reference),
|
||||
DW_AT_string_length(0x19, exprloc, loclist, reference),
|
||||
DW_AT_common_reference(0x1a, reference),
|
||||
DW_AT_comp_dir(0x1b, string),
|
||||
DW_AT_const_value(0x1c, block, constant, string),
|
||||
DW_AT_containing_type(0x1d, reference),
|
||||
DW_AT_default_value(0x1e, constant, reference, flag),
|
||||
DW_AT_inline(0x20, constant),
|
||||
DW_AT_is_optional(0x21, flag),
|
||||
DW_AT_lower_bound(0x22, constant, exprloc, reference),
|
||||
DW_AT_producer(0x25, string),
|
||||
DW_AT_prototyped(0x27, flag),
|
||||
DW_AT_return_addr(0x2a, exprloc, loclist),
|
||||
DW_AT_start_scope(0x2c, constant, rnglist),
|
||||
DW_AT_bit_stride(0x2e, constant, exprloc, reference),
|
||||
DW_AT_upper_bound(0x2f, constant, exprloc, reference),
|
||||
DW_AT_abstract_origin(0x31, reference),
|
||||
DW_AT_accessibility(0x32, constant),
|
||||
DW_AT_address_class(0x33, constant),
|
||||
DW_AT_artificial(0x34, flag),
|
||||
DW_AT_base_types(0x35, reference),
|
||||
DW_AT_calling_convention(0x36, constant),
|
||||
DW_AT_count(0x37, constant, exprloc, reference),
|
||||
DW_AT_data_member_location(0x38, constant, exprloc, loclist, block),
|
||||
DW_AT_decl_column(0x39, constant),
|
||||
DW_AT_decl_file(0x3a, constant),
|
||||
DW_AT_decl_line(0x3b, constant),
|
||||
DW_AT_declaration(0x3c, flag),
|
||||
DW_AT_discr_list(0x3d, block),
|
||||
DW_AT_encoding(0x3e, constant),
|
||||
DW_AT_external(0x3f, flag),
|
||||
DW_AT_frame_base(0x40, exprloc, loclist, block, constant),
|
||||
DW_AT_friend(0x41, reference),
|
||||
DW_AT_identifier_case(0x42, constant),
|
||||
DW_AT_macro_info(0x43, macptr),
|
||||
DW_AT_namelist_item(0x44, reference),
|
||||
DW_AT_priority(0x45, reference),
|
||||
DW_AT_segment(0x46, exprloc, loclist),
|
||||
DW_AT_specification(0x47, reference),
|
||||
DW_AT_static_link(0x48, exprloc, loclist),
|
||||
DW_AT_type(0x49, reference),
|
||||
DW_AT_use_location(0x4a, exprloc, loclist),
|
||||
DW_AT_variable_parameter(0x4b, flag),
|
||||
DW_AT_virtuality(0x4c, constant),
|
||||
DW_AT_vtable_elem_location(0x4d, exprloc, loclist, block),
|
||||
DW_AT_allocated(0x4e, constant, exprloc, reference),
|
||||
DW_AT_associated(0x4f, constant, exprloc, reference),
|
||||
DW_AT_data_location(0x50, exprloc),
|
||||
DW_AT_byte_stride(0x51, constant, exprloc, reference),
|
||||
DW_AT_entry_pc(0x52, address, constant),
|
||||
DW_AT_use_UTF8(0x53, flag),
|
||||
DW_AT_extension(0x54, reference),
|
||||
DW_AT_ranges(0x55, rnglist, constant),
|
||||
DW_AT_trampoline(0x56, address, flag, reference, string),
|
||||
DW_AT_call_column(0x57, constant),
|
||||
DW_AT_call_file(0x58, constant),
|
||||
DW_AT_call_line(0x59, constant),
|
||||
DW_AT_description(0x5a, string),
|
||||
DW_AT_binary_scale(0x5b, constant),
|
||||
DW_AT_decimal_scale(0x5c, constant),
|
||||
DW_AT_small(0x5d, reference),
|
||||
DW_AT_decimal_sign(0x5e, constant),
|
||||
DW_AT_digit_count(0x5f, constant),
|
||||
DW_AT_picture_string(0x60, string),
|
||||
DW_AT_mutable(0x61, flag),
|
||||
DW_AT_threads_scaled(0x62, flag),
|
||||
DW_AT_explicit(0x63, flag),
|
||||
DW_AT_object_pointer(0x64, reference),
|
||||
DW_AT_endianity(0x65, constant),
|
||||
DW_AT_elemental(0x66, flag),
|
||||
DW_AT_pure(0x67, flag),
|
||||
DW_AT_recursive(0x68, flag),
|
||||
DW_AT_signature(0x69, reference),
|
||||
DW_AT_main_subprogram(0x6a, flag),
|
||||
DW_AT_data_bit_offset(0x6b, constant),
|
||||
DW_AT_const_expr(0x6c, flag),
|
||||
DW_AT_enum_class(0x6d, flag),
|
||||
DW_AT_linkage_name(0x6e, string),
|
||||
DW_AT_string_length_bit_size(0x6f, constant),
|
||||
DW_AT_string_length_byte_size(0x70, constant),
|
||||
DW_AT_rank(0x71, constant, exprloc),
|
||||
DW_AT_str_offsets_base(0x72, stroffsetsptr),
|
||||
DW_AT_addr_base(0x73, addrptr),
|
||||
DW_AT_rnglists_base(0x74, rnglistsptr),
|
||||
// 0x75 reserved, unused
|
||||
DW_AT_dwo_name(0x76, string),
|
||||
DW_AT_reference(0x77, flag),
|
||||
DW_AT_rvalue_reference(0x78, flag),
|
||||
DW_AT_macros(0x79, macptr),
|
||||
DW_AT_call_all_calls(0x7a, flag),
|
||||
DW_AT_call_all_source_calls(0x7b, flag),
|
||||
DW_AT_call_all_tail_calls(0x7c, flag),
|
||||
DW_AT_call_return_pc(0x7d, address),
|
||||
DW_AT_call_value(0x7e, exprloc),
|
||||
DW_AT_call_origin(0x7f, reference),
|
||||
DW_AT_call_parameter(0x80, reference),
|
||||
DW_AT_call_pc(0x81, address),
|
||||
DW_AT_call_tail_call(0x82, flag),
|
||||
DW_AT_call_target(0x83, exprloc),
|
||||
DW_AT_call_target_clobbered(0x84, exprloc),
|
||||
DW_AT_call_data_location(0x85, exprloc),
|
||||
DW_AT_call_data_value(0x86, exprloc),
|
||||
DW_AT_noreturn(0x87, flag),
|
||||
DW_AT_alignment(0x88, constant),
|
||||
DW_AT_export_symbols(0x89, flag),
|
||||
DW_AT_deleted(0x8a, flag),
|
||||
DW_AT_defaulted(0x8b, constant),
|
||||
DW_AT_loclists_base(0x8c, loclistsptr),
|
||||
|
||||
DW_AT_lo_user(0x2000),
|
||||
DW_AT_hi_user(0x3fff),
|
||||
DW_AT_MIPS_linkage_name(0x2007),
|
||||
|
||||
// GNU call site extension
|
||||
DW_AT_GNU_call_site_value(0x2111),
|
||||
DW_AT_GNU_call_site_data_value(0x2112),
|
||||
DW_AT_GNU_call_site_target(0x2113),
|
||||
DW_AT_GNU_call_site_target_clobbered(0x2114),
|
||||
DW_AT_GNU_tail_call(0x2115),
|
||||
DW_AT_GNU_all_tail_call_sites(0x2116),
|
||||
DW_AT_GNU_all_call_sites(0x2117),
|
||||
DW_AT_GNU_all_source_call_sites(0x2118),
|
||||
|
||||
DW_AT_GNU_macros(0x2119),
|
||||
|
||||
DW_AT_GNU_deleted(0x211a), // c++ deleted special member func
|
||||
|
||||
// GNU DebugFission stuff
|
||||
DW_AT_GNU_dwo_name(0x2130),
|
||||
DW_AT_GNU_dwo_id(0x2131),
|
||||
DW_AT_GNU_ranges_base(0x2132),
|
||||
DW_AT_GNU_addr_base(0x2133),
|
||||
DW_AT_GNU_pubnames(0x2134),
|
||||
DW_AT_GNU_pubtypes(0x2135),
|
||||
// end GNU DebugFission
|
||||
|
||||
DW_AT_GNU_discriminator(0x2136),
|
||||
DW_AT_GNU_locviews(0x2137),
|
||||
DW_AT_GNU_entry_view(0x2138),
|
||||
|
||||
DW_AT_GNU_annotation(0x2139),
|
||||
|
||||
// Golang
|
||||
DW_AT_go_kind(0x2900),
|
||||
DW_AT_go_key(0x2901),
|
||||
DW_AT_go_elem(0x2902),
|
||||
DW_AT_go_embedded_field(0x2903),
|
||||
DW_AT_go_runtime_type(0x2904),
|
||||
DW_AT_go_package_name(0x2905),
|
||||
DW_AT_go_dict_index(0x2906),
|
||||
// end Golang
|
||||
|
||||
// Apple proprietary tags
|
||||
DW_AT_APPLE_ptrauth_key(0x3e04),
|
||||
DW_AT_APPLE_ptrauth_address_discriminated(0x3e05),
|
||||
DW_AT_APPLE_ptrauth_extra_discriminator(0x3e06),
|
||||
DW_AT_APPLE_omit_frame_ptr(0x3fe7),
|
||||
DW_AT_APPLE_optimized(0x3fe1);
|
||||
// end Apple proprietary tags
|
||||
|
||||
private int id;
|
||||
private Set<DWARFAttributeClass> attributeClass;
|
||||
|
||||
DWARFAttributeId(int id, DWARFAttributeClass... attributeClass) {
|
||||
this.id = id;
|
||||
this.attributeClass = EnumSet.noneOf(DWARFAttributeClass.class);
|
||||
this.attributeClass.addAll(List.of(attributeClass));
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Set<DWARFAttributeClass> getAttributeClass() {
|
||||
return attributeClass;
|
||||
}
|
||||
|
||||
public static final int EOL = 0; // value used as end of attributespec list
|
||||
|
||||
public static DWARFAttributeId of(int attributeInt) {
|
||||
return lookupMap.get(attributeInt);
|
||||
}
|
||||
|
||||
private static Map<Integer, DWARFAttributeId> lookupMap = buildLookup();
|
||||
|
||||
private static Map<Integer, DWARFAttributeId> buildLookup() {
|
||||
Map<Integer, DWARFAttributeId> result = new HashMap<>();
|
||||
for (DWARFAttributeId attr : values()) {
|
||||
result.put(attr.id, attr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents how a specific DWARF attribute is stored in a DIE record.
|
||||
*/
|
||||
public static class AttrDef extends DWARFAttributeDef<DWARFAttributeId> {
|
||||
|
||||
/**
|
||||
* Reads a {@link DWARFAttributeId.AttrDef} instance from the {@link BinaryReader reader}.
|
||||
* <p>
|
||||
* Returns a null if its a end-of-list marker.
|
||||
*
|
||||
* @param reader {@link BinaryReader} abbr stream
|
||||
* @return new {@link AttrDef}, or null if end-of-list
|
||||
* @throws IOException if error reading
|
||||
*/
|
||||
public static AttrDef read(BinaryReader reader) throws IOException {
|
||||
DWARFAttributeDef<DWARFAttributeId> tmp =
|
||||
DWARFAttributeDef.read(reader, DWARFAttributeId::of);
|
||||
if (tmp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AttrDef(tmp.getAttributeId(), tmp.getRawAttributeId(),
|
||||
tmp.getAttributeForm(), tmp.getImplicitValue());
|
||||
}
|
||||
|
||||
public AttrDef(DWARFAttributeId attributeId, int rawAttributeId,
|
||||
DWARFForm attributeForm, long implicitValue) {
|
||||
super(attributeId, rawAttributeId, attributeForm, implicitValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRawAttributeIdDescription() {
|
||||
return "DW_AT_???? %d (0x%x)".formatted(rawAttributeId, rawAttributeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttrDef withForm(DWARFForm newForm) {
|
||||
return new AttrDef(attributeId, rawAttributeId, newForm, implicitValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+3
-24
@@ -18,30 +18,9 @@ package ghidra.app.util.bin.format.dwarf.attribs;
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
|
||||
/**
|
||||
* Base class for all DWARF attribute value implementations.
|
||||
* Common methods for all DWARF attribute value implementations.
|
||||
*/
|
||||
public abstract class DWARFAttributeValue {
|
||||
|
||||
protected final DWARFAttributeDef<?> def;
|
||||
|
||||
public DWARFAttributeValue(DWARFAttributeDef<?> def) {
|
||||
this.def = def;
|
||||
}
|
||||
|
||||
public DWARFForm getAttributeForm() {
|
||||
return def.getAttributeForm();
|
||||
}
|
||||
|
||||
public String getAttributeName() {
|
||||
return def.getAttributeName();
|
||||
}
|
||||
|
||||
public String getValueString(DWARFCompilationUnit cu) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String toString(DWARFCompilationUnit compilationUnit) {
|
||||
return toString();
|
||||
}
|
||||
public interface DWARFAttributeValue {
|
||||
|
||||
String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def);
|
||||
}
|
||||
|
||||
+5
-7
@@ -21,11 +21,10 @@ import ghidra.util.NumericUtilities;
|
||||
/**
|
||||
* DWARF attribute with binary bytes.
|
||||
*/
|
||||
public class DWARFBlobAttribute extends DWARFAttributeValue {
|
||||
public class DWARFBlobAttribute implements DWARFAttributeValue {
|
||||
private final byte[] bytes;
|
||||
|
||||
public DWARFBlobAttribute(byte[] bytes, DWARFAttributeDef<?> def) {
|
||||
super(def);
|
||||
public DWARFBlobAttribute(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@@ -38,13 +37,12 @@ public class DWARFBlobAttribute extends DWARFAttributeValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString(DWARFCompilationUnit cu) {
|
||||
return NumericUtilities.convertBytesToString(bytes, " ");
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
return "[%d]%s".formatted(bytes.length, NumericUtilities.convertBytesToString(bytes, " "));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s : %s = [%d]%s".formatted(getAttributeName(), getAttributeForm(), bytes.length,
|
||||
NumericUtilities.convertBytesToString(bytes, " "));
|
||||
return "[%d]%s".formatted(bytes.length, NumericUtilities.convertBytesToString(bytes, " "));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -20,11 +20,10 @@ import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
/**
|
||||
* DWARF boolean attribute.
|
||||
*/
|
||||
public class DWARFBooleanAttribute extends DWARFAttributeValue {
|
||||
public class DWARFBooleanAttribute implements DWARFAttributeValue {
|
||||
private final boolean value;
|
||||
|
||||
public DWARFBooleanAttribute(boolean value, DWARFAttributeDef<?> def) {
|
||||
super(def);
|
||||
public DWARFBooleanAttribute(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -33,12 +32,13 @@ public class DWARFBooleanAttribute extends DWARFAttributeValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString(DWARFCompilationUnit cu) {
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
return "%b".formatted(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s : %s = %s".formatted(getAttributeName(), getAttributeForm(), getValue());
|
||||
return "%b".formatted(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-65
@@ -1,65 +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.dwarf.attribs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* DWARF string attribute, where getting the value from the string table is deferred
|
||||
* until requested for the first time.
|
||||
*/
|
||||
public class DWARFDeferredStringAttribute extends DWARFStringAttribute {
|
||||
private long offset;
|
||||
|
||||
public DWARFDeferredStringAttribute(long offset, DWARFAttributeDef<?> def) {
|
||||
super(null, def);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(DWARFCompilationUnit cu) {
|
||||
if (value == null) {
|
||||
try {
|
||||
value = cu.getProgram().getString(getAttributeForm(), offset, cu);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(this, "error getting string value", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(DWARFCompilationUnit cu) {
|
||||
String str = value == null && cu != null ? getValue(cu) : value;
|
||||
str = str != null ? "\"%s\"".formatted(value) : "-missing-";
|
||||
return "%s : %s = %s (offset 0x%x)".formatted(getAttributeName(), getAttributeForm(), str,
|
||||
offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(null);
|
||||
}
|
||||
}
|
||||
+30
-38
@@ -38,9 +38,9 @@ public enum DWARFForm {
|
||||
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFNumericAttribute(
|
||||
context.reader().readNextUnsignedValue(context.compUnit().getPointerSize()),
|
||||
context.def());
|
||||
byte ptrSize = context.compUnit().getPointerSize();
|
||||
return new DWARFNumericAttribute(ptrSize * 8,
|
||||
context.reader().readNextUnsignedValue(ptrSize), false);
|
||||
}
|
||||
},
|
||||
DW_FORM_block2(0x3, DWARFForm.DYNAMIC_SIZE, block) {
|
||||
@@ -52,8 +52,7 @@ public enum DWARFForm {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
int length = context.reader().readNextUnsignedShort();
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length),
|
||||
context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length));
|
||||
}
|
||||
},
|
||||
DW_FORM_block4(0x4, DWARFForm.DYNAMIC_SIZE, block) {
|
||||
@@ -68,8 +67,7 @@ public enum DWARFForm {
|
||||
if (length < 0 || length > MAX_BLOCK4_SIZE) {
|
||||
throw new IOException("Invalid/bad dw_form_block4 size: " + length);
|
||||
}
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length),
|
||||
context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length));
|
||||
}
|
||||
},
|
||||
DW_FORM_data2(0x5, 2, constant),
|
||||
@@ -86,7 +84,7 @@ public enum DWARFForm {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
String s = context.reader().readNextString(context.dprog().getCharset(), 1);
|
||||
return new DWARFStringAttribute(s, context.def());
|
||||
return new DWARFStringAttribute(s);
|
||||
}
|
||||
},
|
||||
DW_FORM_block(0x9, DWARFForm.DYNAMIC_SIZE, block) {
|
||||
@@ -102,8 +100,7 @@ public enum DWARFForm {
|
||||
if (length < 0 || length > MAX_BLOCK4_SIZE) {
|
||||
throw new IOException("Invalid/bad dw_form_block size: " + length);
|
||||
}
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length),
|
||||
context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length));
|
||||
}
|
||||
},
|
||||
DW_FORM_block1(0xa, DWARFForm.DYNAMIC_SIZE, block) {
|
||||
@@ -116,30 +113,28 @@ public enum DWARFForm {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
int length = context.reader().readNextUnsignedByte();
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length),
|
||||
context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length));
|
||||
}
|
||||
},
|
||||
DW_FORM_data1(0xb, 1, constant),
|
||||
DW_FORM_flag(0xc, 1, flag) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFBooleanAttribute(context.reader().readNextByte() != 0, context.def());
|
||||
return new DWARFBooleanAttribute(context.reader().readNextByte() != 0);
|
||||
}
|
||||
},
|
||||
DW_FORM_sdata(0xd, DWARFForm.LEB128_SIZE, constant) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFNumericAttribute(64, context.reader().readNext(LEB128::signed), true,
|
||||
context.def());
|
||||
return new DWARFNumericAttribute(64, context.reader().readNext(LEB128::signed), true);
|
||||
}
|
||||
},
|
||||
DW_FORM_strp(0xe, DWARFForm.DWARF_INTSIZE, string),
|
||||
DW_FORM_udata(0xf, DWARFForm.LEB128_SIZE, constant) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFNumericAttribute(64, context.reader().readNext(LEB128::unsigned), false,
|
||||
context.def());
|
||||
return new DWARFNumericAttribute(64, context.reader().readNext(LEB128::unsigned),
|
||||
false);
|
||||
}
|
||||
},
|
||||
DW_FORM_ref_addr(0x10, DWARFForm.DWARF_INTSIZE, reference),
|
||||
@@ -179,7 +174,7 @@ public enum DWARFForm {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
long addr = context.reader().readNextUnsignedValue(context.dwarfIntSize());
|
||||
return new DWARFNumericAttribute(addr, context.def());
|
||||
return new DWARFNumericAttribute(context.dwarfIntSize() * 8, addr, false);
|
||||
}
|
||||
},
|
||||
DW_FORM_exprloc(0x18, DWARFForm.DYNAMIC_SIZE, exprloc) {
|
||||
@@ -195,15 +190,14 @@ public enum DWARFForm {
|
||||
if (length < 0 || length > MAX_BLOCK4_SIZE) {
|
||||
throw new IOException("Invalid/bad dw_form_exprloc size: " + length);
|
||||
}
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length),
|
||||
context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(length));
|
||||
|
||||
}
|
||||
},
|
||||
DW_FORM_flag_present(0x19, 0, flag) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFBooleanAttribute(true, context.def());
|
||||
return new DWARFBooleanAttribute(true);
|
||||
}
|
||||
},
|
||||
DW_FORM_strx(0x1a, DWARFForm.LEB128_SIZE, string),
|
||||
@@ -213,7 +207,7 @@ public enum DWARFForm {
|
||||
DW_FORM_data16(0x1e, 16, constant) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(16), context.def());
|
||||
return new DWARFBlobAttribute(context.reader().readNextByteArray(16));
|
||||
}
|
||||
},
|
||||
DW_FORM_line_strp(0x1f, DWARFForm.DWARF_INTSIZE, string),
|
||||
@@ -221,22 +215,19 @@ public enum DWARFForm {
|
||||
DW_FORM_implicit_const(0x21, 0) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFNumericAttribute(64, context.def().getImplicitValue(), true,
|
||||
context.def());
|
||||
return new DWARFNumericAttribute(64, context.def().getImplicitValue(), true);
|
||||
}
|
||||
},
|
||||
DW_FORM_loclistx(0x22, DWARFForm.LEB128_SIZE, loclist) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFIndirectAttribute(context.reader().readNext(LEB128::unsigned),
|
||||
context.def());
|
||||
return new DWARFIndirectAttribute(context.reader().readNext(LEB128::unsigned));
|
||||
}
|
||||
},
|
||||
DW_FORM_rnglistx(0x23, DWARFForm.LEB128_SIZE, rnglist) {
|
||||
@Override
|
||||
public DWARFAttributeValue readValue(DWARFFormContext context) throws IOException {
|
||||
return new DWARFIndirectAttribute(context.reader().readNext(LEB128::unsigned),
|
||||
context.def());
|
||||
return new DWARFIndirectAttribute(context.reader().readNext(LEB128::unsigned));
|
||||
}
|
||||
},
|
||||
DW_FORM_ref_sup8(0x24, 8, reference), // unimpl
|
||||
@@ -326,12 +317,12 @@ public enum DWARFForm {
|
||||
case DW_FORM_addrx3:
|
||||
case DW_FORM_addrx4: {
|
||||
long index = context.reader().readNextUnsignedValue(size);
|
||||
return new DWARFIndirectAttribute(index, context.def());
|
||||
return new DWARFIndirectAttribute(index);
|
||||
}
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_gnu_addr_index: {
|
||||
int index = context.reader().readNextUnsignedVarIntExact(LEB128::unsigned);
|
||||
return new DWARFIndirectAttribute(index, context.def());
|
||||
return new DWARFIndirectAttribute(index);
|
||||
}
|
||||
|
||||
case DW_FORM_data1:
|
||||
@@ -339,7 +330,7 @@ public enum DWARFForm {
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_data8: {
|
||||
long val = context.reader().readNextValue(size);
|
||||
return new DWARFNumericAttribute(size * 8, val, true, true, context.def());
|
||||
return new DWARFNumericAttribute(size * 8, val, true, true);
|
||||
}
|
||||
|
||||
case DW_FORM_ref1:
|
||||
@@ -347,16 +338,17 @@ public enum DWARFForm {
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_ref8: {
|
||||
long uoffset = context.reader().readNextUnsignedValue(size);
|
||||
return new DWARFNumericAttribute(uoffset, context.def());
|
||||
return new DWARFNumericAttribute(size * 8, uoffset, false);
|
||||
}
|
||||
case DW_FORM_ref_addr:
|
||||
case DW_FORM_gnu_ref_alt: {
|
||||
long addr = context.reader().readNextUnsignedValue(context.dwarfIntSize());
|
||||
return new DWARFNumericAttribute(addr, context.def());
|
||||
int intSize = context.dwarfIntSize();
|
||||
long addr = context.reader().readNextUnsignedValue(intSize);
|
||||
return new DWARFNumericAttribute(intSize * 8, addr, false);
|
||||
}
|
||||
case DW_FORM_ref_udata: {
|
||||
long uoffset = context.reader().readNext(LEB128::unsigned);
|
||||
return new DWARFNumericAttribute(uoffset, context.def());
|
||||
return new DWARFNumericAttribute(64, uoffset, false);
|
||||
}
|
||||
|
||||
case DW_FORM_strx1:
|
||||
@@ -366,7 +358,7 @@ public enum DWARFForm {
|
||||
long index = context.reader().readNextUnsignedValue(size);
|
||||
String s =
|
||||
context.compUnit().getProgram().getString(this, index, context.compUnit());
|
||||
return new DWARFStringAttribute(s, context.def());
|
||||
return new DWARFStringAttribute(s);
|
||||
}
|
||||
case DW_FORM_strp:
|
||||
case DW_FORM_line_strp:
|
||||
@@ -374,14 +366,14 @@ public enum DWARFForm {
|
||||
long offset = context.reader().readNextUnsignedValue(context.dwarfIntSize());
|
||||
String s =
|
||||
context.compUnit().getProgram().getString(this, offset, context.compUnit());
|
||||
return new DWARFStringAttribute(s, context.def());
|
||||
return new DWARFStringAttribute(s);
|
||||
}
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_gnu_str_index: {
|
||||
int index = context.reader().readNextUnsignedVarIntExact(LEB128::unsigned);
|
||||
String s =
|
||||
context.compUnit().getProgram().getString(this, index, context.compUnit());
|
||||
return new DWARFStringAttribute(s, context.def());
|
||||
return new DWARFStringAttribute(s);
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
+16
-18
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -26,8 +26,8 @@ import ghidra.app.util.bin.format.dwarf.sectionprovider.DWARFSectionNames;
|
||||
*/
|
||||
public class DWARFIndirectAttribute extends DWARFNumericAttribute {
|
||||
|
||||
public DWARFIndirectAttribute(long index, DWARFAttributeDef<?> def) {
|
||||
super(index, def);
|
||||
public DWARFIndirectAttribute(long index) {
|
||||
super(index);
|
||||
}
|
||||
|
||||
public int getIndex() throws IOException {
|
||||
@@ -35,38 +35,36 @@ public class DWARFIndirectAttribute extends DWARFNumericAttribute {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(DWARFCompilationUnit cu) {
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
DWARFProgram dprog = cu.getProgram();
|
||||
DWARFForm form = def.getAttributeForm();
|
||||
try {
|
||||
DWARFProgram prog = cu.getProgram();
|
||||
int index = getIndex();
|
||||
long offset = prog.getOffsetOfIndexedElement(getAttributeForm(), index, cu);
|
||||
if (getAttributeForm().isClass(DWARFAttributeClass.address)) {
|
||||
return "%s : %s, addr v%d 0x%x (idx %d)".formatted(getAttributeName(),
|
||||
getAttributeForm(), cu.getDWARFVersion(), offset, index);
|
||||
long offset = dprog.getOffsetOfIndexedElement(form, index, cu);
|
||||
if (form.isClass(DWARFAttributeClass.address)) {
|
||||
return "addr v%d 0x%x (idx %d)".formatted(cu.getDWARFVersion(), offset, index);
|
||||
}
|
||||
else if (getAttributeForm().isClass(DWARFAttributeClass.rnglist)) {
|
||||
else if (form.isClass(DWARFAttributeClass.rnglist)) {
|
||||
return toElementLocationString("rnglist", DWARFSectionNames.DEBUG_RNGLISTS, index,
|
||||
offset, cu.getDWARFVersion());
|
||||
}
|
||||
else if (getAttributeForm().isClass(DWARFAttributeClass.loclist)) {
|
||||
else if (form.isClass(DWARFAttributeClass.loclist)) {
|
||||
return toElementLocationString("loclist", DWARFSectionNames.DEBUG_LOCLISTS, index,
|
||||
offset, cu.getDWARFVersion());
|
||||
}
|
||||
else if (getAttributeForm().isClass(DWARFAttributeClass.string)) {
|
||||
return toElementLocationString("string", DWARFSectionNames.DEBUG_LOCLISTS, index,
|
||||
else if (form.isClass(DWARFAttributeClass.string)) {
|
||||
return toElementLocationString("string", "string_list_???", index,
|
||||
offset, cu.getDWARFVersion());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// fall thru to default
|
||||
}
|
||||
return super.toString(cu);
|
||||
return super.getValueString(cu, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
long index = getUnsignedValue();
|
||||
return "%s : %s, index/offset %d [0x%x]".formatted(getAttributeName(), getAttributeForm(),
|
||||
index, index);
|
||||
return "indirect " + super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/* ###
|
||||
* 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.dwarf.attribs;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
|
||||
/**
|
||||
* Placeholder for an attribute value that failed to be deserialized.
|
||||
*/
|
||||
public class DWARFMissingAttributeValue implements DWARFAttributeValue {
|
||||
|
||||
public DWARFMissingAttributeValue() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
return "<missing>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<missing>";
|
||||
}
|
||||
|
||||
}
|
||||
+23
-33
@@ -25,7 +25,7 @@ import ghidra.program.model.scalar.Scalar;
|
||||
/**
|
||||
* DWARF numeric attribute.
|
||||
*/
|
||||
public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
public class DWARFNumericAttribute implements DWARFAttributeValue {
|
||||
|
||||
private final Scalar value;
|
||||
private final boolean ambiguous;
|
||||
@@ -34,10 +34,9 @@ public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
* Creates a new numeric value, using 64 bits and marked as signed
|
||||
*
|
||||
* @param value long 64 bit value
|
||||
* @param def attribute id and form of this value
|
||||
*/
|
||||
public DWARFNumericAttribute(long value, DWARFAttributeDef<?> def) {
|
||||
this(64, value, true, false, def);
|
||||
public DWARFNumericAttribute(long value) {
|
||||
this(64, value, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,11 +45,9 @@ public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
* @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.
|
||||
* @param def attribute id and form of this value
|
||||
*/
|
||||
public DWARFNumericAttribute(int bitLength, long value, boolean signed,
|
||||
DWARFAttributeDef<?> def) {
|
||||
this(bitLength, value, signed, false, def);
|
||||
public DWARFNumericAttribute(int bitLength, long value, boolean signed) {
|
||||
this(bitLength, value, signed, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,11 +58,8 @@ public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
* @param signed true for a signed value, false for an unsigned value.
|
||||
* @param ambiguous true for value with ambiguous signedness ({@code signed} parameter should
|
||||
* not be trusted), false for value where the {@code signed} parameter is known to be correct
|
||||
* @param def attribute id and form of this value
|
||||
*/
|
||||
public DWARFNumericAttribute(int bitLength, long value, boolean signed, boolean ambiguous,
|
||||
DWARFAttributeDef<?> def) {
|
||||
super(def);
|
||||
public DWARFNumericAttribute(int bitLength, long value, boolean signed, boolean ambiguous) {
|
||||
this.value = new Scalar(bitLength, value, signed);
|
||||
this.ambiguous = ambiguous;
|
||||
}
|
||||
@@ -95,12 +89,6 @@ public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString(DWARFCompilationUnit cu) {
|
||||
long v = getValue();
|
||||
return "%d [0x%x]".formatted(v, v);
|
||||
}
|
||||
|
||||
public long getUnsignedValue() {
|
||||
return value.getUnsignedValue();
|
||||
}
|
||||
@@ -118,37 +106,39 @@ public class DWARFNumericAttribute extends DWARFAttributeValue {
|
||||
public String toElementLocationString(String elementType, String sectionName, int index,
|
||||
long offset, int ver) {
|
||||
String indexStr = index >= 0 ? " (idx %d)".formatted(index) : "";
|
||||
return "%s : %s, %s v%d %s:%x%s".formatted(getAttributeName(), getAttributeForm(),
|
||||
elementType, ver, sectionName, offset, indexStr);
|
||||
return "%s v%d %s:%x%s".formatted(elementType, ver, sectionName, offset, indexStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(DWARFCompilationUnit cu) {
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
|
||||
short ver = cu.getDWARFVersion();
|
||||
if (getAttributeForm().isClass(DWARFAttributeClass.address)) {
|
||||
return "%s : %s, addr v%d 0x%x".formatted(getAttributeName(), getAttributeForm(), ver,
|
||||
getUnsignedValue());
|
||||
DWARFForm form = def.getAttributeForm();
|
||||
if (form.isClass(DWARFAttributeClass.address)) {
|
||||
return "addr v%d 0x%x".formatted(ver, getUnsignedValue());
|
||||
}
|
||||
else if (getAttributeForm().isClass(DWARFAttributeClass.rnglist)) {
|
||||
else if (form.isClass(DWARFAttributeClass.rnglist)) {
|
||||
String sectionName =
|
||||
ver < 5 ? DWARFSectionNames.DEBUG_RANGES : DWARFSectionNames.DEBUG_RNGLISTS;
|
||||
return toElementLocationString("rnglist", sectionName, -1, getUnsignedValue(),
|
||||
cu.getDWARFVersion()) + " offset: " + getUnsignedValue();
|
||||
return toElementLocationString("rnglist", sectionName, -1, getUnsignedValue(), ver) +
|
||||
" offset: " + getUnsignedValue();
|
||||
}
|
||||
else if (getAttributeForm().isClass(DWARFAttributeClass.loclist)) {
|
||||
else if (form.isClass(DWARFAttributeClass.loclist)) {
|
||||
String sectionName =
|
||||
ver < 5 ? DWARFSectionNames.DEBUG_LOC : DWARFSectionNames.DEBUG_LOCLISTS;
|
||||
return toElementLocationString("loclist", sectionName, -1, getUnsignedValue(),
|
||||
cu.getDWARFVersion());
|
||||
return toElementLocationString("loclist", sectionName, -1, getUnsignedValue(), ver);
|
||||
}
|
||||
return toString();
|
||||
|
||||
String orStr =
|
||||
ambiguous && isHighbitSet() ? " or " + value.getValue(!value.isSigned()) : "";
|
||||
return "%d%s [%s]".formatted(getValue(), orStr, value.toString(16, true, false, "", ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String orStr =
|
||||
ambiguous && isHighbitSet() ? " or " + value.getValue(!value.isSigned()) : "";
|
||||
return "%s : %s = %d%s [%s]".formatted(getAttributeName(), getAttributeForm(), getValue(),
|
||||
orStr, value.toString(16, true, false, "", ""));
|
||||
return "%d%s [%s]".formatted(getValue(), orStr, value.toString(16, true, false, "", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,11 +20,10 @@ import ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit;
|
||||
/**
|
||||
* DWARF string attribute.
|
||||
*/
|
||||
public class DWARFStringAttribute extends DWARFAttributeValue {
|
||||
public class DWARFStringAttribute implements DWARFAttributeValue {
|
||||
protected String value;
|
||||
|
||||
public DWARFStringAttribute(String value, DWARFAttributeDef<?> def) {
|
||||
super(def);
|
||||
public DWARFStringAttribute(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -33,12 +32,13 @@ public class DWARFStringAttribute extends DWARFAttributeValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString(DWARFCompilationUnit cu) {
|
||||
return getValue(cu);
|
||||
public String getValueString(DWARFCompilationUnit cu, DWARFAttributeDef<?> def) {
|
||||
return "\"%s\"".formatted(getValue(cu));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s : %s = \"%s\"".formatted(getAttributeName(), getAttributeForm(), value);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -194,8 +194,8 @@ public enum DWARFExpressionOpCode {
|
||||
DW_OP_convert(0xa8, U_LEB128),
|
||||
DW_OP_reinterpret(0xa9, U_LEB128);
|
||||
|
||||
private static final int DW_OP_lo_user = 0xe0;
|
||||
private static final int DW_OP_hi_user = 0xff;
|
||||
// private static final int DW_OP_lo_user = 0xe0;
|
||||
// private static final int DW_OP_hi_user = 0xff;
|
||||
|
||||
private final int opcode;
|
||||
private final DWARFExpressionOperandType[] operandTypes;
|
||||
|
||||
+1
@@ -146,6 +146,7 @@ public class ExternalDebugFilesConfigDialog extends DialogComponentProvider {
|
||||
|
||||
/**
|
||||
* Screen shot only
|
||||
* @param edfs {@link ExternalDebugFilesService}
|
||||
*/
|
||||
public void setService(ExternalDebugFilesService edfs) {
|
||||
setProviders(edfs.getProviders());
|
||||
|
||||
+3
-2
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -54,6 +54,7 @@ public interface DWARFFunctionFixup extends ExtensionPoint {
|
||||
* a {@link DWARFException}.
|
||||
*
|
||||
* @param dfunc {@link DWARFFunction} info read from DWARF about the function
|
||||
* @throws DWARFException if error fixing function
|
||||
*/
|
||||
void fixupDWARFFunction(DWARFFunction dfunc) throws DWARFException;
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import ghidra.app.util.bin.format.dwarf.attribs.*;
|
||||
/**
|
||||
* Represents an identifier of a value in a DWARFLine/DWARFFile object.
|
||||
* <p>
|
||||
* Similar to the {@link DWARFAttribute} enum, both are identifiers of an attribute value
|
||||
* Similar to the {@link DWARFAttributeId} enum, both are identifiers of an attribute value
|
||||
* that is serialized by a DWARFForm.
|
||||
* <p>
|
||||
* Users of this enum should be tolerant of unknown values.
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ public final class DWARFLineProgramExecutor implements Closeable {
|
||||
/**
|
||||
* Read the next instruction and executes it
|
||||
*
|
||||
* @return
|
||||
* @return next {@link DWARFLineProgramInstruction}
|
||||
* @throws IOException if an i/o error occurs
|
||||
*/
|
||||
public DWARFLineProgramInstruction step() throws IOException {
|
||||
|
||||
+2
-2
@@ -86,8 +86,8 @@ public class DWARFMacroDefine extends DWARFMacroInfoEntry {
|
||||
|
||||
public DWARFMacroDefine(int lineNumber, String defineString, DWARFMacroHeader parent) {
|
||||
super(DWARFMacroOpcode.DW_MACRO_define, parent);
|
||||
operandValues[0] = new DWARFNumericAttribute(lineNumber, operandDef(0));
|
||||
operandValues[1] = new DWARFStringAttribute(defineString, operandDef(1));
|
||||
operandValues[0] = new DWARFNumericAttribute(lineNumber);
|
||||
operandValues[1] = new DWARFStringAttribute(defineString);
|
||||
}
|
||||
|
||||
public DWARFMacroDefine(DWARFMacroInfoEntry other) {
|
||||
|
||||
+2
-1
@@ -149,7 +149,8 @@ public class DWARFMacroInfoEntry {
|
||||
if (i != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(operandValues[i].getValueString(macroHeader.getCompilationUnit()));
|
||||
sb.append(operandValues[i].getValueString(macroHeader.getCompilationUnit(),
|
||||
operandDef(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -27,7 +27,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
* a Ghidra program.
|
||||
* <p>
|
||||
* Implementors of this interface need to be registered in
|
||||
* {@link DWARFSectionProviderFactory#sectionProviderFactoryFuncs} and should implement the
|
||||
* DWARFSectionProviderFactory's {@code sectionProviderFactoryFuncs} and should implement the
|
||||
* static method:
|
||||
* <p>
|
||||
* <code>public static DWARFSectionProvider createSectionProviderFor(Program program, TaskMonitor monitor)</code>
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -54,7 +54,7 @@ public class DWARFSectionProviderFactory {
|
||||
* The resulting {@link DWARFSectionProvider} is {@link Closeable} and it is the caller's
|
||||
* responsibility to ensure that the object is closed when done.
|
||||
*
|
||||
* @param program
|
||||
* @param program {@link Program}
|
||||
* @param monitor {@link TaskMonitor}
|
||||
* @return {@link DWARFSectionProvider} that should be closed by the caller or NULL if no
|
||||
* section provider types match the specified program.
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFSourceLanguage.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.expression.DWARFExpressionOpCode.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.expression.DWARFExpressionOpCode.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
+18
-18
@@ -20,17 +20,17 @@ import static ghidra.app.util.bin.format.dwarf.attribs.DWARFForm.*;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.*;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.AttrDef;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.AttrDef;
|
||||
|
||||
/**
|
||||
* Helper class to create mock DebugInfoEntry instances for use during junit tests.
|
||||
*/
|
||||
public class DIECreator {
|
||||
record AttrInfo(DWARFAttribute attribute, AttrDef spec, DWARFAttributeValue value) {}
|
||||
record AttrInfo(DWARFAttributeId attribute, AttrDef spec, DWARFAttributeValue value) {}
|
||||
|
||||
private MockDWARFProgram dwarfProg;
|
||||
private DWARFTag tag;
|
||||
private Map<DWARFAttribute, AttrInfo> attributes = new HashMap<>();
|
||||
private Map<DWARFAttributeId, AttrInfo> attributes = new HashMap<>();
|
||||
private DebugInfoEntry parent;
|
||||
|
||||
public DIECreator(MockDWARFProgram dwarfProg, DWARFTag tag) {
|
||||
@@ -43,45 +43,45 @@ public class DIECreator {
|
||||
new AttrInfo(attrSpec.getAttributeId(), attrSpec, attrVal));
|
||||
}
|
||||
|
||||
public DIECreator addString(DWARFAttribute attribute, String value) {
|
||||
public DIECreator addString(DWARFAttributeId attribute, String value) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_string, 0);
|
||||
add(attrSpec, new DWARFStringAttribute(value, attrSpec));
|
||||
add(attrSpec, new DWARFStringAttribute(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addUInt(DWARFAttribute attribute, long value) {
|
||||
public DIECreator addUInt(DWARFAttributeId attribute, long value) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_udata, 0);
|
||||
add(attrSpec, new DWARFNumericAttribute(value, attrSpec));
|
||||
add(attrSpec, new DWARFNumericAttribute(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addInt(DWARFAttribute attribute, long value) {
|
||||
public DIECreator addInt(DWARFAttributeId attribute, long value) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_sdata, 0);
|
||||
add(attrSpec, new DWARFNumericAttribute(value, attrSpec));
|
||||
add(attrSpec, new DWARFNumericAttribute(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addRef(DWARFAttribute attribute, DebugInfoEntry die) {
|
||||
public DIECreator addRef(DWARFAttributeId attribute, DebugInfoEntry die) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_ref8, 0);
|
||||
add(attrSpec, new DWARFNumericAttribute(
|
||||
die.getOffset() - dwarfProg.getCurrentCompUnit().getStartOffset(), attrSpec));
|
||||
die.getOffset() - dwarfProg.getCurrentCompUnit().getStartOffset()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addRef(DWARFAttribute attribute, long offset) {
|
||||
public DIECreator addRef(DWARFAttributeId attribute, long offset) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_ref8, 0);
|
||||
add(attrSpec, new DWARFNumericAttribute(
|
||||
offset - dwarfProg.getCurrentCompUnit().getStartOffset(), attrSpec));
|
||||
offset - dwarfProg.getCurrentCompUnit().getStartOffset()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addBoolean(DWARFAttribute attribute, boolean value) {
|
||||
public DIECreator addBoolean(DWARFAttributeId attribute, boolean value) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_flag, 0);
|
||||
add(attrSpec, new DWARFBooleanAttribute(value, attrSpec));
|
||||
add(attrSpec, new DWARFBooleanAttribute(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addBlock(DWARFAttribute attribute, int... intBytes) {
|
||||
public DIECreator addBlock(DWARFAttributeId attribute, int... intBytes) {
|
||||
byte[] bytes = new byte[intBytes.length];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = (byte) intBytes[i];
|
||||
@@ -90,9 +90,9 @@ public class DIECreator {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DIECreator addBlockBytes(DWARFAttribute attribute, byte[] blockBytes) {
|
||||
public DIECreator addBlockBytes(DWARFAttributeId attribute, byte[] blockBytes) {
|
||||
AttrDef attrSpec = new AttrDef(attribute, attribute.getId(), DW_FORM_block1, 0);
|
||||
add(attrSpec, new DWARFBlobAttribute(blockBytes, attrSpec));
|
||||
add(attrSpec, new DWARFBlobAttribute(blockBytes));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFEncoding.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.DWARFTag.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -17,7 +17,7 @@ package ghidra.app.util.bin.format.dwarf;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.AttrDef;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.AttrDef;
|
||||
|
||||
public class MockDWARFCompilationUnit extends DWARFCompilationUnit {
|
||||
|
||||
|
||||
+5
-5
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -23,7 +23,7 @@ import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId;
|
||||
import ghidra.app.util.bin.format.dwarf.sectionprovider.DWARFSectionProvider;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.datastruct.IntArrayList;
|
||||
@@ -74,7 +74,7 @@ public class MockDWARFProgram extends DWARFProgram {
|
||||
compUnitDieIndex.put(dieOffsets.length - 1, currentCompUnit);
|
||||
|
||||
DebugInfoEntry compUnitRootDIE = new DIECreator(this, DWARFTag.DW_TAG_compile_unit)
|
||||
.addInt(DWARFAttribute.DW_AT_language, cuLang)
|
||||
.addInt(DWARFAttributeId.DW_AT_language, cuLang)
|
||||
.createRootDIE();
|
||||
try {
|
||||
currentCompUnit.init(compUnitRootDIE);
|
||||
@@ -129,7 +129,7 @@ public class MockDWARFProgram extends DWARFProgram {
|
||||
LongArrayList aggrTargets = new LongArrayList();
|
||||
for (DebugInfoEntry die : dies) {
|
||||
DIEAggregate diea = DIEAggregate.createSingle(die);
|
||||
for (DWARFAttribute attr : REF_ATTRS) {
|
||||
for (DWARFAttributeId attr : REF_ATTRS) {
|
||||
long refdOffset = diea.getUnsignedLong(attr, -1);
|
||||
if (refdOffset != -1) {
|
||||
aggrTargets.add(refdOffset);
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.bin.format.dwarf.attribs;
|
||||
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.*;
|
||||
import static ghidra.app.util.bin.format.dwarf.attribs.DWARFForm.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.junit.Test;
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFSourceLanguage;
|
||||
import ghidra.app.util.bin.format.dwarf.DWARFTestBase;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttribute.AttrDef;
|
||||
import ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeId.AttrDef;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class DWARFAttributeFactoryTest extends DWARFTestBase {
|
||||
return createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY64_BE, this);
|
||||
}
|
||||
|
||||
private DWARFAttributeValue read(BinaryReader br, DWARFAttribute attr, DWARFForm form)
|
||||
private DWARFAttributeValue read(BinaryReader br, DWARFAttributeId attr, DWARFForm form)
|
||||
throws IOException {
|
||||
ensureCompUnit();
|
||||
AttrDef spec = new AttrDef(attr, attr.getId(), form, 0);
|
||||
|
||||
Reference in New Issue
Block a user