Merge remote-tracking branch 'origin/GP-6400_dev747368_dwarf_attribute_refactor'

This commit is contained in:
Ryan Kurtz
2026-02-05 05:00:17 -05:00
46 changed files with 796 additions and 747 deletions
@@ -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;
@@ -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;
@@ -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;
@@ -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());
@@ -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) {
@@ -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) {
@@ -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.*;
@@ -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;
@@ -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);
@@ -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);
@@ -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;
@@ -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" -&gt;
* [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;
@@ -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;
}
@@ -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();
@@ -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);
}
}
@@ -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 {
@@ -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;
}
@@ -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);
}
}
}
@@ -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);
}
@@ -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, " "));
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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:
@@ -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();
}
}
@@ -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>";
}
}
@@ -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, "", ""));
}
}
@@ -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;
}
}
@@ -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;
@@ -146,6 +146,7 @@ public class ExternalDebugFilesConfigDialog extends DialogComponentProvider {
/**
* Screen shot only
* @param edfs {@link ExternalDebugFilesService}
*/
public void setService(ExternalDebugFilesService edfs) {
setProviders(edfs.getProviders());
@@ -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;
@@ -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.
@@ -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 {
@@ -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) {
@@ -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)));
}
}
@@ -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>
@@ -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.
@@ -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;
@@ -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.*;
@@ -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.*;
@@ -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;
}
@@ -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;
@@ -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;
@@ -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 {
@@ -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);
@@ -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);