mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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:
parent
02f96cfdfc
commit
2cafddfdc8
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user