[DWARFv5] Support DW_FORM_strp in the .debug_line header.

Supporting this form in .debug_line.dwo will be done as a follow-up.

Differential Revision: https://reviews.llvm.org/D33155

llvm-svn: 317607
This commit is contained in:
Paul Robinson 2017-11-07 19:57:12 +00:00
parent 5c65148565
commit e5400f8a6e
13 changed files with 57 additions and 49 deletions

View File

@ -77,8 +77,10 @@ template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
// The second parameter is offset in .debug_line section // The second parameter is offset in .debug_line section
// for compilation unit (CU) of interest. We have only one // for compilation unit (CU) of interest. We have only one
// CU (object file), so offset is always 0. // CU (object file), so offset is always 0.
// FIXME: Provide the associated DWARFUnit if there is one. DWARF v5
// needs it in order to find indirect strings.
const DWARFDebugLine::LineTable *LT = const DWARFDebugLine::LineTable *LT =
DwarfLine->getOrParseLineTable(LineData, 0); DwarfLine->getOrParseLineTable(LineData, 0, nullptr);
// Return if there is no debug information about CU available. // Return if there is no debug information about CU available.
if (!Dwarf.getNumCompileUnits()) if (!Dwarf.getNumCompileUnits())

View File

@ -22,6 +22,7 @@
namespace llvm { namespace llvm {
class DWARFUnit;
class raw_ostream; class raw_ostream;
class DWARFDebugLine { class DWARFDebugLine {
@ -95,7 +96,8 @@ public:
void clear(); void clear();
void dump(raw_ostream &OS) const; void dump(raw_ostream &OS) const;
bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr); bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
const DWARFUnit *U = nullptr);
}; };
/// Standard .debug_line state machine structure. /// Standard .debug_line state machine structure.
@ -218,7 +220,7 @@ public:
/// Parse prologue and all rows. /// Parse prologue and all rows.
bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
raw_ostream *OS = nullptr); const DWARFUnit *U, raw_ostream *OS = nullptr);
using RowVector = std::vector<Row>; using RowVector = std::vector<Row>;
using RowIter = RowVector::const_iterator; using RowIter = RowVector::const_iterator;
@ -236,7 +238,7 @@ public:
const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getLineTable(uint32_t Offset) const;
const LineTable *getOrParseLineTable(const DWARFDataExtractor &DebugLineData, const LineTable *getOrParseLineTable(const DWARFDataExtractor &DebugLineData,
uint32_t Offset); uint32_t Offset, const DWARFUnit *U);
private: private:
struct ParsingState { struct ParsingState {

View File

@ -104,16 +104,12 @@ public:
const DWARFUnit *getUnit() const { return U; } const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
/// Extracts a value in \p Data at offset \p *OffsetPtr. /// Extracts a value in \p Data at offset \p *OffsetPtr. The information
/// /// in \p FormParams is needed to interpret some forms. The optional
/// The passed DWARFUnit is allowed to be nullptr, in which case some /// \p Unit allows extracting information if the form refers to other
/// kind of forms that depend on Unit information are disallowed. /// sections (e.g., .debug_str).
/// \param Data The DWARFDataExtractor to use.
/// \param OffsetPtr The offset within \p Data where the data starts.
/// \param U The optional DWARFUnit supplying information for some forms.
/// \returns whether the extraction succeeded.
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
const DWARFUnit *U); DWARFFormParams FormParams, const DWARFUnit *U = nullptr);
bool isInlinedCStr() const { bool isInlinedCStr() const {
return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;

View File

@ -184,7 +184,7 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
FormValue.setSValue(Spec.getImplicitConstValue()); FormValue.setSValue(Spec.getImplicitConstValue());
return FormValue; return FormValue;
} }
if (FormValue.extractValue(DebugInfoData, &Offset, &U)) if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
return FormValue; return FormValue;
} }
// March Offset along until we get to the attribute we want. // March Offset along until we get to the attribute we want.

View File

@ -90,10 +90,11 @@ std::pair<uint32_t, dwarf::Tag>
DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) { DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
uint32_t DieOffset = dwarf::DW_INVALID_OFFSET; uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
dwarf::Tag DieTag = dwarf::DW_TAG_null; dwarf::Tag DieTag = dwarf::DW_TAG_null;
DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
for (auto Atom : getAtomsDesc()) { for (auto Atom : getAtomsDesc()) {
DWARFFormValue FormValue(Atom.second); DWARFFormValue FormValue(Atom.second);
FormValue.extractValue(AccelSection, &HashDataOffset, NULL); FormValue.extractValue(AccelSection, &HashDataOffset, FormParams);
switch (Atom.first) { switch (Atom.first) {
case dwarf::DW_ATOM_die_offset: case dwarf::DW_ATOM_die_offset:
DieOffset = *FormValue.getAsUnsignedConstant(); DieOffset = *FormValue.getAsUnsignedConstant();
@ -145,6 +146,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
unsigned HashesBase = Offset + Hdr.NumBuckets * 4; unsigned HashesBase = Offset + Hdr.NumBuckets * 4;
unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;
DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) { for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) {
unsigned Index = AccelSection.getU32(&Offset); unsigned Index = AccelSection.getU32(&Offset);
@ -181,7 +183,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
unsigned i = 0; unsigned i = 0;
for (auto &Atom : AtomForms) { for (auto &Atom : AtomForms) {
OS << format("{Atom[%d]: ", i++); OS << format("{Atom[%d]: ", i++);
if (Atom.extractValue(AccelSection, &DataOffset, nullptr)) if (Atom.extractValue(AccelSection, &DataOffset, FormParams))
Atom.dump(OS); Atom.dump(OS);
else else
OS << "Error extracting the value"; OS << "Error extracting the value";
@ -216,8 +218,10 @@ void DWARFAcceleratorTable::ValueIterator::Next() {
NumData = 0; NumData = 0;
return; return;
} }
DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0,
dwarf::DwarfFormat::DWARF32};
for (auto &Atom : AtomForms) for (auto &Atom : AtomForms)
Atom.extractValue(AccelSection, &DataOffset, nullptr); Atom.extractValue(AccelSection, &DataOffset, FormParams);
++Data; ++Data;
} }

View File

@ -329,9 +329,9 @@ void DWARFContext::dump(
// representation. // representation.
OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n"; OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n";
if (DumpOpts.Verbose) { if (DumpOpts.Verbose) {
LineTable.parse(lineData, &Offset, &OS); LineTable.parse(lineData, &Offset, &*CU, &OS);
} else { } else {
LineTable.parse(lineData, &Offset); LineTable.parse(lineData, &Offset, &*CU);
LineTable.dump(OS); LineTable.dump(OS);
} }
} }
@ -349,7 +349,7 @@ void DWARFContext::dump(
DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(), DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(),
isLittleEndian(), savedAddressByteSize); isLittleEndian(), savedAddressByteSize);
DWARFDebugLine::LineTable LineTable; DWARFDebugLine::LineTable LineTable;
while (LineTable.Prologue.parse(lineData, &stmtOffset)) { while (LineTable.Prologue.parse(lineData, &stmtOffset, nullptr)) {
LineTable.dump(OS); LineTable.dump(OS);
LineTable.clear(); LineTable.clear();
} }
@ -681,7 +681,7 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
// We have to parse it first. // We have to parse it first.
DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
U->getAddressByteSize()); U->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset); return Line->getOrParseLineTable(lineData, stmtOffset, U);
} }
void DWARFContext::parseCompileUnits() { void DWARFContext::parseCompileUnits() {

View File

@ -144,7 +144,7 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
static bool static bool
parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, uint64_t EndPrologueOffset, uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
const DWARFFormParams &FormParams, const DWARFFormParams &FormParams, const DWARFUnit *U,
std::vector<StringRef> &IncludeDirectories, std::vector<StringRef> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
// Get the directory entry description. // Get the directory entry description.
@ -162,7 +162,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
DWARFFormValue Value(Descriptor.Form); DWARFFormValue Value(Descriptor.Form);
switch (Descriptor.Type) { switch (Descriptor.Type) {
case DW_LNCT_path: case DW_LNCT_path:
if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U))
return false; return false;
IncludeDirectories.push_back(Value.getAsCString().getValue()); IncludeDirectories.push_back(Value.getAsCString().getValue());
break; break;
@ -187,7 +187,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
DWARFDebugLine::FileNameEntry FileEntry; DWARFDebugLine::FileNameEntry FileEntry;
for (auto Descriptor : FileDescriptors) { for (auto Descriptor : FileDescriptors) {
DWARFFormValue Value(Descriptor.Form); DWARFFormValue Value(Descriptor.Form);
if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U))
return false; return false;
switch (Descriptor.Type) { switch (Descriptor.Type) {
case DW_LNCT_path: case DW_LNCT_path:
@ -213,7 +213,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
} }
bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr) { uint32_t *OffsetPtr, const DWARFUnit *U) {
const uint64_t PrologueOffset = *OffsetPtr; const uint64_t PrologueOffset = *OffsetPtr;
clear(); clear();
@ -253,7 +253,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
if (getVersion() >= 5) { if (getVersion() >= 5) {
if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
getFormParams(), IncludeDirectories, FileNames)) { getFormParams(), U, IncludeDirectories,
FileNames)) {
fprintf(stderr, fprintf(stderr,
"warning: parsing line table prologue at 0x%8.8" PRIx64 "warning: parsing line table prologue at 0x%8.8" PRIx64
" found an invalid directory or file table description at" " found an invalid directory or file table description at"
@ -382,24 +383,25 @@ DWARFDebugLine::getLineTable(uint32_t Offset) const {
const DWARFDebugLine::LineTable * const DWARFDebugLine::LineTable *
DWARFDebugLine::getOrParseLineTable(const DWARFDataExtractor &DebugLineData, DWARFDebugLine::getOrParseLineTable(const DWARFDataExtractor &DebugLineData,
uint32_t Offset) { uint32_t Offset, const DWARFUnit *U) {
std::pair<LineTableIter, bool> Pos = std::pair<LineTableIter, bool> Pos =
LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
LineTable *LT = &Pos.first->second; LineTable *LT = &Pos.first->second;
if (Pos.second) { if (Pos.second) {
if (!LT->parse(DebugLineData, &Offset)) if (!LT->parse(DebugLineData, &Offset, U))
return nullptr; return nullptr;
} }
return LT; return LT;
} }
bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, raw_ostream *OS) { uint32_t *OffsetPtr, const DWARFUnit *U,
raw_ostream *OS) {
const uint32_t DebugLineOffset = *OffsetPtr; const uint32_t DebugLineOffset = *OffsetPtr;
clear(); clear();
if (!Prologue.parse(DebugLineData, OffsetPtr)) { if (!Prologue.parse(DebugLineData, OffsetPtr, U)) {
// Restore our offset and return false to indicate failure! // Restore our offset and return false to indicate failure!
*OffsetPtr = DebugLineOffset; *OffsetPtr = DebugLineOffset;
return false; return false;

View File

@ -208,7 +208,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
DWARFUnit *U = Die.getDwarfUnit(); DWARFUnit *U = Die.getDwarfUnit();
DWARFFormValue formValue(Form); DWARFFormValue formValue(Form);
if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
U->getFormParams(), U))
return; return;
OS << "\t("; OS << "\t(";
@ -550,7 +551,7 @@ void DWARFDie::attribute_iterator::updateForIndex(
auto U = Die.getDwarfUnit(); auto U = Die.getDwarfUnit();
assert(U && "Die must have valid DWARF unit"); assert(U && "Die must have valid DWARF unit");
bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(),
&ParseOffset, U); &ParseOffset, U->getFormParams(), U);
(void)b; (void)b;
assert(b && "extractValue cannot fail on fully parsed DWARF"); assert(b && "extractValue cannot fail on fully parsed DWARF");
AttrValue.ByteSize = ParseOffset - AttrValue.Offset; AttrValue.ByteSize = ParseOffset - AttrValue.Offset;

View File

@ -276,7 +276,8 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
} }
bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
uint32_t *OffsetPtr, const DWARFUnit *CU) { uint32_t *OffsetPtr, DWARFFormParams FP,
const DWARFUnit *CU) {
U = CU; U = CU;
bool Indirect = false; bool Indirect = false;
bool IsBlock = false; bool IsBlock = false;
@ -288,10 +289,8 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
switch (Form) { switch (Form) {
case DW_FORM_addr: case DW_FORM_addr:
case DW_FORM_ref_addr: { case DW_FORM_ref_addr: {
if (!U) uint16_t Size =
return false; (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();
uint16_t Size = (Form == DW_FORM_addr) ? U->getAddressByteSize()
: U->getRefAddrByteSize();
Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex); Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex);
break; break;
} }
@ -360,10 +359,8 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
case DW_FORM_GNU_strp_alt: case DW_FORM_GNU_strp_alt:
case DW_FORM_line_strp: case DW_FORM_line_strp:
case DW_FORM_strp_sup: { case DW_FORM_strp_sup: {
if (!U)
return false;
Value.uval = Value.uval =
Data.getRelocatedValue(U->getDwarfOffsetByteSize(), OffsetPtr); Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), OffsetPtr);
break; break;
} }
case DW_FORM_flag_present: case DW_FORM_flag_present:

View File

@ -15,6 +15,10 @@ str_CU_5:
.asciz "V5_compile_unit" .asciz "V5_compile_unit"
str_TU_4: str_TU_4:
.asciz "V4_type_unit" .asciz "V4_type_unit"
str_LT_5a:
.asciz "Directory5a"
str_LT_5b:
.asciz "Directory5b"
.section .debug_str.dwo,"MS",@progbits,1 .section .debug_str.dwo,"MS",@progbits,1
dwo_TU_5: dwo_TU_5:
@ -227,11 +231,11 @@ LH_5_params:
# Directory table format # Directory table format
.byte 1 # One element per directory entry .byte 1 # One element per directory entry
.byte 1 # DW_LNCT_path .byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string .byte 0x0e # DW_FORM_strp (-> .debug_str)
# Directory table entries # Directory table entries
.byte 2 # Two directories .byte 2 # Two directories
.asciz "Directory5a" .long str_LT_5a
.asciz "Directory5b" .long str_LT_5b
# File table format # File table format
.byte 4 # Four elements per file entry .byte 4 # Four elements per file entry
.byte 1 # DW_LNCT_path .byte 1 # DW_LNCT_path

View File

@ -2366,7 +2366,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
continue; continue;
} }
Val.extractValue(Data, &Offset, &Unit); Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
CompileUnit *ReferencedCU; CompileUnit *ReferencedCU;
if (auto RefDie = if (auto RefDie =
resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) { resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) {
@ -2965,7 +2965,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
DWARFFormValue Val(AttrSpec.Form); DWARFFormValue Val(AttrSpec.Form);
uint32_t AttrSize = Offset; uint32_t AttrSize = Offset;
Val.extractValue(Data, &Offset, &U); Val.extractValue(Data, &Offset, U.getFormParams(), &U);
AttrSize = Offset - AttrSize; AttrSize = Offset - AttrSize;
OutOffset += OutOffset +=
@ -3158,7 +3158,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
DWARFDataExtractor LineExtractor( DWARFDataExtractor LineExtractor(
OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
LineTable.parse(LineExtractor, &StmtOffset); LineTable.parse(LineExtractor, &StmtOffset, &Unit.getOrigUnit());
// This vector is the output line table. // This vector is the output line table.
std::vector<DWARFDebugLine::Row> NewRows; std::vector<DWARFDebugLine::Row> NewRows;

View File

@ -99,7 +99,7 @@ DWARFFormValue createDataXFormValue(dwarf::Form Form, RawTypeT Value) {
DWARFFormValue Result(Form); DWARFFormValue Result(Form);
DWARFDataExtractor Data(StringRef(Raw, sizeof(RawTypeT)), DWARFDataExtractor Data(StringRef(Raw, sizeof(RawTypeT)),
sys::IsLittleEndianHost, sizeof(void *)); sys::IsLittleEndianHost, sizeof(void *));
Result.extractValue(Data, &Offset, nullptr); Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
return Result; return Result;
} }
@ -110,7 +110,7 @@ DWARFFormValue createULEBFormValue(uint64_t Value) {
uint32_t Offset = 0; uint32_t Offset = 0;
DWARFFormValue Result(DW_FORM_udata); DWARFFormValue Result(DW_FORM_udata);
DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *)); DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *));
Result.extractValue(Data, &Offset, nullptr); Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
return Result; return Result;
} }
@ -121,7 +121,7 @@ DWARFFormValue createSLEBFormValue(int64_t Value) {
uint32_t Offset = 0; uint32_t Offset = 0;
DWARFFormValue Result(DW_FORM_sdata); DWARFFormValue Result(DW_FORM_sdata);
DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *)); DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *));
Result.extractValue(Data, &Offset, nullptr); Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
return Result; return Result;
} }