Index: include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -20,6 +20,7 @@ namespace llvm { +class DWARFUnit; class raw_ostream; class DWARFDebugLine { @@ -93,7 +94,8 @@ void clear(); void dump(raw_ostream &OS) const; - bool parse(DataExtractor DebugLineData, uint32_t *OffsetPtr); + bool parse(DataExtractor DebugLineData, uint32_t *OffsetPtr, + const DWARFUnit *U, const RelocAddrMap *RMap = nullptr); }; /// Standard .debug_line state machine structure. @@ -214,7 +216,7 @@ /// Parse prologue and all rows. bool parse(DataExtractor DebugLineData, const RelocAddrMap *RMap, - uint32_t *OffsetPtr); + uint32_t *OffsetPtr, const DWARFUnit *U); struct Prologue Prologue; typedef std::vector RowVector; @@ -231,7 +233,7 @@ const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getOrParseLineTable(DataExtractor DebugLineData, - uint32_t Offset); + uint32_t Offset, const DWARFUnit *U); private: struct ParsingState { Index: include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -13,6 +13,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Dwarf.h" #include @@ -37,6 +38,37 @@ FC_Exprloc }; + struct FormValueInfo { + FormValueInfo() {} + FormValueInfo(const DWARFUnit *U) { Init(U); } + FormValueInfo(uint16_t Ver, uint8_t AddrByteSize, bool IsDwarf64) { + Init(nullptr, nullptr, Ver, AddrByteSize, IsDwarf64); + } + FormValueInfo(const DWARFUnit *U, const RelocAddrMap *RMap, uint16_t Ver, + uint8_t AddrByteSize, bool IsDwarf64) { + Init(U, RMap, Ver, AddrByteSize, IsDwarf64); + } + + const DWARFUnit *Unit = nullptr; + const RelocAddrMap *RelocMap = nullptr; + uint16_t Version = 0; + uint8_t AddrSize = 0; + uint8_t OffsetSize = 0; + + void Init(const DWARFUnit *U); + void Init(const DWARFUnit *U, const RelocAddrMap *RMap, uint16_t Ver, + uint8_t AddrByteSize, bool IsDwarf64) { + Unit = U; + RelocMap = RMap; + Version = Ver; + AddrSize = AddrByteSize; + OffsetSize = IsDwarf64 ? 8 : 4; + } + uint8_t getRefAddrByteSize() const { + return Version == 2 ? AddrSize : OffsetSize; + } + }; + private: struct ValueType { ValueType() { uval = 0; } @@ -51,7 +83,7 @@ dwarf::Form Form; // Form for this value. ValueType Value; // Contains all data for the form. - const DWARFUnit *U = nullptr; // Remember the DWARFUnit at extract time. + FormValueInfo Info; // Info useful during extraction. public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {} @@ -69,7 +101,6 @@ } bool isFormClass(FormClass FC) const; - const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS) const; /// Extracts a value in \p Data at offset \p *OffsetPtr. @@ -84,6 +115,24 @@ bool extractValue(const DataExtractor &Data, uint32_t *OffsetPtr, const DWARFUnit *U); + /// Extracts a value in \p Data at offset \p *OffsetPtr, from a section + /// other than .debug_info (e.g., .debug_line). + /// + /// The passed DWARFUnit mainly provides information about other sections + /// that might be needed for reference or indirect forms. Additional + /// parameters specify the relocations, DWARF format, and DWARF version to + /// use for interpreting certain forms. + /// \param Data The DataExtractor to use. + /// \param OffsetPtr The offset within DataExtractor where the data starts. + /// \param U The DWARFUnit supplying information about other sections. + /// \param RM The relocations for the section referenced by \p Data. + /// \param Format DWARF format (32-bit or 64-bit). + /// \param Version DWARF version number. + /// \returns whether the extraction succeeded. + bool extractValue(const DataExtractor &Data, uint32_t *OffsetPtr, + const DWARFUnit *U, const RelocAddrMap *RM, + uint16_t Version, uint8_t AddrSize, bool IsDwarf64); + bool isInlinedCStr() const { return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; } @@ -170,14 +219,34 @@ /// \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. + /// \param IsDwarf64 which DWARF format. /// \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); + bool IsDwarf64); + + /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr. + /// + /// Skips the bytes for this form in a section other than .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 DU a DWARFUnit describing other sections that might be needed. + /// \param RM relocations for the section used by \p DebugInfoData. + /// \param Version DWARF version number. + /// \param AddrSize size of an address in bytes. + /// \param IsDwarf64 which DWARF format. + /// \returns true on success, false if the form was not skipped. + bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, + const DWARFUnit *DU, const RelocAddrMap *RM, uint16_t Version, + uint8_t AddrSize, bool IsDwarf64); private: void dumpString(raw_ostream &OS) const; + bool extractValueImpl(const DataExtractor &DebugInfoData, + uint32_t *OffsetPtr); }; namespace dwarf { Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -168,7 +168,7 @@ savedAddressByteSize); DWARFDebugLine::LineTable LineTable; uint32_t Offset = *StmtOffset; - LineTable.parse(lineData, &getLineSection().Relocs, &Offset); + LineTable.parse(lineData, &getLineSection().Relocs, &Offset, &*CU); LineTable.dump(OS); } } @@ -190,7 +190,10 @@ DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; - while (LineTable.Prologue.parse(lineData, &stmtOffset)) { + DWARFUnit *U = nullptr; + if (!CUs.empty()) + U = &**CUs.begin(); + while (LineTable.Prologue.parse(lineData, &stmtOffset, U)) { LineTable.dump(OS); LineTable.clear(); } @@ -699,7 +702,7 @@ // We have to parse it first. DataExtractor lineData(U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); - return Line->getOrParseLineTable(lineData, stmtOffset); + return Line->getOrParseLineTable(lineData, stmtOffset, U); } void DWARFContext::parseCompileUnits() { Index: lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -136,8 +136,9 @@ static bool parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr, - uint64_t EndPrologueOffset, - std::vector &IncludeDirectories, + uint64_t EndPrologueOffset, const DWARFUnit *U, + const RelocAddrMap *RM, uint16_t Version, uint8_t AddrSize, + bool IsDwarf64, std::vector &IncludeDirectories, std::vector &FileNames) { // Get the directory entry description. ContentDescriptors DirDescriptors = @@ -154,12 +155,14 @@ DWARFFormValue Value(Descriptor.Form); switch (Descriptor.Type) { case DW_LNCT_path: - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, U, RM, Version, + AddrSize, IsDwarf64)) return false; IncludeDirectories.push_back(Value.getAsCString().getValue()); break; default: - if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.skipValue(DebugLineData, OffsetPtr, U, RM, Version, AddrSize, + IsDwarf64)) return false; } } @@ -179,7 +182,8 @@ DWARFDebugLine::FileNameEntry FileEntry; for (auto Descriptor : FileDescriptors) { DWARFFormValue Value(Descriptor.Form); - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, U, RM, Version, + AddrSize, IsDwarf64)) return false; switch (Descriptor.Type) { case DW_LNCT_path: @@ -205,7 +209,8 @@ } bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData, - uint32_t *OffsetPtr) { + uint32_t *OffsetPtr, const DWARFUnit *U, + const RelocAddrMap *RM) { const uint64_t PrologueOffset = *OffsetPtr; clear(); @@ -242,7 +247,8 @@ } if (Version >= 5) { - if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, + if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, U, + RM, Version, AddressSize, IsDWARF64, IncludeDirectories, FileNames)) { fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 @@ -372,12 +378,12 @@ const DWARFDebugLine::LineTable * DWARFDebugLine::getOrParseLineTable(DataExtractor DebugLineData, - uint32_t Offset) { + uint32_t Offset, const DWARFUnit *U) { std::pair Pos = LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { - if (!LT->parse(DebugLineData, RelocMap, &Offset)) + if (!LT->parse(DebugLineData, RelocMap, &Offset, U)) return nullptr; } return LT; @@ -385,12 +391,12 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor DebugLineData, const RelocAddrMap *RMap, - uint32_t *OffsetPtr) { + uint32_t *OffsetPtr, const DWARFUnit *U) { const uint32_t DebugLineOffset = *OffsetPtr; clear(); - if (!Prologue.parse(DebugLineData, OffsetPtr)) { + if (!Prologue.parse(DebugLineData, OffsetPtr, U, RMap)) { // Restore our offset and return false to indicate failure! *OffsetPtr = DebugLineOffset; return false; Index: lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -59,47 +59,20 @@ DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present }; -namespace { +typedef DWARFFormValue::FormValueInfo FormValueInfo; -/// 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 +void DWARFFormValue::FormValueInfo::Init(const DWARFUnit *U) { + if (U) + Init(U, U->getRelocMap(), U->getVersion(), U->getAddressByteSize(), + U->getFormat() == dwarf::DwarfFormat::DWARF64); +} -template -static Optional getFixedByteSize(dwarf::Form Form, const T *U) { +static Optional getFixedByteSize(dwarf::Form Form, + const FormValueInfo *I) { switch (Form) { case DW_FORM_addr: - if (U) - return U->getAddressByteSize(); + if (I) + return I->AddrSize; return None; case DW_FORM_block: // ULEB128 length L followed by L bytes. @@ -121,8 +94,8 @@ return None; case DW_FORM_ref_addr: - if (U) - return U->getRefAddrByteSize(); + if (I) + return I->getRefAddrByteSize(); return None; case DW_FORM_flag: @@ -151,8 +124,8 @@ case DW_FORM_line_strp: case DW_FORM_sec_offset: case DW_FORM_strp_sup: - if (U) - return U->getDwarfOffsetByteSize(); + if (I) + return I->OffsetSize; return None; case DW_FORM_data8: @@ -178,9 +151,8 @@ return None; } -template static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, - uint32_t *OffsetPtr, const T *U) { + uint32_t *OffsetPtr, const FormValueInfo *I) { bool Indirect = false; do { switch (Form) { @@ -240,7 +212,7 @@ case DW_FORM_line_strp: case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_strp_alt: - if (Optional FixedSize = ::getFixedByteSize(Form, U)) { + if (Optional FixedSize = ::getFixedByteSize(Form, I)) { *OffsetPtr += *FixedSize; return true; } @@ -276,15 +248,16 @@ Optional DWARFFormValue::getFixedByteSize(dwarf::Form Form, const DWARFUnit *U) { - return ::getFixedByteSize(Form, U); + FormValueInfo I(U); + return ::getFixedByteSize(Form, U ? &I : nullptr); } Optional DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version, uint8_t AddrSize, llvm::dwarf::DwarfFormat Format) { - FormSizeHelper FSH(Version, AddrSize, Format); - return ::getFixedByteSize(Form, &FSH); + FormValueInfo I(Version, AddrSize, Format == dwarf::DwarfFormat::DWARF64); + return ::getFixedByteSize(Form, &I); } bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { @@ -318,7 +291,21 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data, uint32_t *OffsetPtr, const DWARFUnit *CU) { - U = CU; + + Info.Init(CU); + return extractValueImpl(Data, OffsetPtr); +} + +bool DWARFFormValue::extractValue(const DataExtractor &Data, + uint32_t *OffsetPtr, const DWARFUnit *CU, + const RelocAddrMap *RM, uint16_t Version, + uint8_t AddrSize, bool IsDwarf64) { + Info.Init(CU, RM, Version, AddrSize, IsDwarf64); + return extractValueImpl(Data, OffsetPtr); +} + +bool DWARFFormValue::extractValueImpl(const DataExtractor &Data, + uint32_t *OffsetPtr) { bool Indirect = false; bool IsBlock = false; Value.data = nullptr; @@ -329,12 +316,11 @@ switch (Form) { case DW_FORM_addr: case DW_FORM_ref_addr: { - if (!U) + if (!Info.Unit) return false; - uint16_t AddrSize = (Form == DW_FORM_addr) ? U->getAddressByteSize() - : U->getRefAddrByteSize(); - Value.uval = - getRelocatedValue(Data, AddrSize, OffsetPtr, U->getRelocMap()); + uint16_t AddrSize = + (Form == DW_FORM_addr) ? Info.AddrSize : Info.getRefAddrByteSize(); + Value.uval = getRelocatedValue(Data, AddrSize, OffsetPtr, Info.RelocMap); break; } case DW_FORM_exprloc: @@ -371,11 +357,9 @@ case DW_FORM_ref4: case DW_FORM_ref_sup4: case DW_FORM_strx4: - case DW_FORM_addrx4: { - const RelocAddrMap *RelocMap = U ? U->getRelocMap() : nullptr; - Value.uval = getRelocatedValue(Data, 4, OffsetPtr, RelocMap); + case DW_FORM_addrx4: + Value.uval = getRelocatedValue(Data, 4, OffsetPtr, Info.RelocMap); break; - } case DW_FORM_data8: case DW_FORM_ref8: case DW_FORM_ref_sup8: @@ -401,10 +385,10 @@ case DW_FORM_GNU_strp_alt: case DW_FORM_line_strp: case DW_FORM_strp_sup: { - if (!U) + if (!Info.Unit) return false; - Value.uval = getRelocatedValue(Data, U->getDwarfOffsetByteSize(), - OffsetPtr, U->getRelocMap()); + Value.uval = + getRelocatedValue(Data, Info.OffsetSize, OffsetPtr, Info.RelocMap); break; } case DW_FORM_flag_present: @@ -441,17 +425,25 @@ return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U); } +bool DWARFFormValue::skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, + const DWARFUnit *U, const RelocAddrMap *RM, + uint16_t Version, uint8_t AddrSize, + bool IsDwarf64) { + FormValueInfo I(U, RM, Version, AddrSize, IsDwarf64); + return skipFormValue(Form, DebugInfoData, OffsetPtr, U ? &I : nullptr); +} + bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, uint32_t *OffsetPtr, const DWARFUnit *U) { - return skipFormValue(Form, DebugInfoData, OffsetPtr, U); + FormValueInfo I(U); + return skipFormValue(Form, DebugInfoData, OffsetPtr, U ? &I : nullptr); } 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); + uint8_t AddrSize, bool IsDwarf64) { + FormValueInfo I(Version, AddrSize, IsDwarf64); + return skipFormValue(Form, DebugInfoData, OffsetPtr, &I); } void DWARFFormValue::dump(raw_ostream &OS) const { @@ -465,9 +457,9 @@ case DW_FORM_GNU_addr_index: { OS << format(" indexed (%8.8x) address = ", (uint32_t)UValue); uint64_t Address; - if (U == nullptr) + if (Info.Unit == nullptr) OS << ""; - else if (U->getAddrOffsetSectionItem(UValue, Address)) + else if (Info.Unit->getAddrOffsetSectionItem(UValue, Address)) OS << format("0x%016" PRIx64, Address); else OS << ""; @@ -595,8 +587,8 @@ if (CURelativeOffset) { OS << " => {"; - WithColor(OS, syntax::Address).get() - << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0)); + WithColor(OS, syntax::Address).get() << format( + "0x%8.8" PRIx64, UValue + (Info.Unit ? Info.Unit->getOffset() : 0)); OS << "}"; } } @@ -617,16 +609,16 @@ if (Form == DW_FORM_string) return Value.cstr; // FIXME: Add support for DW_FORM_GNU_strp_alt - if (Form == DW_FORM_GNU_strp_alt || U == nullptr) + if (Form == DW_FORM_GNU_strp_alt || Info.Unit == nullptr) return None; uint32_t Offset = Value.uval; if (Form == DW_FORM_GNU_str_index) { uint32_t StrOffset; - if (!U->getStringOffsetSectionItem(Offset, StrOffset)) + if (!Info.Unit->getStringOffsetSectionItem(Offset, StrOffset)) return None; Offset = StrOffset; } - if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { + if (const char *Str = Info.Unit->getStringExtractor().getCStr(&Offset)) { return Str; } return None; @@ -638,7 +630,7 @@ if (Form == DW_FORM_GNU_addr_index) { uint32_t Index = Value.uval; uint64_t Result; - if (!U || !U->getAddrOffsetSectionItem(Index, Result)) + if (!Info.Unit || !Info.Unit->getAddrOffsetSectionItem(Index, Result)) return None; return Result; } @@ -654,9 +646,9 @@ case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - if (!U) + if (!Info.Unit) return None; - return Value.uval + U->getOffset(); + return Value.uval + Info.Unit->getOffset(); case DW_FORM_ref_addr: case DW_FORM_ref_sig8: case DW_FORM_GNU_ref_alt: Index: test/DebugInfo/Inputs/dwarfdump-header-64.s =================================================================== --- test/DebugInfo/Inputs/dwarfdump-header-64.s +++ test/DebugInfo/Inputs/dwarfdump-header-64.s @@ -0,0 +1,108 @@ +# Test object to verify dwarfdump handles a DWARF-64 v5 line header. +# FIXME: Make the other headers DWARF-64 also. +# FIXME: Add variants for earlier DWARF versions. + +# To generate the test object: +# llvm-mc -triple x86_64-unknown-linux dwarfdump-header-64.s -filetype=obj \ +# -o dwarfdump-header-64.elf-x86-64 + + .section .debug_str,"MS",@progbits,1 +str_producer: + .asciz "Handmade DWARF producer" +str_CU_5: + .asciz "V5_compile_unit" +str_LT_5a: + .asciz "Directory5a" +str_LT_5b: + .asciz "Directory5b" + + .section .debug_abbrev,"",@progbits + .byte 0x01 # Abbrev code + .byte 0x11 # DW_TAG_compile_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x25 # DW_AT_producer + .byte 0x0e # DW_FORM_strp + .byte 0x03 # DW_AT_name + .byte 0x0e # DW_FORM_strp + .byte 0x10 # DW_AT_stmt_list + .byte 0x17 # DW_FORM_sec_offset + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + + .section .debug_info,"",@progbits + +# DWARF-32 v5 normal CU header. + .long CU_5_end-CU_5_version # Length of Unit +CU_5_version: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section +# The compile-unit DIE, with DW_AT_producer, DW_AT_name, DW_AT_stmt_list. + .byte 1 + .long str_producer + .long str_CU_5 + .long LH_5_start + .byte 0 # NULL +CU_5_end: + + .section .debug_line,"",@progbits +# DWARF-64 v5 line-table header. +LH_5_start: + .long -1 + .quad LH_5_end-LH_5_version # Length of Unit +LH_5_version: + .short 5 # DWARF version number + .byte 8 # Address Size + .byte 0 # Segment Selector Size + .quad LH_5_header_end-LH_5_params # Length of Prologue +LH_5_params: + .byte 1 # Minimum Instruction Length + .byte 1 # Maximum Operations per Instruction + .byte 1 # Default is_stmt + .byte -5 # Line Base + .byte 14 # Line Range + .byte 13 # Opcode Base + .byte 0 # Standard Opcode Lengths + .byte 1 + .byte 1 + .byte 1 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 1 + # Directory table format + .byte 1 # One element per directory entry + .byte 1 # DW_LNCT_path + .byte 0x0e # DW_FORM_strp + # Directory table entries + .byte 2 # Two directories + .quad str_LT_5a + .quad str_LT_5b + # File table format + .byte 4 # Four elements per file entry + .byte 1 # DW_LNCT_path + .byte 0x08 # DW_FORM_string + .byte 2 # DW_LNCT_directory_index + .byte 0x0b # DW_FORM_data1 + .byte 3 # DW_LNCT_timestamp + .byte 0x0f # DW_FORM_udata + .byte 4 # DW_LNCT_size + .byte 0x0f # DW_FORM_udata + # File table entries + .byte 2 # Two files + .asciz "File5a" + .byte 1 + .byte 0x51 + .byte 0x52 + .asciz "File5b" + .byte 2 + .byte 0x53 + .byte 0x54 +LH_5_header_end: + # Line number program, which is empty. +LH_5_end: Index: test/DebugInfo/Inputs/dwarfdump-header.s =================================================================== --- test/DebugInfo/Inputs/dwarfdump-header.s +++ test/DebugInfo/Inputs/dwarfdump-header.s @@ -15,6 +15,10 @@ .asciz "V5_compile_unit" str_TU_4: .asciz "V4_type_unit" +str_LT_5a: + .asciz "Directory5a" +str_LT_5b: + .asciz "Directory5b" .section .debug_str.dwo,"MS",@progbits,1 dwo_TU_5: @@ -227,11 +231,11 @@ # Directory table format .byte 1 # One element per directory entry .byte 1 # DW_LNCT_path - .byte 0x08 # DW_FORM_string + .byte 0x0e # DW_FORM_strp # Directory table entries .byte 2 # Two directories - .asciz "Directory5a" - .asciz "Directory5b" + .long str_LT_5a + .long str_LT_5b # File table format .byte 4 # Four elements per file entry .byte 1 # DW_LNCT_path Index: test/DebugInfo/dwarfdump-header-64.test =================================================================== --- test/DebugInfo/dwarfdump-header-64.test +++ test/DebugInfo/dwarfdump-header-64.test @@ -0,0 +1,29 @@ +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-header-64.elf-x86-64 | FileCheck %s + +The input file is hand-coded assembler to generate DWARF-64 information, +so we're willing to make exact checks for offsets and such. + +CHECK-LABEL: .debug_info contents: + +The v5 CU header. + +CHECK: 0x00000000: Compile Unit: length = 0x00000016 version = 0x0005 unit_type = DW_UT_compile abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000001a) +CHECK: 0x0000000c: DW_TAG_compile_unit + +CHECK-LABEL: .debug_line contents: + +The DWARF-64 v5 line table header. + +CHECK: Line table prologue: +CHECK: total_length: 0x00000050 +CHECK: version: 5 +CHECK: address_size: 8 +CHECK: seg_select_size: 0 +CHECK: prologue_length: 0x00000044 +CHECK: max_ops_per_inst: 1 +CHECK: include_directories[ 1] = 'Directory5a' +CHECK: include_directories[ 2] = 'Directory5b' +CHECK-NOT: include_directories +CHECK: file_names[ 1] 1 0x00000051 0x00000052 File5a{{$}} +CHECK: file_names[ 2] 2 0x00000053 0x00000054 File5b{{$}} +CHECK-NOT: file_names Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -2984,7 +2984,7 @@ DataExtractor LineExtractor(LineData, OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); LineTable.parse(LineExtractor, &OrigDwarf.getLineSection().Relocs, - &StmtOffset); + &StmtOffset, &Unit.getOrigUnit()); // This vector is the output line table. std::vector NewRows;