[DWARF] NFC: Collect info used by DWARFFormValue into a helper.

Some forms have sizes that depend on the DWARF version, DWARF format
(32/64-bit), or the size of an address.  Collect these into a struct
to simplify passing them around.  Require callers to provide one when
they query a form's size.

Differential Revision: http://reviews.llvm.org/D34570

llvm-svn: 306315
This commit is contained in:
Paul Robinson 2017-06-26 18:43:01 +00:00
parent d58f051792
commit 75c068c50b
11 changed files with 205 additions and 252 deletions

View File

@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
#include <cstdint>
@ -43,10 +44,10 @@ public:
/// The size in bytes of the statement information for this compilation unit
/// (not including the total_length field itself).
uint64_t TotalLength;
/// Version identifier for the statement information format.
uint16_t Version;
/// In v5, size in bytes of an address (or segment offset).
uint8_t AddressSize;
/// Version, address size (starting in v5), and DWARF32/64 format; these
/// parameters affect interpretation of forms (used in the directory and
/// file tables starting with v5).
DWARFFormParams FormParams;
/// In v5, size in bytes of a segment selector.
uint8_t SegSelectorSize;
/// The number of bytes following the prologue_length field to the beginning
@ -71,15 +72,18 @@ public:
std::vector<StringRef> IncludeDirectories;
std::vector<FileNameEntry> FileNames;
bool IsDWARF64;
const DWARFFormParams getFormParams() const { return FormParams; }
uint16_t getVersion() const { return FormParams.Version; }
uint8_t getAddressSize() const { return FormParams.AddrSize; }
bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
uint32_t sizeofTotalLength() const { return IsDWARF64 ? 12 : 4; }
uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
uint32_t sizeofPrologueLength() const { return IsDWARF64 ? 8 : 4; }
uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
/// Length of the prologue in bytes.
uint32_t getLength() const {
return PrologueLength + sizeofTotalLength() + sizeof(Version) +
return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
sizeofPrologueLength();
}

View File

@ -22,6 +22,35 @@ namespace llvm {
class DWARFUnit;
class raw_ostream;
/// A helper struct for DWARFFormValue methods, providing information that
/// allows it to know the byte size of DW_FORM values that vary in size
/// depending on the DWARF version, address byte size, or DWARF32/DWARF64.
struct DWARFFormParams {
uint16_t Version;
uint8_t AddrSize;
dwarf::DwarfFormat Format;
/// The definition of the size of form DW_FORM_ref_addr depends on the
/// version. In DWARF v2 it's the size of an address; after that, it's the
/// size of a reference.
uint8_t getRefAddrByteSize() const {
if (Version == 2)
return AddrSize;
return getDwarfOffsetByteSize();
}
/// The size of a reference is determined by the DWARF 32/64-bit format.
uint8_t getDwarfOffsetByteSize() const {
switch (Format) {
case dwarf::DwarfFormat::DWARF32:
return 4;
case dwarf::DwarfFormat::DWARF64:
return 8;
}
llvm_unreachable("Invalid Format value");
}
};
class DWARFFormValue {
public:
enum FormClass {
@ -104,79 +133,43 @@ public:
/// Get the fixed byte size for a given form.
///
/// If the form always has a fixed valid byte size that doesn't depend on a
/// DWARFUnit, then an Optional with a value will be returned. If the form
/// can vary in size depending on the DWARFUnit (DWARF version, address byte
/// size, or DWARF 32/64) and the DWARFUnit is valid, then an Optional with a
/// valid value is returned. If the form is always encoded using a variable
/// length storage format (ULEB or SLEB numbers or blocks) or the size
/// depends on a DWARFUnit and the DWARFUnit is NULL, then None will be
/// returned.
/// \param Form The DWARF form to get the fixed byte size for
/// \param U The DWARFUnit that can be used to help determine the byte size.
/// If the form has a fixed byte size, then an Optional with a value will be
/// returned. If the form is always encoded using a variable length storage
/// format (ULEB or SLEB numbers or blocks) then None will be returned.
///
/// \returns Optional<uint8_t> value with the fixed byte size or None if
/// \p Form doesn't have a fixed byte size or a DWARFUnit wasn't supplied
/// and was needed to calculate the byte size.
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
const DWARFUnit *U = nullptr);
/// Get the fixed byte size for a given form.
///
/// If the form has a fixed byte size given a valid DWARF version and address
/// byte size, then an Optional with a valid value is returned. If the form
/// is always encoded using a variable length storage format (ULEB or SLEB
/// numbers or blocks) then None will be returned.
///
/// \param Form DWARF form to get the fixed byte size for
/// \param Version DWARF version number.
/// \param AddrSize size of an address in bytes.
/// \param Format enum value from llvm::dwarf::DwarfFormat.
/// \param Form DWARF form to get the fixed byte size for.
/// \param FormParams DWARF parameters to help interpret forms.
/// \returns Optional<uint8_t> value with the fixed byte size or None if
/// \p Form doesn't have a fixed byte size.
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, uint16_t Version,
uint8_t AddrSize,
llvm::dwarf::DwarfFormat Format);
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
const DWARFFormParams &FormParams);
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
/// Skip a form's value in \p DebugInfoData at the offset specified by
/// \p OffsetPtr.
///
/// Skips the bytes for this form in the debug info and updates the offset.
/// Skips the bytes for the current form and updates the offset.
///
/// \param DebugInfoData the .debug_info data to use to skip the value.
/// \param OffsetPtr a reference to the offset that will be updated.
/// \param U the DWARFUnit to use when skipping the form in case the form
/// size differs according to data in the DWARFUnit.
/// \param DebugInfoData The data where we want to skip the value.
/// \param OffsetPtr A reference to the offset that will be updated.
/// \param Params DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
const DWARFUnit *U) const;
const DWARFFormParams &Params) const {
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
}
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
/// Skip a form's value in \p DebugInfoData at the offset specified by
/// \p OffsetPtr.
///
/// Skips the bytes for this form in the debug info and updates the offset.
/// Skips the bytes for the specified form and updates the offset.
///
/// \param Form the DW_FORM enumeration that indicates the form to skip.
/// \param DebugInfoData the .debug_info data to use to skip the value.
/// \param OffsetPtr a reference to the offset that will be updated.
/// \param U the DWARFUnit to use when skipping the form in case the form
/// size differs according to data in the DWARFUnit.
/// \param Form The DW_FORM enumeration that indicates the form to skip.
/// \param DebugInfoData The data where we want to skip the value.
/// \param OffsetPtr A reference to the offset that will be updated.
/// \param FormParams DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
uint32_t *OffsetPtr, const DWARFUnit *U);
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
///
/// Skips the bytes for this form in the debug info and updates the offset.
///
/// \param Form the DW_FORM enumeration that indicates the form to skip.
/// \param DebugInfoData the .debug_info data to use to skip the value.
/// \param OffsetPtr a reference to the offset that will be updated.
/// \param Version DWARF version number.
/// \param AddrSize size of an address in bytes.
/// \param Format enum value from llvm::dwarf::DwarfFormat.
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize,
llvm::dwarf::DwarfFormat Format);
uint32_t *OffsetPtr, const DWARFFormParams &FormParams);
private:
void dumpString(raw_ostream &OS) const;

View File

@ -19,6 +19,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
@ -127,12 +128,13 @@ class DWARFUnit {
bool isDWO;
const DWARFUnitSectionBase &UnitSection;
// Version, address size, and DWARF format.
DWARFFormParams FormParams;
uint32_t Offset;
uint32_t Length;
const DWARFAbbreviationDeclarationSet *Abbrevs;
uint16_t Version;
uint8_t UnitType;
uint8_t AddrSize;
uint64_t BaseAddr;
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
@ -159,7 +161,7 @@ protected:
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
/// Size in bytes of the unit header.
virtual uint32_t getHeaderSize() const { return Version <= 4 ? 11 : 12; }
virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
@ -197,7 +199,8 @@ public:
uint64_t getStringOffsetSectionRelocation(uint32_t Index) const;
DataExtractor getDebugInfoExtractor() const {
return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
return DataExtractor(InfoSection.Data, isLittleEndian,
getAddressByteSize());
}
DataExtractor getStringExtractor() const {
@ -220,10 +223,14 @@ public:
uint32_t getOffset() const { return Offset; }
uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
uint32_t getLength() const { return Length; }
uint16_t getVersion() const { return Version; }
dwarf::DwarfFormat getFormat() const {
return dwarf::DwarfFormat::DWARF32; // FIXME: Support DWARF64.
const DWARFFormParams &getFormParams() const { return FormParams; }
uint16_t getVersion() const { return FormParams.Version; }
dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
uint8_t getDwarfOffsetByteSize() const {
return FormParams.getDwarfOffsetByteSize();
}
const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
@ -231,19 +238,6 @@ public:
}
uint8_t getUnitType() const { return UnitType; }
uint8_t getAddressByteSize() const { return AddrSize; }
uint8_t getRefAddrByteSize() const {
if (Version == 2)
return AddrSize;
return getDwarfOffsetByteSize();
}
uint8_t getDwarfOffsetByteSize() const {
if (getFormat() == dwarf::DwarfFormat::DWARF64)
return 8;
return 4;
}
uint64_t getBaseAddress() const { return BaseAddr; }

View File

@ -65,46 +65,52 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data,
if (A && F) {
Optional<int64_t> V;
bool IsImplicitConst = (F == DW_FORM_implicit_const);
if (IsImplicitConst)
if (IsImplicitConst) {
V = Data.getSLEB128(OffsetPtr);
else if (auto Size = DWARFFormValue::getFixedByteSize(F))
V = *Size;
AttributeSpecs.push_back(AttributeSpec(A, F, V));
if (IsImplicitConst)
AttributeSpecs.push_back(AttributeSpec(A, F, V));
continue;
}
// If this abbrevation still has a fixed byte size, then update the
// FixedAttributeSize as needed.
if (FixedAttributeSize) {
if (V)
FixedAttributeSize->NumBytes += *V;
else {
switch (F) {
case DW_FORM_addr:
++FixedAttributeSize->NumAddrs;
break;
switch (F) {
case DW_FORM_addr:
if (FixedAttributeSize)
++FixedAttributeSize->NumAddrs;
break;
case DW_FORM_ref_addr:
++FixedAttributeSize->NumRefAddrs;
break;
case DW_FORM_ref_addr:
if (FixedAttributeSize)
++FixedAttributeSize->NumRefAddrs;
break;
case DW_FORM_strp:
case DW_FORM_GNU_ref_alt:
case DW_FORM_GNU_strp_alt:
case DW_FORM_line_strp:
case DW_FORM_sec_offset:
case DW_FORM_strp_sup:
++FixedAttributeSize->NumDwarfOffsets;
break;
case DW_FORM_strp:
case DW_FORM_GNU_ref_alt:
case DW_FORM_GNU_strp_alt:
case DW_FORM_line_strp:
case DW_FORM_sec_offset:
case DW_FORM_strp_sup:
if (FixedAttributeSize)
++FixedAttributeSize->NumDwarfOffsets;
break;
default:
// Indicate we no longer have a fixed byte size for this
// abbreviation by clearing the FixedAttributeSize optional value
// so it doesn't have a value.
FixedAttributeSize.reset();
break;
}
default:
// The form has a byte size that doesn't depend on Params.
// If it's a fixed size, keep track of it.
if (auto Size =
DWARFFormValue::getFixedByteSize(F, DWARFFormParams())) {
V = *Size;
if (FixedAttributeSize)
FixedAttributeSize->NumBytes += *V;
break;
}
// Indicate we no longer have a fixed byte size for this
// abbreviation by clearing the FixedAttributeSize optional value
// so it doesn't have a value.
FixedAttributeSize.reset();
break;
}
// Record this attribute and its fixed size if it has one.
AttributeSpecs.push_back(AttributeSpec(A, F, V));
} else if (A == 0 && F == 0) {
// We successfully reached the end of this abbreviation declaration
// since both attribute and form are zero.
@ -186,7 +192,8 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
if (auto FixedSize = Spec.getByteSize(U))
Offset += *FixedSize;
else
DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U);
DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset,
U.getFormParams());
++AttrIndex;
}
return None;
@ -211,7 +218,8 @@ Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
if (ByteSizeOrValue)
return ByteSizeOrValue;
Optional<int64_t> S;
auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U);
auto FixedByteSize =
DWARFFormValue::getFixedByteSize(Form, U.getFormParams());
if (FixedByteSize)
S = *FixedByteSize;
return S;

View File

@ -59,7 +59,7 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
// Attribute byte size if fixed, just add the size to the offset.
*OffsetPtr += *FixedSize;
} else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData,
OffsetPtr, &U)) {
OffsetPtr, U.getFormParams())) {
// We failed to skip this attribute's value, restore the original offset
// and return the failure status.
*OffsetPtr = Offset;

View File

@ -44,11 +44,11 @@ using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
DWARFDebugLine::Prologue::Prologue() { clear(); }
void DWARFDebugLine::Prologue::clear() {
TotalLength = Version = PrologueLength = 0;
AddressSize = SegSelectorSize = 0;
TotalLength = PrologueLength = 0;
SegSelectorSize = 0;
MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
OpcodeBase = 0;
IsDWARF64 = false;
FormParams = DWARFFormParams({0, 0, DWARF32});
StandardOpcodeLengths.clear();
IncludeDirectories.clear();
FileNames.clear();
@ -57,12 +57,13 @@ void DWARFDebugLine::Prologue::clear() {
void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
OS << "Line table prologue:\n"
<< format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength)
<< format(" version: %u\n", Version)
<< format(Version >= 5 ? " address_size: %u\n" : "", AddressSize)
<< format(Version >= 5 ? " seg_select_size: %u\n" : "", SegSelectorSize)
<< format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
<< format(" version: %u\n", getVersion());
if (getVersion() >= 5)
OS << format(" address_size: %u\n", getAddressSize())
<< format(" seg_select_size: %u\n", SegSelectorSize);
OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
<< format(" min_inst_length: %u\n", MinInstLength)
<< format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
<< format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
<< format(" default_is_stmt: %u\n", DefaultIsStmt)
<< format(" line_base: %i\n", LineBase)
<< format(" line_range: %u\n", LineRange)
@ -143,6 +144,7 @@ parseV5EntryFormat(DataExtractor DebugLineData, uint32_t *OffsetPtr,
static bool
parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,
uint64_t EndPrologueOffset,
const DWARFFormParams &FormParams,
std::vector<StringRef> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
// Get the directory entry description.
@ -165,7 +167,7 @@ parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,
IncludeDirectories.push_back(Value.getAsCString().getValue());
break;
default:
if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr))
if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
return false;
}
}
@ -217,24 +219,26 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData,
clear();
TotalLength = DebugLineData.getU32(OffsetPtr);
if (TotalLength == UINT32_MAX) {
IsDWARF64 = true;
FormParams.Format = dwarf::DWARF64;
TotalLength = DebugLineData.getU64(OffsetPtr);
} else if (TotalLength > 0xffffff00) {
} else if (TotalLength >= 0xffffff00) {
return false;
}
Version = DebugLineData.getU16(OffsetPtr);
if (Version < 2)
FormParams.Version = DebugLineData.getU16(OffsetPtr);
if (getVersion() < 2)
return false;
if (Version >= 5) {
AddressSize = DebugLineData.getU8(OffsetPtr);
if (getVersion() >= 5) {
FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
assert(getAddressSize() == DebugLineData.getAddressSize() &&
"Line table header and data extractor disagree");
SegSelectorSize = DebugLineData.getU8(OffsetPtr);
}
PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
MinInstLength = DebugLineData.getU8(OffsetPtr);
if (Version >= 4)
if (getVersion() >= 4)
MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
LineBase = DebugLineData.getU8(OffsetPtr);
@ -247,9 +251,9 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData,
StandardOpcodeLengths.push_back(OpLen);
}
if (Version >= 5) {
if (getVersion() >= 5) {
if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
IncludeDirectories, FileNames)) {
getFormParams(), IncludeDirectories, FileNames)) {
fprintf(stderr,
"warning: parsing line table prologue at 0x%8.8" PRIx64
" found an invalid directory or file table description at"

View File

@ -59,48 +59,13 @@ static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
};
namespace {
/// A helper class that can be used in DWARFFormValue.cpp functions that need
/// to know the byte size of DW_FORM values that vary in size depending on the
/// DWARF version, address byte size, or DWARF32 or DWARF64.
class FormSizeHelper {
uint16_t Version;
uint8_t AddrSize;
llvm::dwarf::DwarfFormat Format;
public:
FormSizeHelper(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F)
: Version(V), AddrSize(A), Format(F) {}
uint8_t getAddressByteSize() const { return AddrSize; }
uint8_t getRefAddrByteSize() const {
if (Version == 2)
return AddrSize;
return getDwarfOffsetByteSize();
}
uint8_t getDwarfOffsetByteSize() const {
switch (Format) {
case dwarf::DwarfFormat::DWARF32:
return 4;
case dwarf::DwarfFormat::DWARF64:
return 8;
}
llvm_unreachable("Invalid Format value");
}
};
} // end anonymous namespace
template <class T>
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {
Optional<uint8_t>
DWARFFormValue::getFixedByteSize(dwarf::Form Form,
const DWARFFormParams &Params) {
switch (Form) {
case DW_FORM_addr:
if (U)
return U->getAddressByteSize();
return None;
assert(Params.Version && Params.AddrSize && "Invalid Params for form");
return Params.AddrSize;
case DW_FORM_block: // ULEB128 length L followed by L bytes.
case DW_FORM_block1: // 1 byte length L followed by L bytes.
@ -121,9 +86,8 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {
return None;
case DW_FORM_ref_addr:
if (U)
return U->getRefAddrByteSize();
return None;
assert(Params.Version && Params.AddrSize && "Invalid Params for form");
return Params.getRefAddrByteSize();
case DW_FORM_flag:
case DW_FORM_data1:
@ -154,9 +118,8 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {
case DW_FORM_line_strp:
case DW_FORM_sec_offset:
case DW_FORM_strp_sup:
if (U)
return U->getDwarfOffsetByteSize();
return None;
assert(Params.Version && Params.AddrSize && "Invalid Params for form");
return Params.getDwarfOffsetByteSize();
case DW_FORM_data8:
case DW_FORM_ref8:
@ -181,9 +144,9 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {
return None;
}
template <class T>
static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,
uint32_t *OffsetPtr, const T *U) {
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
uint32_t *OffsetPtr,
const DWARFFormParams &Params) {
bool Indirect = false;
do {
switch (Form) {
@ -243,7 +206,8 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,
case DW_FORM_line_strp:
case DW_FORM_GNU_ref_alt:
case DW_FORM_GNU_strp_alt:
if (Optional<uint8_t> FixedSize = ::getFixedByteSize(Form, U)) {
if (Optional<uint8_t> FixedSize =
DWARFFormValue::getFixedByteSize(Form, Params)) {
*OffsetPtr += *FixedSize;
return true;
}
@ -277,19 +241,6 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,
return true;
}
Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form,
const DWARFUnit *U) {
return ::getFixedByteSize(Form, U);
}
Optional<uint8_t>
DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version,
uint8_t AddrSize,
llvm::dwarf::DwarfFormat Format) {
FormSizeHelper FSH(Version, AddrSize, Format);
return ::getFixedByteSize(Form, &FSH);
}
bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
// First, check DWARF4 form classes.
if (Form < makeArrayRef(DWARF4FormClasses).size() &&
@ -448,24 +399,6 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data,
return true;
}
bool DWARFFormValue::skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
const DWARFUnit *U) const {
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U);
}
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
uint32_t *OffsetPtr, const DWARFUnit *U) {
return skipFormValue(Form, DebugInfoData, OffsetPtr, U);
}
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
uint32_t *OffsetPtr, uint16_t Version,
uint8_t AddrSize,
llvm::dwarf::DwarfFormat Format) {
FormSizeHelper FSH(Version, AddrSize, Format);
return skipFormValue(Form, DebugInfoData, OffsetPtr, &FSH);
}
void DWARFFormValue::dump(raw_ostream &OS) const {
uint64_t UValue = Value.uval;
bool CURelativeOffset = false;

View File

@ -62,11 +62,13 @@ DWARFUnit::~DWARFUnit() = default;
bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
uint64_t &Result) const {
uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
if (AddrOffsetSection->Data.size() < Offset + AddrSize)
uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize();
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
return false;
DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, AddrSize);
Result = getRelocatedValue(DA, AddrSize, &Offset, &AddrOffsetSection->Relocs);
DataExtractor DA(AddrOffsetSection->Data, isLittleEndian,
getAddressByteSize());
Result = getRelocatedValue(DA, getAddressByteSize(), &Offset,
&AddrOffsetSection->Relocs);
return true;
}
@ -92,15 +94,17 @@ uint64_t DWARFUnit::getStringOffsetSectionRelocation(uint32_t Index) const {
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
Length = debug_info.getU32(offset_ptr);
Version = debug_info.getU16(offset_ptr);
// FIXME: Support DWARF64.
FormParams.Format = DWARF32;
FormParams.Version = debug_info.getU16(offset_ptr);
uint64_t AbbrOffset;
if (Version >= 5) {
if (FormParams.Version >= 5) {
UnitType = debug_info.getU8(offset_ptr);
AddrSize = debug_info.getU8(offset_ptr);
FormParams.AddrSize = debug_info.getU8(offset_ptr);
AbbrOffset = debug_info.getU32(offset_ptr);
} else {
AbbrOffset = debug_info.getU32(offset_ptr);
AddrSize = debug_info.getU8(offset_ptr);
FormParams.AddrSize = debug_info.getU8(offset_ptr);
}
if (IndexEntry) {
if (AbbrOffset)
@ -115,14 +119,14 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
}
bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
bool VersionOK = DWARFContext::isSupportedVersion(Version);
bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;
if (!LengthOK || !VersionOK || !AddrSizeOK)
return false;
// Keep track of the highest DWARF version we encounter across all units.
Context.setMaxVersionIfGreater(Version);
Context.setMaxVersionIfGreater(getVersion());
Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
return Abbrevs != nullptr;
@ -148,7 +152,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
DWARFDebugRangeList &RangeList) const {
// Require that compile unit is extracted.
assert(!DieArray.empty());
DataExtractor RangesData(RangeSection->Data, isLittleEndian, AddrSize);
DataExtractor RangesData(RangeSection->Data, isLittleEndian,
getAddressByteSize());
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
return RangeList.extract(RangesData, &ActualRangeListOffset,
RangeSection->Relocs);
@ -157,9 +162,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
void DWARFUnit::clear() {
Offset = 0;
Length = 0;
Version = 0;
Abbrevs = nullptr;
AddrSize = 0;
FormParams = DWARFFormParams({0, 0, DWARF32});
BaseAddr = 0;
RangeSectionBase = 0;
AddrOffsetSectionBase = 0;

View File

@ -2063,10 +2063,12 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
DataExtractor Data = Unit.getDebugInfoExtractor();
for (unsigned i = 0; i < Idx; ++i)
DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset, &Unit);
DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset,
Unit.getFormParams());
uint32_t End = Offset;
DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, &Unit);
DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End,
Unit.getFormParams());
return std::make_pair(Offset, End);
}
@ -2219,7 +2221,8 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
DWARFFormValue Val(AttrSpec.Form);
if (!Val.isFormClass(DWARFFormValue::FC_Reference)) {
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, &Unit);
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
Unit.getFormParams());
continue;
}
@ -2779,7 +2782,8 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
for (const auto &AttrSpec : Abbrev->attributes()) {
if (shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap,
Flags & TF_SkipPC, Flags & TF_InFunctionScope)) {
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, &U);
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
U.getFormParams());
// FIXME: dsymutil-classic keeps the old abbreviation around
// even if it's not used. We can remove this (and the copyAbbrev
// helper) as soon as bit-for-bit compatibility is not a goal anymore.
@ -3077,7 +3081,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
// prologue over and that works because we act as both producer and
// consumer. It would be nicer to have a real configurable line
// table emitter.
if (LineTable.Prologue.Version != 2 ||
if (LineTable.Prologue.getVersion() != 2 ||
LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT ||
LineTable.Prologue.OpcodeBase > 13)
reportWarning("line table parameters mismatch. Cannot emit.");

View File

@ -182,8 +182,8 @@ static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
ID.Signature = InfoData.getU64(&Offset);
break;
default:
DWARFFormValue::skipValue(Form, InfoData, &Offset, Version, AddrSize,
Format);
DWARFFormValue::skipValue(Form, InfoData, &Offset,
DWARFFormParams({Version, AddrSize, Format}));
}
}
return ID;

View File

@ -23,43 +23,52 @@ namespace {
TEST(DWARFFormValue, FixedFormSizes) {
Optional<uint8_t> RefSize;
Optional<uint8_t> AddrSize;
// Test 32 bit DWARF version 2 with 4 byte addresses.
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
DWARFFormParams Params_2_4_32 = {2, 4, DWARF32};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32);
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_TRUE(AddrSize.hasValue());
EXPECT_EQ(*RefSize, *AddrSize);
// Test 32 bit DWARF version 2 with 8 byte addresses.
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
DWARFFormParams Params_2_8_32 = {2, 8, DWARF32};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32);
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_TRUE(AddrSize.hasValue());
EXPECT_EQ(*RefSize, *AddrSize);
// DW_FORM_ref_addr is 4 bytes in DWARF 32 in DWARF version 3 and beyond.
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 4, DWARF32);
DWARFFormParams Params_3_4_32 = {3, 4, DWARF32};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 4, DWARF32);
DWARFFormParams Params_4_4_32 = {4, 4, DWARF32};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 4, DWARF32);
DWARFFormParams Params_5_4_32 = {5, 4, DWARF32};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
// DW_FORM_ref_addr is 8 bytes in DWARF 64 in DWARF version 3 and beyond.
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 8, DWARF64);
DWARFFormParams Params_3_8_64 = {3, 8, DWARF64};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 8, DWARF64);
DWARFFormParams Params_4_8_64 = {4, 8, DWARF64};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 8, DWARF64);
DWARFFormParams Params_5_8_64 = {5, 8, DWARF64};
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
}