Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -205,14 +205,25 @@ uint64_t Offset) { llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); + // Detect SectionIndex for specified section. + uint64_t SectionIndex = object::SectionedAddress::UndefSection; + ArrayRef Sections = S->File->getSections(); + for (uint64_t CurIndex = 0; CurIndex < Sections.size(); ++CurIndex) { + if (S == Sections[CurIndex]) { + SectionIndex = CurIndex; + break; + } + } + // Use fake address calcuated by adding section file offset and offset in // section. See comments for ObjectInfo class. DILineInfo Info; - for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) + for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) { if (LT->getFileLineInfoForAddress( - S->getOffsetInFile() + Offset, nullptr, + {S->getOffsetInFile() + Offset, SectionIndex}, nullptr, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info)) return Info; + } return None; } Index: llvm/include/llvm/DebugInfo/DIContext.h =================================================================== --- llvm/include/llvm/DebugInfo/DIContext.h +++ llvm/include/llvm/DebugInfo/DIContext.h @@ -203,11 +203,14 @@ return true; } - virtual DILineInfo getLineInfoForAddress(uint64_t Address, + virtual DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + virtual DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; private: Index: llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -317,13 +317,18 @@ /// Get the compilation unit, the function DIE and lexical block DIE for the /// given address where applicable. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" DIEsForAddress getDIEsForAddress(uint64_t Address); - DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; bool isLittleEndian() const { return DObj->isLittleEndian(); } @@ -366,6 +371,8 @@ private: /// Return the compile unit which contains instruction with provided /// address. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); }; Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -139,12 +139,16 @@ static void dumpTableHeader(raw_ostream &OS); static bool orderByAddress(const Row &LHS, const Row &RHS) { - return LHS.Address < RHS.Address; + return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) < + std::tie(RHS.Address.SectionIndex, RHS.Address.Address); } /// The program-counter value corresponding to a machine instruction - /// generated by the compiler. - uint64_t Address; + /// generated by the compiler and section index pointing to the section + /// containg this PC. If relocation information is present then section + /// index is the index of the section which contains above address. + /// Otherwise this is object::SectionedAddress::Undef value. + object::SectionedAddress Address; /// An unsigned integer indicating a source line number. Lines are numbered /// beginning at 1. The compiler may emit the value 0 in cases where an /// instruction cannot be attributed to any source line. @@ -192,6 +196,10 @@ /// and is described by line table rows [FirstRowIndex, LastRowIndex). uint64_t LowPC; uint64_t HighPC; + /// If relocation information is present then this is the index of the + /// section which contains above addresses. Otherwise this is + /// object::SectionedAddress::Undef value. + uint64_t SectionIndex; unsigned FirstRowIndex; unsigned LastRowIndex; bool Empty; @@ -199,14 +207,18 @@ void reset(); static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { - return LHS.LowPC < RHS.LowPC; + return std::tie(LHS.SectionIndex, LHS.LowPC) < + std::tie(RHS.SectionIndex, RHS.LowPC); } bool isValid() const { return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); } - bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } + bool containsPC(object::SectionedAddress PC) const { + return SectionIndex == PC.SectionIndex && + (LowPC <= PC.Address && PC.Address < HighPC); + } }; struct LineTable { @@ -223,9 +235,9 @@ /// Returns the index of the row with file/line info for a given address, /// or UnknownRowIndex if there is no such row. - uint32_t lookupAddress(uint64_t Address) const; + uint32_t lookupAddress(object::SectionedAddress Address) const; - bool lookupAddressRange(uint64_t Address, uint64_t Size, + bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector &Result) const; bool hasFileAtIndex(uint64_t FileIndex) const; @@ -238,7 +250,8 @@ /// Fills the Result argument with the file and line information /// corresponding to Address. Returns true on success. - bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + bool getFileLineInfoForAddress(object::SectionedAddress Address, + const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const; @@ -263,10 +276,15 @@ private: uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const; + object::SectionedAddress Address) const; Optional getSourceByIndex(uint64_t FileIndex, DILineInfoSpecifier::FileLineInfoKind Kind) const; + + uint32_t lookupAddressImpl(object::SectionedAddress Address) const; + + bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size, + std::vector &Result) const; }; const LineTable *getLineTable(uint32_t Offset) const; Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -76,7 +76,7 @@ /// list. Has to be passed base address of the compile unit referencing this /// range list. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional BaseAddr) const; + getAbsoluteRanges(llvm::Optional BaseAddr) const; }; } // end namespace llvm Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -37,7 +37,7 @@ Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, - llvm::function_ref(uint32_t)> + llvm::function_ref(uint32_t)> LookupPooledAddress) const; bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } }; @@ -47,7 +47,7 @@ public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional BaseAddr, + getAbsoluteRanges(llvm::Optional BaseAddr, DWARFUnit &U) const; }; Index: llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -74,7 +74,7 @@ const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, - SectionedAddress SA) const; + object::SectionedAddress SA) const; static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, DIDumpOptions DumpOpts, uint64_t SectionIndex); @@ -103,7 +103,7 @@ Optional getAsSignedConstant() const; Optional getAsCString() const; Optional getAsAddress() const; - Optional getAsSectionedAddress() const; + Optional getAsSectionedAddress() const; Optional getAsSectionOffset() const; Optional> getAsBlock() const; Optional getAsCStringOffset() const; @@ -241,7 +241,7 @@ return None; } -inline Optional +inline Optional toSectionedAddress(const Optional &V) { if (V) return V->getAsSectionedAddress(); Index: llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -157,7 +157,7 @@ uint8_t getAddrSize() const { return Header.getAddrSize(); } void dump(raw_ostream &OS, - llvm::function_ref(uint32_t)> + llvm::function_ref(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts = {}) const; @@ -234,7 +234,7 @@ template void DWARFListTableBase::dump( raw_ostream &OS, - llvm::function_ref(uint32_t)> + llvm::function_ref(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts) const { Header.dump(OS, DumpOpts); Index: llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -22,11 +22,6 @@ bool IsNameUnique; }; -struct SectionedAddress { - uint64_t Address; - uint64_t SectionIndex; -}; - } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H Index: llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -217,7 +217,7 @@ Optional RngListTable; mutable const DWARFAbbreviationDeclarationSet *Abbrevs; - llvm::Optional BaseAddr; + llvm::Optional BaseAddr; /// The compile unit debug information entry items. std::vector DieArray; @@ -304,7 +304,8 @@ RangeSectionBase = Base; } - Optional getAddrOffsetSectionItem(uint32_t Index) const; + Optional + getAddrOffsetSectionItem(uint32_t Index) const; Optional getStringOffsetSectionItem(uint32_t Index) const; DWARFDataExtractor getDebugInfoExtractor() const; @@ -375,7 +376,7 @@ llvm_unreachable("Invalid UnitType."); } - llvm::Optional getBaseAddress(); + llvm::Optional getBaseAddress(); DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); Index: llvm/include/llvm/DebugInfo/PDB/PDBContext.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/PDBContext.h +++ llvm/include/llvm/DebugInfo/PDB/PDBContext.h @@ -43,13 +43,13 @@ void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override; DILineInfo getLineInfoForAddress( - uint64_t Address, + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoTable getLineInfoForAddressRange( - uint64_t Address, uint64_t Size, + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DIInliningInfo getInliningInfoForAddress( - uint64_t Address, + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; private: Index: llvm/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h =================================================================== --- llvm/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h +++ llvm/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h @@ -24,13 +24,14 @@ public: virtual ~SymbolizableModule() = default; - virtual DILineInfo symbolizeCode(uint64_t ModuleOffset, + virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const = 0; - virtual DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const = 0; - virtual DIGlobal symbolizeData(uint64_t ModuleOffset) const = 0; + virtual DIInliningInfo + symbolizeInlinedCode(object::SectionedAddress ModuleOffset, + FunctionNameKind FNKind, bool UseSymbolTable) const = 0; + virtual DIGlobal + symbolizeData(object::SectionedAddress ModuleOffset) const = 0; // Return true if this is a 32-bit x86 PE COFF module. virtual bool isWin32Module() const = 0; Index: llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h =================================================================== --- llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -60,13 +60,14 @@ } Expected symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset, + object::SectionedAddress ModuleOffset, StringRef DWPName = ""); - Expected symbolizeInlinedCode(const std::string &ModuleName, - uint64_t ModuleOffset, - StringRef DWPName = ""); + Expected + symbolizeInlinedCode(const std::string &ModuleName, + object::SectionedAddress ModuleOffset, + StringRef DWPName = ""); Expected symbolizeData(const std::string &ModuleName, - uint64_t ModuleOffset); + object::SectionedAddress ModuleOffset); void flush(); static std::string Index: llvm/include/llvm/Object/ObjectFile.h =================================================================== --- llvm/include/llvm/Object/ObjectFile.h +++ llvm/include/llvm/Object/ObjectFile.h @@ -135,6 +135,30 @@ const ObjectFile *getObject() const; }; +struct SectionedAddress { + // TODO: constructors could be removed when C++14 would be adopted. + SectionedAddress() {} + SectionedAddress(uint64_t Addr, uint64_t SectIdx) + : Address(Addr), SectionIndex(SectIdx) {} + + const static uint64_t UndefSection = UINT64_MAX; + + uint64_t Address = 0; + uint64_t SectionIndex = UndefSection; +}; + +inline bool operator<(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) < + std::tie(RHS.SectionIndex, RHS.Address); +} + +inline bool operator==(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) == + std::tie(RHS.SectionIndex, RHS.Address); +} + /// This is a value type class that represents a single symbol in the list of /// symbols in the object file. class SymbolRef : public BasicSymbolRef { Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -268,11 +268,11 @@ } // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). -static void -dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, - llvm::function_ref(uint32_t)> - LookupPooledAddress, - DIDumpOptions DumpOpts) { +static void dumpRnglistsSection( + raw_ostream &OS, DWARFDataExtractor &rnglistData, + llvm::function_ref(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; @@ -938,6 +938,8 @@ return Result; } +/// TODO: change input parameter from "uint64_t Address" +/// into "SectionedAddress Address" static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, @@ -966,36 +968,37 @@ return FoundResult; } -DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, +DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DILineInfo Result; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Result; - getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, - Result.FunctionName, - Result.StartLine); + + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, + Result.FunctionName, Result.StartLine); if (Spec.FLIKind != FileLineInfoKind::None) { - if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Result); + if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { + LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), + Spec.FLIKind, Result); + } } return Result; } -DILineInfoTable -DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, - DILineInfoSpecifier Spec) { +DILineInfoTable DWARFContext::getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { DILineInfoTable Lines; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Lines; std::string FunctionName = ""; uint32_t StartLine = 0; - getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName, - StartLine); + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, + FunctionName, StartLine); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. @@ -1003,7 +1006,7 @@ DILineInfo Result; Result.FunctionName = FunctionName; Result.StartLine = StartLine; - Lines.push_back(std::make_pair(Address, Result)); + Lines.push_back(std::make_pair(Address.Address, Result)); return Lines; } @@ -1011,8 +1014,10 @@ // Get the index of row we're looking for in the line table. std::vector RowVector; - if (!LineTable->lookupAddressRange(Address, Size, RowVector)) + if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex}, + Size, RowVector)) { return Lines; + } for (uint32_t RowIndex : RowVector) { // Take file number and line/column from the row. @@ -1024,33 +1029,33 @@ Result.Line = Row.Line; Result.Column = Row.Column; Result.StartLine = StartLine; - Lines.push_back(std::make_pair(Row.Address, Result)); + Lines.push_back(std::make_pair(Row.Address.Address, Result)); } return Lines; } DIInliningInfo -DWARFContext::getInliningInfoForAddress(uint64_t Address, +DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DIInliningInfo InliningInfo; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return InliningInfo; const DWARFLineTable *LineTable = nullptr; SmallVector InlinedChain; - CU->getInlinedChainForAddress(Address, InlinedChain); + CU->getInlinedChainForAddress(Address.Address, InlinedChain); if (InlinedChain.size() == 0) { // If there is no DIE for address (e.g. it is in unavailable .dwo file), // try to at least get file/line info from symbol table. if (Spec.FLIKind != FileLineInfoKind::None) { DILineInfo Frame; LineTable = getLineTableForUnit(CU); - if (LineTable && - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame)) + if (LineTable && LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, + CU->getCompilationDir(), Spec.FLIKind, Frame)) InliningInfo.addFrame(Frame); } return InliningInfo; @@ -1072,8 +1077,9 @@ LineTable = getLineTableForUnit(CU); // For the topmost routine, get file/line info from line table. if (LineTable) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame); + LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), + Spec.FLIKind, Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. Index: llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -15,7 +15,7 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t *SecNdx) const { if (SecNdx) - *SecNdx = -1ULL; + *SecNdx = object::SectionedAddress::UndefSection; if (!Section) return getUnsigned(Off, Size); Optional Rel = Obj->find(*Section, *Off); Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -353,7 +353,8 @@ } void DWARFDebugLine::Row::reset(bool DefaultIsStmt) { - Address = 0; + Address.Address = 0; + Address.SectionIndex = object::SectionedAddress::UndefSection; Line = 1; Column = 0; File = 1; @@ -373,7 +374,7 @@ } void DWARFDebugLine::Row::dump(raw_ostream &OS) const { - OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column) + OS << format("0x%16.16" PRIx64 " %6u %6u", Address.Address, Line, Column) << format(" %6u %3u %13u ", File, Isa, Discriminator) << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "") << (PrologueEnd ? " prologue_end" : "") @@ -386,6 +387,7 @@ void DWARFDebugLine::Sequence::reset() { LowPC = 0; HighPC = 0; + SectionIndex = object::SectionedAddress::UndefSection; FirstRowIndex = 0; LastRowIndex = 0; Empty = true; @@ -426,15 +428,16 @@ if (Sequence.Empty) { // Record the beginning of instruction sequence. Sequence.Empty = false; - Sequence.LowPC = Row.Address; + Sequence.LowPC = Row.Address.Address; Sequence.FirstRowIndex = RowNumber; } ++RowNumber; LineTable->appendRow(Row); if (Row.EndSequence) { // Record the end of instruction sequence. - Sequence.HighPC = Row.Address; + Sequence.HighPC = Row.Address.Address; Sequence.LastRowIndex = RowNumber; + Sequence.SectionIndex = Row.Address.SectionIndex; if (Sequence.isValid()) LineTable->appendSequence(Sequence); Sequence.reset(); @@ -565,9 +568,10 @@ ExtOffset, DebugLineData.getAddressSize(), Len - 1); } - State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr); + State.Row.Address.Address = DebugLineData.getRelocatedAddress( + OffsetPtr, &State.Row.Address.SectionIndex); if (OS) - *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address); + *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address); break; case DW_LNE_define_file: @@ -654,7 +658,7 @@ { uint64_t AddrOffset = DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) *OS << " (" << AddrOffset << ")"; } @@ -712,7 +716,7 @@ uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase; uint64_t AddrOffset = (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) *OS << format(" (0x%16.16" PRIx64 ")", AddrOffset); @@ -731,7 +735,7 @@ // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. { uint16_t PCOffset = DebugLineData.getU16(OffsetPtr); - State.Row.Address += PCOffset; + State.Row.Address.Address += PCOffset; if (OS) *OS << format(" (0x%16.16" PRIx64 ")", PCOffset); @@ -814,7 +818,7 @@ int32_t LineOffset = Prologue.LineBase + (AdjustOpcode % Prologue.LineRange); State.Row.Line += LineOffset; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) { *OS << "address += " << AddrOffset << ", line += " << LineOffset @@ -850,11 +854,12 @@ return Error::success(); } -uint32_t -DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const { +uint32_t DWARFDebugLine::LineTable::findRowInSeq( + const DWARFDebugLine::Sequence &Seq, + object::SectionedAddress Address) const { if (!Seq.containsPC(Address)) return UnknownRowIndex; + assert(Seq.SectionIndex == Address.SectionIndex); // Search for instruction address in the rows describing the sequence. // Rows are stored in a vector, so we may use arithmetical operations with // iterators. @@ -867,8 +872,9 @@ if (RowPos == LastRow) { return Seq.LastRowIndex - 1; } + assert(Seq.SectionIndex == RowPos->Address.SectionIndex); uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow); - if (RowPos->Address > Address) { + if (RowPos->Address.Address > Address.Address) { if (RowPos == FirstRow) return UnknownRowIndex; else @@ -877,42 +883,81 @@ return Index; } -uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const { +uint32_t DWARFDebugLine::LineTable::lookupAddress( + object::SectionedAddress Address) const { + + // Search for relocatable addresses + uint32_t Result = lookupAddressImpl(Address); + + if (Result != UnknownRowIndex || + Address.SectionIndex == object::SectionedAddress::UndefSection) + return Result; + + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + return lookupAddressImpl(Address); +} + +uint32_t DWARFDebugLine::LineTable::lookupAddressImpl( + object::SectionedAddress Address) const { if (Sequences.empty()) return UnknownRowIndex; // First, find an instruction sequence containing the given address. DWARFDebugLine::Sequence Sequence; - Sequence.LowPC = Address; + Sequence.SectionIndex = Address.SectionIndex; + Sequence.LowPC = Address.Address; SequenceIter FirstSeq = Sequences.begin(); SequenceIter LastSeq = Sequences.end(); SequenceIter SeqPos = std::lower_bound( FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); DWARFDebugLine::Sequence FoundSeq; + if (SeqPos == LastSeq) { FoundSeq = Sequences.back(); - } else if (SeqPos->LowPC == Address) { + } else if (SeqPos->LowPC == Address.Address && + SeqPos->SectionIndex == Address.SectionIndex) { FoundSeq = *SeqPos; } else { if (SeqPos == FirstSeq) return UnknownRowIndex; FoundSeq = *(SeqPos - 1); } + if (FoundSeq.SectionIndex != Address.SectionIndex) + return UnknownRowIndex; return findRowInSeq(FoundSeq, Address); } bool DWARFDebugLine::LineTable::lookupAddressRange( - uint64_t Address, uint64_t Size, std::vector &Result) const { + object::SectionedAddress Address, uint64_t Size, + std::vector &Result) const { + + // Search for relocatable addresses + if (lookupAddressRangeImpl(Address, Size, Result)) + return true; + + if (Address.SectionIndex == object::SectionedAddress::UndefSection) + return false; + + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + return lookupAddressRangeImpl(Address, Size, Result); +} + +bool DWARFDebugLine::LineTable::lookupAddressRangeImpl( + object::SectionedAddress Address, uint64_t Size, + std::vector &Result) const { if (Sequences.empty()) return false; - uint64_t EndAddr = Address + Size; + uint64_t EndAddr = Address.Address + Size; // First, find an instruction sequence containing the given address. DWARFDebugLine::Sequence Sequence; - Sequence.LowPC = Address; + Sequence.SectionIndex = Address.SectionIndex; + Sequence.LowPC = Address.Address; SequenceIter FirstSeq = Sequences.begin(); SequenceIter LastSeq = Sequences.end(); SequenceIter SeqPos = std::lower_bound( FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); - if (SeqPos == LastSeq || SeqPos->LowPC != Address) { + if (SeqPos == LastSeq || !SeqPos->containsPC(Address)) { if (SeqPos == FirstSeq) return false; SeqPos--; @@ -934,7 +979,8 @@ FirstRowIndex = findRowInSeq(CurSeq, Address); // Figure out the last row in the range. - uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1); + uint32_t LastRowIndex = + findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex}); if (LastRowIndex == UnknownRowIndex) LastRowIndex = CurSeq.LastRowIndex - 1; @@ -1011,8 +1057,8 @@ } bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( - uint64_t Address, const char *CompDir, FileLineInfoKind Kind, - DILineInfo &Result) const { + object::SectionedAddress Address, const char *CompDir, + FileLineInfoKind Kind, DILineInfo &Result) const { // Get the index of row we're looking for in the line table. uint32_t RowIndex = lookupAddress(Address); if (RowIndex == -1U) Index: llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -68,7 +68,7 @@ } DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( - llvm::Optional BaseAddr) const { + llvm::Optional BaseAddr) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { Index: llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -112,9 +112,8 @@ return Error::success(); } -DWARFAddressRangesVector -DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional BaseAddr, - DWARFUnit &U) const { +DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( + llvm::Optional BaseAddr, DWARFUnit &U) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) @@ -174,7 +173,7 @@ void RangeListEntry::dump( raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, - llvm::function_ref(uint32_t)> + llvm::function_ref(uint32_t)> LookupPooledAddress) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, uint8_t AddrSize, DIDumpOptions DumpOpts) { Index: llvm/lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -100,7 +100,7 @@ auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { uint64_t BaseAddr = 0; - if (Optional BA = U->getBaseAddress()) + if (Optional BA = U->getBaseAddress()) BaseAddr = BA->Address; LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, BaseAddr, Indent); @@ -125,7 +125,7 @@ Data, &Offset, UseLocLists ? U->getVersion() : 4); uint64_t BaseAddr = 0; - if (Optional BA = U->getBaseAddress()) + if (Optional BA = U->getBaseAddress()) BaseAddr = BA->Address; if (LL) Index: llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -332,7 +332,7 @@ void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, - SectionedAddress SA) const { + object::SectionedAddress SA) const { OS << format("0x%016" PRIx64, SA.Address); dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, SA.SectionIndex); @@ -369,7 +369,7 @@ case DW_FORM_addrx3: case DW_FORM_addrx4: case DW_FORM_GNU_addr_index: { - Optional A = U->getAddrOffsetSectionItem(UValue); + Optional A = U->getAddrOffsetSectionItem(UValue); if (!A || DumpOpts.Verbose) AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); if (U == nullptr) @@ -590,14 +590,15 @@ return SA->Address; return None; } -Optional DWARFFormValue::getAsSectionedAddress() const { +Optional +DWARFFormValue::getAsSectionedAddress() const { if (!isFormClass(FC_Address)) return None; if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) { uint32_t Index = Value.uval; if (!U) return None; - Optional SA = U->getAddrOffsetSectionItem(Index); + Optional SA = U->getAddrOffsetSectionItem(Index); if (!SA) return None; return SA; Index: llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -197,7 +197,7 @@ getAddressByteSize()); } -Optional +Optional DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (IsDWO) { auto R = Context.info_section_units(); @@ -744,7 +744,7 @@ return Abbrevs; } -llvm::Optional DWARFUnit::getBaseAddress() { +llvm::Optional DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; Index: llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -772,7 +772,7 @@ uint32_t RowIndex = 0; for (const auto &Row : LineTable->Rows) { // Verify row address. - if (Row.Address < PrevAddress) { + if (Row.Address.Address < PrevAddress) { ++NumDebugLineErrors; error() << ".debug_line[" << format("0x%08" PRIx64, @@ -802,7 +802,7 @@ if (Row.EndSequence) PrevAddress = 0; else - PrevAddress = Row.Address; + PrevAddress = Row.Address.Address; ++RowIndex; } } Index: llvm/lib/DebugInfo/PDB/PDBContext.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -30,14 +30,14 @@ void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){} -DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address, +DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier) { DILineInfo Result; - Result.FunctionName = getFunctionName(Address, Specifier.FNKind); + Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind); uint32_t Length = 1; std::unique_ptr Symbol = - Session->findSymbolByAddress(Address, PDB_SymType::None); + Session->findSymbolByAddress(Address.Address, PDB_SymType::None); if (auto Func = dyn_cast_or_null(Symbol.get())) { Length = Func->getLength(); } else if (auto Data = dyn_cast_or_null(Symbol.get())) { @@ -46,7 +46,7 @@ // If we couldn't find a symbol, then just assume 1 byte, so that we get // only the line number of the first instruction. - auto LineNumbers = Session->findLineNumbersByAddress(Address, Length); + auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length); if (!LineNumbers || LineNumbers->getChildCount() == 0) return Result; @@ -63,26 +63,27 @@ } DILineInfoTable -PDBContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, +PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, + uint64_t Size, DILineInfoSpecifier Specifier) { if (Size == 0) return DILineInfoTable(); DILineInfoTable Table; - auto LineNumbers = Session->findLineNumbersByAddress(Address, Size); + auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size); if (!LineNumbers || LineNumbers->getChildCount() == 0) return Table; while (auto LineInfo = LineNumbers->getNext()) { - DILineInfo LineEntry = - getLineInfoForAddress(LineInfo->getVirtualAddress(), Specifier); + DILineInfo LineEntry = getLineInfoForAddress( + {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier); Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry)); } return Table; } DIInliningInfo -PDBContext::getInliningInfoForAddress(uint64_t Address, +PDBContext::getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier) { DIInliningInfo InlineInfo; DILineInfo Frame = getLineInfoForAddress(Address, Specifier); Index: llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h =================================================================== --- llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h @@ -33,12 +33,13 @@ static ErrorOr> create(object::ObjectFile *Obj, std::unique_ptr DICtx); - DILineInfo symbolizeCode(uint64_t ModuleOffset, FunctionNameKind FNKind, + DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, + FunctionNameKind FNKind, bool UseSymbolTable) const override; - DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, + DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const override; - DIGlobal symbolizeData(uint64_t ModuleOffset) const override; + DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override; // Return true if this is a 32-bit x86 PE COFF module. bool isWin32Module() const override; Index: llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp =================================================================== --- llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -222,9 +222,10 @@ isa(DebugInfoContext.get()); } -DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const { +DILineInfo +SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset, + FunctionNameKind FNKind, + bool UseSymbolTable) const { DILineInfo LineInfo; if (DebugInfoContext) { LineInfo = DebugInfoContext->getLineInfoForAddress( @@ -234,7 +235,7 @@ if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { std::string FunctionName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, + if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, FunctionName, Start, Size)) { LineInfo.FunctionName = FunctionName; } @@ -243,7 +244,8 @@ } DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( - uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const { + object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable) const { DIInliningInfo InlinedContext; if (DebugInfoContext) @@ -257,7 +259,7 @@ if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { std::string FunctionName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, + if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, FunctionName, Start, Size)) { InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1) ->FunctionName = FunctionName; @@ -267,9 +269,10 @@ return InlinedContext; } -DIGlobal SymbolizableObjectFile::symbolizeData(uint64_t ModuleOffset) const { +DIGlobal SymbolizableObjectFile::symbolizeData( + object::SectionedAddress ModuleOffset) const { DIGlobal Res; - getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Res.Name, Res.Start, - Res.Size); + getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name, + Res.Start, Res.Size); return Res; } Index: llvm/lib/DebugInfo/Symbolize/Symbolize.cpp =================================================================== --- llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -52,7 +52,8 @@ Expected LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset, StringRef DWPName) { + object::SectionedAddress ModuleOffset, + StringRef DWPName) { SymbolizableModule *Info; if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) Info = InfoOrErr.get(); @@ -67,7 +68,7 @@ // If the user is giving us relative addresses, add the preferred base of the // object to the offset before we do the query. It's what DIContext expects. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); @@ -78,7 +79,8 @@ Expected LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, - uint64_t ModuleOffset, StringRef DWPName) { + object::SectionedAddress ModuleOffset, + StringRef DWPName) { SymbolizableModule *Info; if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) Info = InfoOrErr.get(); @@ -93,7 +95,7 @@ // If the user is giving us relative addresses, add the preferred base of the // object to the offset before we do the query. It's what DIContext expects. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DIInliningInfo InlinedContext = Info->symbolizeInlinedCode( ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); @@ -106,8 +108,9 @@ return InlinedContext; } -Expected LLVMSymbolizer::symbolizeData(const std::string &ModuleName, - uint64_t ModuleOffset) { +Expected +LLVMSymbolizer::symbolizeData(const std::string &ModuleName, + object::SectionedAddress ModuleOffset) { SymbolizableModule *Info; if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) Info = InfoOrErr.get(); @@ -123,7 +126,7 @@ // the object to the offset before we do the query. It's what DIContext // expects. if (Opts.RelativeAddresses) - ModuleOffset += Info->getModulePreferredBase(); + ModuleOffset.Address += Info->getModulePreferredBase(); DIGlobal Global = Info->symbolizeData(ModuleOffset); if (Opts.Demangle) Index: llvm/test/tools/llvm-objdump/X86/function-sections-line-numbers.s =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/X86/function-sections-line-numbers.s @@ -0,0 +1,221 @@ +# The code below is the reduced version of the output +# from the following invocation and source: +# +# // test.cpp: +#void f1() {} +#void f2() {} +# +# clang -gdwarf-5 -ffunction-sections test.cpp -o test.s -S + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -dwarf-version=5 %s -o %t.o +# RUN: llvm-objdump -disassemble -line-numbers -r -s -section-headers -t %t.o | FileCheck %s + + +# CHECK: 0000000000000000 _Z2f1v +# CHECK-NOT: test.cpp:2 +# CHECK: test.cpp:1 +# CHECK-NOT: test.cpp:2 +# CHECK: 0000000000000000 _Z2f2v +# CHECK-NOT: test.cpp:1 +# CHECK: test.cpp:2 +# CHECK-NOT: test.cpp:1 + + + .text + .file "test.cpp" + .section .text._Z2f1v,"ax",@progbits + .globl _Z2f1v # -- Begin function _Z2f1v + .p2align 4, 0x90 + .type _Z2f1v,@function +_Z2f1v: # @_Z2f1v +.Lfunc_begin0: + .file 0 "/home/avl" "test.cpp" md5 0xefae234cc05b45384d782316d3a5d338 + .file 1 "test.cpp" md5 0xefae234cc05b45384d782316d3a5d338 + .loc 1 1 0 # test.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 1 1 12 prologue_end # test.cpp:1:12 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size _Z2f1v, .Lfunc_end0-_Z2f1v + .cfi_endproc + # -- End function + .section .text._Z2f2v,"ax",@progbits + .globl _Z2f2v # -- Begin function _Z2f2v + .p2align 4, 0x90 + .type _Z2f2v,@function +_Z2f2v: # @_Z2f2v +.Lfunc_begin1: + .loc 1 2 0 # test.cpp:2:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp2: + .loc 1 2 12 prologue_end # test.cpp:2:12 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end1: + .size _Z2f2v, .Lfunc_end1-_Z2f2v + .cfi_endproc + # -- End function + .section .debug_str_offsets,"",@progbits + .long 32 + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 9.0.0 (https://github.com/llvm/llvm-project.git ebfc1e5af7a65381d858612517e6414ef58df482)" # string offset=0 +.Linfo_string1: + .asciz "test.cpp" # string offset=104 +.Linfo_string2: + .asciz "/home/avl" # string offset=113 +.Linfo_string3: + .asciz "_Z2f1v" # string offset=123 +.Linfo_string4: + .asciz "f1" # string offset=130 +.Linfo_string5: + .asciz "_Z2f2v" # string offset=133 +.Linfo_string6: + .asciz "f2" # string offset=140 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 35 # DW_FORM_rnglistx + .byte 116 # DW_AT_rnglists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x38 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 4 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .long .Laddr_table_base0 # DW_AT_addr_base + .quad 0 # DW_AT_low_pc + .byte 0 # DW_AT_ranges + .long .Lrnglists_table_base0 # DW_AT_rnglists_base + .byte 2 # Abbrev [2] 0x2b:0xc DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + .byte 2 # Abbrev [2] 0x37:0xc DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 5 # DW_AT_linkage_name + .byte 6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_rnglists,"",@progbits + .long .Ldebug_rnglist_table_end0-.Ldebug_rnglist_table_start0 # Length +.Ldebug_rnglist_table_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lrnglists_table_base0: + .long .Ldebug_ranges0-.Lrnglists_table_base0 +.Ldebug_ranges0: + .byte 3 # DW_RLE_startx_length + .byte 0 # start index + .uleb128 .Lfunc_end0-.Lfunc_begin0 # length + .byte 3 # DW_RLE_startx_length + .byte 1 # start index + .uleb128 .Lfunc_end1-.Lfunc_begin1 # length + .byte 0 # DW_RLE_end_of_list +.Ldebug_rnglist_table_end0: +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + + .section .debug_line,"",@progbits +.Lline_table_start0: Index: llvm/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinker.cpp +++ llvm/tools/dsymutil/DwarfLinker.cpp @@ -1734,17 +1734,17 @@ // it is marked as end_sequence in the input (because in that // case, the relocation offset is accurate and that entry won't // serve as the start of another function). - if (CurrRange == InvalidRange || Row.Address < CurrRange.start() || - Row.Address > CurrRange.stop() || - (Row.Address == CurrRange.stop() && !Row.EndSequence)) { + if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() || + Row.Address.Address > CurrRange.stop() || + (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) { // We just stepped out of a known range. Insert a end_sequence // corresponding to the end of the range. uint64_t StopAddress = CurrRange != InvalidRange ? CurrRange.stop() + CurrRange.value() : -1ULL; - CurrRange = FunctionRanges.find(Row.Address); + CurrRange = FunctionRanges.find(Row.Address.Address); bool CurrRangeValid = - CurrRange != InvalidRange && CurrRange.start() <= Row.Address; + CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address; if (!CurrRangeValid) { CurrRange = InvalidRange; if (StopAddress != -1ULL) { @@ -1754,13 +1754,13 @@ // for now do as dsymutil. // FIXME: Understand exactly what cases this addresses and // potentially remove it along with the Ranges map. - auto Range = Ranges.lower_bound(Row.Address); + auto Range = Ranges.lower_bound(Row.Address.Address); if (Range != Ranges.begin() && Range != Ranges.end()) --Range; - if (Range != Ranges.end() && Range->first <= Row.Address && - Range->second.HighPC >= Row.Address) { - StopAddress = Row.Address + Range->second.Offset; + if (Range != Ranges.end() && Range->first <= Row.Address.Address && + Range->second.HighPC >= Row.Address.Address) { + StopAddress = Row.Address.Address + Range->second.Offset; } } } @@ -1768,7 +1768,7 @@ // Insert end sequence row with the computed end address, but // the same line as the previous one. auto NextLine = Seq.back(); - NextLine.Address = StopAddress; + NextLine.Address.Address = StopAddress; NextLine.EndSequence = 1; NextLine.PrologueEnd = 0; NextLine.BasicBlock = 0; @@ -1786,7 +1786,7 @@ continue; // Relocate row address and add it to the current sequence. - Row.Address += CurrRange.value(); + Row.Address.Address += CurrRange.value(); Seq.emplace_back(Row); if (Row.EndSequence) Index: llvm/tools/dsymutil/DwarfStreamer.cpp =================================================================== --- llvm/tools/dsymutil/DwarfStreamer.cpp +++ llvm/tools/dsymutil/DwarfStreamer.cpp @@ -480,11 +480,11 @@ MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MS->EmitULEB128IntValue(PointerSize + 1); MS->EmitIntValue(dwarf::DW_LNE_set_address, 1); - MS->EmitIntValue(Row.Address, PointerSize); + MS->EmitIntValue(Row.Address.Address, PointerSize); LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1); AddressDelta = 0; } else { - AddressDelta = (Row.Address - Address) / MinInstLength; + AddressDelta = (Row.Address.Address - Address) / MinInstLength; } // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. @@ -540,7 +540,7 @@ MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); - Address = Row.Address; + Address = Row.Address.Address; LastLine = Row.Line; RowsSinceLastSequence++; } else { Index: llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h =================================================================== --- llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h +++ llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h @@ -139,14 +139,15 @@ bool usesRegisterOperand(const Instr &InstrMeta) const; // Returns the list of indirect instructions. - const std::set &getIndirectInstructions() const; + const std::set &getIndirectInstructions() const; const MCRegisterInfo *getRegisterInfo() const; const MCInstrInfo *getMCInstrInfo() const; const MCInstrAnalysis *getMCInstrAnalysis() const; // Returns the inlining information for the provided address. - Expected symbolizeInlinedCode(uint64_t Address); + Expected + symbolizeInlinedCode(object::SectionedAddress Address); // Returns whether the provided Graph represents a protected indirect control // flow instruction in this file. @@ -178,7 +179,7 @@ // Disassemble and parse the provided bytes into this object. Instruction // address calculation is done relative to the provided SectionAddress. void parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress); + object::SectionedAddress Address); // Constructs and initialises members required for disassembly. Error initialiseDisassemblyMembers(); @@ -225,7 +226,7 @@ DenseMap> StaticBranchTargetings; // A list of addresses of indirect control flow instructions. - std::set IndirectInstructions; + std::set IndirectInstructions; // The addresses of functions that will trap on CFI violations. SmallSet TrapOnFailFunctionAddresses; Index: llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp =================================================================== --- llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp +++ llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp @@ -254,7 +254,8 @@ return CFCrossReferences; } -const std::set &FileAnalysis::getIndirectInstructions() const { +const std::set & +FileAnalysis::getIndirectInstructions() const { return IndirectInstructions; } @@ -268,8 +269,10 @@ return MIA.get(); } -Expected FileAnalysis::symbolizeInlinedCode(uint64_t Address) { +Expected +FileAnalysis::symbolizeInlinedCode(object::SectionedAddress Address) { assert(Symbolizer != nullptr && "Symbolizer is invalid."); + return Symbolizer->symbolizeInlinedCode(Object->getFileName(), Address); } @@ -457,13 +460,14 @@ ArrayRef SectionBytes((const uint8_t *)SectionContents.data(), Section.getSize()); - parseSectionContents(SectionBytes, Section.getAddress()); + parseSectionContents(SectionBytes, + {Section.getAddress(), Section.getIndex()}); } return Error::success(); } void FileAnalysis::parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress) { + object::SectionedAddress Address) { assert(Symbolizer && "Symbolizer is uninitialised."); MCInst Instruction; Instr InstrMeta; @@ -477,7 +481,7 @@ Byte += InstructionSize; - uint64_t VMAddress = SectionAddress + Byte - InstructionSize; + uint64_t VMAddress = Address.Address + Byte - InstructionSize; InstrMeta.Instruction = Instruction; InstrMeta.VMAddress = VMAddress; InstrMeta.InstructionSize = InstructionSize; @@ -509,8 +513,8 @@ // Check if this instruction exists in the range of the DWARF metadata. if (!IgnoreDWARFFlag) { - auto LineInfo = - Symbolizer->symbolizeCode(Object->getFileName(), VMAddress); + auto LineInfo = Symbolizer->symbolizeCode( + Object->getFileName(), {VMAddress, Address.SectionIndex}); if (!LineInfo) { handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) { errs() << "Symbolizer failed to get line: " << E.message() << "\n"; @@ -522,7 +526,7 @@ continue; } - IndirectInstructions.insert(VMAddress); + IndirectInstructions.insert({VMAddress, Address.SectionIndex}); } } Index: llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h =================================================================== --- llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h +++ llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h @@ -102,7 +102,7 @@ // (i.e. the upwards traversal did not make it to a branch node) flows to the // provided node in GraphResult::OrphanedNodes. static GraphResult buildFlowGraph(const FileAnalysis &Analysis, - uint64_t Address); + object::SectionedAddress Address); private: // Implementation function that actually builds the flow graph. Retrieves a Index: llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp =================================================================== --- llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp +++ llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp @@ -93,17 +93,19 @@ } GraphResult GraphBuilder::buildFlowGraph(const FileAnalysis &Analysis, - uint64_t Address) { + object::SectionedAddress Address) { GraphResult Result; - Result.BaseAddress = Address; + Result.BaseAddress = Address.Address; DenseSet OpenedNodes; const auto &IndirectInstructions = Analysis.getIndirectInstructions(); - if (IndirectInstructions.find(Address) == IndirectInstructions.end()) + // check that IndirectInstructions contains specified Address + if (IndirectInstructions.find(Address) == IndirectInstructions.end()) { return Result; + } - buildFlowGraphImpl(Analysis, OpenedNodes, Result, Address, 0); + buildFlowGraphImpl(Analysis, OpenedNodes, Result, Address.Address, 0); return Result; } Index: llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp =================================================================== --- llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp +++ llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp @@ -130,8 +130,8 @@ std::map BlameCounter; - for (uint64_t Address : Analysis.getIndirectInstructions()) { - const auto &InstrMeta = Analysis.getInstructionOrDie(Address); + for (object::SectionedAddress Address : Analysis.getIndirectInstructions()) { + const auto &InstrMeta = Analysis.getInstructionOrDie(Address.Address); GraphResult Graph = GraphBuilder::buildFlowGraph(Analysis, Address); CFIProtectionStatus ProtectionStatus = @@ -153,7 +153,7 @@ auto InliningInfo = Analysis.symbolizeInlinedCode(Address); if (!InliningInfo || InliningInfo->getNumberOfFrames() == 0) { - errs() << "Failed to symbolise " << format_hex(Address, 2) + errs() << "Failed to symbolise " << format_hex(Address.Address, 2) << " with line tables from " << InputFilename << "\n"; exit(EXIT_FAILURE); } @@ -164,9 +164,9 @@ if (!Summarize) { for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) { const auto &Line = InliningInfo->getFrame(i); - outs() << " " << format_hex(Address, 2) << " = " << Line.FileName - << ":" << Line.Line << ":" << Line.Column << " (" - << Line.FunctionName << ")\n"; + outs() << " " << format_hex(Address.Address, 2) << " = " + << Line.FileName << ":" << Line.Line << ":" << Line.Column + << " (" << Line.FunctionName << ")\n"; } } Index: llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -379,7 +379,12 @@ /// Handle the --lookup option and dump the DIEs and line info for the given /// address. -static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) { +/// TODO: specified Address for --lookup option could relate for several +/// different sections(in case not-linked object file). llvm-dwarfdump +/// need to do something with this: extend lookup option with section +/// information or probably display all matched entries, or something else... +static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address, + raw_ostream &OS) { auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup); if (!DIEsForAddr) @@ -394,7 +399,10 @@ DIEsForAddr.BlockDIE.dump(OS, 4, DumpOpts); } - if (DILineInfo LineInfo = DICtx.getLineInfoForAddress(Lookup)) + // TODO: it is neccessary to set proper SectionIndex here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + if (DILineInfo LineInfo = DICtx.getLineInfoForAddress( + {Lookup, object::SectionedAddress::UndefSection})) LineInfo.dump(OS); return true; @@ -413,7 +421,7 @@ // Handle the --lookup option. if (Lookup) - return lookup(DICtx, Lookup, OS); + return lookup(Obj, DICtx, Lookup, OS); // Handle the --name option. if (!Name.empty()) { Index: llvm/tools/llvm-objdump/MachODump.cpp =================================================================== --- llvm/tools/llvm-objdump/MachODump.cpp +++ llvm/tools/llvm-objdump/MachODump.cpp @@ -7500,7 +7500,7 @@ // Print debug info. if (diContext) { - DILineInfo dli = diContext->getLineInfoForAddress(PC); + DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); // Print valid line info if it changed. if (dli != lastLine && dli.Line != 0) outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -508,7 +508,8 @@ Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); } virtual ~SourcePrinter() = default; - virtual void printSourceLine(raw_ostream &OS, uint64_t Address, + virtual void printSourceLine(raw_ostream &OS, + object::SectionedAddress Address, StringRef Delimiter = "; "); }; @@ -538,7 +539,8 @@ return true; } -void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, +void SourcePrinter::printSourceLine(raw_ostream &OS, + object::SectionedAddress Address, StringRef Delimiter) { if (!Symbolizer) return; @@ -599,14 +601,15 @@ public: virtual ~PrettyPrinter() = default; virtual void printInst(MCInstPrinter &IP, const MCInst *MI, - ArrayRef Bytes, uint64_t Address, - raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP, + ArrayRef Bytes, + object::SectionedAddress Address, raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, + SourcePrinter *SP, std::vector *Rels = nullptr) { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address); if (!NoLeadingAddr) - OS << format("%8" PRIx64 ":", Address); + OS << format("%8" PRIx64 ":", Address.Address); if (!NoShowRawInsn) { OS << "\t"; dumpBytes(Bytes, OS); @@ -633,13 +636,13 @@ } } void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP, + object::SectionedAddress Address, raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, std::vector *Rels) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ""); if (!MI) { - printLead(Bytes, Address, OS); + printLead(Bytes, Address.Address, OS); OS << " "; return; } @@ -661,9 +664,9 @@ std::vector::const_iterator RelCur = Rels->begin(); std::vector::const_iterator RelEnd = Rels->end(); auto PrintReloc = [&]() -> void { - while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address)) { - if (RelCur->getOffset() == Address) { - printRelocation(*RelCur, Address, 4); + while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) { + if (RelCur->getOffset() == Address.Address) { + printRelocation(*RelCur, Address.Address, 4); return; } ++RelCur; @@ -675,7 +678,7 @@ Separator = "\n"; if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ""); - printLead(Bytes, Address, OS); + printLead(Bytes, Address.Address, OS); OS << Preamble; Preamble = " "; StringRef Inst; @@ -693,7 +696,7 @@ OS << " } " << PacketBundle.second; PrintReloc(); Bytes = Bytes.slice(4); - Address += 4; + Address.Address += 4; } } }; @@ -702,8 +705,8 @@ class AMDGCNPrettyPrinter : public PrettyPrinter { public: void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP, + object::SectionedAddress Address, raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, std::vector *Rels) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address); @@ -733,7 +736,7 @@ } } - OS << format("// %012" PRIX64 ": ", Address); + OS << format("// %012" PRIX64 ": ", Address.Address); if (Bytes.size() >=4) { for (auto D : makeArrayRef(reinterpret_cast(Bytes.data()), Bytes.size() / sizeof(U32))) @@ -754,13 +757,13 @@ class BPFPrettyPrinter : public PrettyPrinter { public: void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP, + object::SectionedAddress Address, raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, std::vector *Rels) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address); if (!NoLeadingAddr) - OS << format("%8" PRId64 ":", Address / 8); + OS << format("%8" PRId64 ":", Address.Address / 8); if (!NoShowRawInsn) { OS << "\t"; dumpBytes(Bytes, OS); @@ -1323,9 +1326,10 @@ if (Size == 0) Size = 1; - PIP.printInst( - *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), - SectionAddr + Index + VMAAdjustment, outs(), "", *STI, &SP, &Rels); + PIP.printInst(*IP, Disassembled ? &Inst : nullptr, + Bytes.slice(Index, Size), + {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, + outs(), "", *STI, &SP, &Rels); outs() << CommentStream.str(); Comments.clear(); Index: llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp =================================================================== --- llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -367,6 +367,8 @@ } uint64_t Addr = *AddrOrErr; + object::SectionedAddress Address; + uint64_t Size = P.second; // If we're not using the debug object, compute the address of the // symbol in memory (rather than that in the unrelocated object file) @@ -381,16 +383,20 @@ object::section_iterator Sec = *SecOrErr; StringRef SecName; Sec->getName(SecName); + Address.SectionIndex = Sec->getIndex(); uint64_t SectionLoadAddress = LoadedObjInfo->getSectionLoadAddress(*Sec); if (SectionLoadAddress != 0) Addr += SectionLoadAddress - Sec->getAddress(); - } + } else if (auto SecOrErr = Sym.getSection()) + Address.SectionIndex = SecOrErr.get()->getIndex(); outs() << "Function: " << *Name << ", Size = " << Size << ", Addr = " << Addr << "\n"; - DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); + Address.Address = Addr; + DILineInfoTable Lines = + Context->getLineInfoForAddressRange(Address, Size); for (auto &D : Lines) { outs() << " Line info @ " << D.first - Addr << ": " << D.second.FileName << ", line:" << D.second.Line << "\n"; Index: llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -194,23 +194,54 @@ return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset); } +// This routine returns section index for an address. +// Assumption: would work ambiguously for object files which have sections not +// assigned to an address(since the same address could belong to various +// sections). +static uint64_t getModuleSectionIndexForAddress(const std::string &ModuleName, + uint64_t Address) { + + Expected> BinaryOrErr = createBinary(ModuleName); + + if (error(BinaryOrErr)) + return object::SectionedAddress::UndefSection; + + Binary &Binary = *BinaryOrErr->getBinary(); + + if (ObjectFile *O = dyn_cast(&Binary)) { + for (SectionRef Sec : O->sections()) { + if (!Sec.isText() || Sec.isVirtual()) + continue; + + if (Address >= Sec.getAddress() && + Address <= Sec.getAddress() + Sec.getSize()) { + return Sec.getIndex(); + } + } + } + + return object::SectionedAddress::UndefSection; +} + static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer, DIPrinter &Printer) { bool IsData = false; std::string ModuleName; - uint64_t ModuleOffset = 0; - if (!parseCommand(StringRef(InputString), IsData, ModuleName, ModuleOffset)) { + uint64_t Offset = 0; + if (!parseCommand(StringRef(InputString), IsData, ModuleName, Offset)) { outs() << InputString; return; } if (ClPrintAddress) { outs() << "0x"; - outs().write_hex(ModuleOffset); + outs().write_hex(Offset); StringRef Delimiter = ClPrettyPrint ? ": " : "\n"; outs() << Delimiter; } - ModuleOffset -= ClAdjustVMA; + Offset -= ClAdjustVMA; + object::SectionedAddress ModuleOffset = { + Offset, getModuleSectionIndexForAddress(ModuleName, Offset)}; if (IsData) { auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset); Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get()); Index: llvm/tools/llvm-xray/func-id-helper.cpp =================================================================== --- llvm/tools/llvm-xray/func-id-helper.cpp +++ llvm/tools/llvm-xray/func-id-helper.cpp @@ -29,7 +29,12 @@ return F.str(); } - if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second)) { + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = It->second; + // TODO: set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection; + if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, ModuleAddress)) { auto &DI = *ResOrErr; if (DI.FunctionName == "") F << "@(" << std::hex << It->second << ")"; @@ -51,7 +56,12 @@ return "(unknown)"; std::ostringstream F; - auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second); + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = It->second; + // TODO: set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection; + auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, ModuleAddress); if (!ResOrErr) { consumeError(ResOrErr.takeError()); return "(unknown)"; Index: llvm/tools/sancov/sancov.cpp =================================================================== --- llvm/tools/sancov/sancov.cpp +++ llvm/tools/sancov/sancov.cpp @@ -621,10 +621,17 @@ std::set CoveredFiles; if (ClSkipDeadFiles) { for (auto Addr : CoveredAddrs) { - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + // TODO: it would be neccessary to set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute + // addresses. + object::SectionedAddress ModuleAddress = { + Addr, object::SectionedAddress::UndefSection}; + + auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress); failIfError(LineInfo); CoveredFiles.insert(LineInfo->FileName); - auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr); + auto InliningInfo = + Symbolizer->symbolizeInlinedCode(ObjectFile, ModuleAddress); failIfError(InliningInfo); for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) { auto FrameInfo = InliningInfo->getFrame(I); @@ -636,7 +643,12 @@ for (auto Addr : Addrs) { std::set Infos; // deduplicate debug info. - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + // TODO: it would be neccessary to set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + object::SectionedAddress ModuleAddress = { + Addr, object::SectionedAddress::UndefSection}; + + auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress); failIfError(LineInfo); if (ClSkipDeadFiles && CoveredFiles.find(LineInfo->FileName) == CoveredFiles.end()) @@ -650,7 +662,8 @@ Infos.insert(*LineInfo); Point.Locs.push_back(*LineInfo); - auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr); + auto InliningInfo = + Symbolizer->symbolizeInlinedCode(ObjectFile, ModuleAddress); failIfError(InliningInfo); for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) { auto FrameInfo = InliningInfo->getFrame(I); @@ -957,7 +970,10 @@ auto Symbolizer(createSymbolizer()); for (uint64_t Addr : *Data.Addrs) { - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + // TODO: it would be neccessary to set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + auto LineInfo = Symbolizer->symbolizeCode( + ObjectFile, {Addr, object::SectionedAddress::UndefSection}); failIfError(LineInfo); if (B.isBlacklisted(*LineInfo)) continue; Index: llvm/tools/sanstats/sanstats.cpp =================================================================== --- llvm/tools/sanstats/sanstats.cpp +++ llvm/tools/sanstats/sanstats.cpp @@ -84,8 +84,10 @@ // As the instrumentation tracks the return address and not // the address of the call to `__sanitizer_stat_report` we // remove one from the address to get the correct DI. - if (Expected LineInfo = - Symbolizer.symbolizeCode(Filename, Addr - 1)) { + // TODO: it would be neccessary to set proper section index here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + if (Expected LineInfo = Symbolizer.symbolizeCode( + Filename, {Addr - 1, object::SectionedAddress::UndefSection})) { llvm::outs() << format_hex(Addr - 1, 18) << ' ' << LineInfo->FileName << ':' << LineInfo->Line << ' ' << LineInfo->FunctionName << ' '; Index: llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp =================================================================== --- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp +++ llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp @@ -51,8 +51,8 @@ // Expose this method publicly for testing. void parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress) { - FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); + object::SectionedAddress Address) { + FileAnalysis::parseSectionContents(SectionBytes, Address); } Error initialiseDisassemblyMembers() { @@ -106,7 +106,7 @@ 0x41, 0x0e, // 21: rex.B (bad) 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); EXPECT_EQ(nullptr, Analysis.getInstruction(0x0)); EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000)); @@ -210,7 +210,7 @@ 0x2f, // 1: (bad) 0x90 // 2: nop }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1); const auto *GoodInstrMeta = Analysis.getPrevInstructionSequential(BadInstrMeta); @@ -240,7 +240,7 @@ 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 0x0f, 0x0b // 28: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF))); EXPECT_FALSE( @@ -275,7 +275,7 @@ 0x75, 0x00, // 17: jne +0 0xc3, // 19: retq }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); EXPECT_TRUE( Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF))); @@ -322,7 +322,7 @@ 0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdc, // 38: jmp 4 [-36] }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); const auto *Current = Analysis.getInstruction(0xDEADBEEF); const auto *Next = Analysis.getDefiniteNextInstruction(*Current); @@ -412,7 +412,7 @@ 0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdc, // 38: jmp 4 [-36] }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF); std::set XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); @@ -503,17 +503,18 @@ 0x0f, 0x0b, // 1: ud2 0x75, 0x00, // 3: jne 5 [+0] }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); + Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0x12345678); + Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION, Analysis.validateCFIProtection(Result)); } @@ -527,8 +528,9 @@ 0x0f, 0x0b, // 2: ud2 0xff, 0x10, // 4: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -542,8 +544,9 @@ 0xff, 0x10, // 2: callq *(%rax) 0x0f, 0x0b, // 4: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -560,8 +563,9 @@ 0x75, 0xf9, // 7: jne 2 [-7] 0x0f, 0x0b, // 9: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -577,8 +581,9 @@ 0x75, 0xfb, // 5: jne 2 [-5] 0x0f, 0x0b, // 7: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -596,12 +601,13 @@ 0xff, 0x10, // 6: callq *(%rax) 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); uint64_t PrevSearchLengthForConditionalBranch = SearchLengthForConditionalBranch; SearchLengthForConditionalBranch = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); @@ -621,11 +627,12 @@ 0x90, // 7: nop 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, Analysis.validateCFIProtection(Result)); @@ -642,8 +649,9 @@ 0xff, 0x10, // 4: callq *(%rax) 0x0f, 0x0b, // 6: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); } @@ -658,8 +666,9 @@ 0xff, 0x10, // 4: callq *(%rax) 0x0f, 0x0b, // 6: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -685,10 +694,11 @@ 0x90, // 21: nop 0x0f, 0x0b, // 22: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 5; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = PrevSearchLengthForUndef; @@ -704,10 +714,10 @@ 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130 0x0f, 0x0b, // 0x688127: ud2 }, - 0x688118); + {0x688118, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 1; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x68811d); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = PrevSearchLengthForUndef; @@ -719,7 +729,7 @@ 0x74, 0x73, // 0x7759eb: je 0x775a60 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e }, - 0x7759eb); + {0x7759eb, 0x0}); Analysis.parseSectionContents( { @@ -729,24 +739,24 @@ 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi 0xff, 0xd1, // 0x775a68: callq *%rcx }, - 0x775a56); + {0x775a56, 0x0}); Analysis.parseSectionContents( { 0x0f, 0x0b, // 0x775e0e: ud2 }, - 0x775e0e); + {0x775e0e, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 1; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = 2; - Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = 3; - Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = PrevSearchLengthForUndef; @@ -762,8 +772,9 @@ 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax 0xff, 0x10, // 10: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 10); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -778,8 +789,9 @@ 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax 0xff, 0x10, // 8: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -794,8 +806,9 @@ 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax 0xff, 0x10, // 9: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -812,8 +825,9 @@ 0x75, 0xf9, // 8: jne 2 [-7] 0x0f, 0x0b, // 10: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -825,8 +839,9 @@ { 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); } @@ -840,8 +855,9 @@ 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -856,8 +872,9 @@ 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -872,8 +889,9 @@ 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 0x20, 0x00, 0x1f, 0xd6, // 12: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -889,8 +907,9 @@ 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -906,8 +925,9 @@ 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -923,8 +943,9 @@ 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -940,8 +961,9 @@ 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16] 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -957,8 +979,9 @@ 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -974,8 +997,9 @@ 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16] 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -990,8 +1014,9 @@ 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1 0x20, 0x00, 0x1f, 0xd6, // 12: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); } @@ -1009,8 +1034,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 20: br x1 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 20); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0}); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -1029,8 +1055,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -1049,8 +1076,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0}); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } Index: llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp =================================================================== --- llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp +++ llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp @@ -113,8 +113,8 @@ // Expose this method publicly for testing. void parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress) { - FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); + object::SectionedAddress Address) { + FileAnalysis::parseSectionContents(SectionBytes, Address); } Error initialiseDisassemblyMembers() { @@ -156,8 +156,9 @@ 0x0f, 0x0b, // 2: ud2 0xff, 0x10, // 4: callq *(%rax) }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); @@ -182,8 +183,9 @@ 0xff, 0x10, // 2: callq *(%rax) 0x0f, 0x0b, // 4: ud2 }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + {0xDEADBEEF, 0x0}); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); @@ -211,8 +213,9 @@ 0x75, 0xf9, // 7: jne 2 [-7] 0x0f, 0x0b, // 9: ud2 }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + {0xDEADBEEF, 0x0}); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); @@ -249,8 +252,9 @@ 0x75, 0xfb, // 5: jne 2 [-5] 0x0f, 0x0b, // 7: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); @@ -284,16 +288,17 @@ 0x90, // 0: nop 0x75, 0xfe, // 1: jne 1 [-2] }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); + Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADC0DE); + Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADC0DE, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); } @@ -306,8 +311,9 @@ 0xeb, 0xfe, // 0: jmp 0 [-2] 0xff, 0x10, // 2: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 2)); EXPECT_THAT(Result.IntermediateNodes, IsEmpty()); @@ -321,8 +327,9 @@ 0x75, 0xfe, // 0: jne 0 [-2] 0xff, 0x10, // 2: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT( @@ -344,8 +351,9 @@ 0xeb, 0xfc, // 2: jmp 0 [-4] 0xff, 0x10, // 4: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT( @@ -368,8 +376,9 @@ 0xeb, 0xfc, // 2: jmp 0 [-4] 0xff, 0x10, // 4: callq *(%rax) }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 4)); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); } @@ -387,12 +396,13 @@ 0xff, 0x10, // 6: callq *(%rax) 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); uint64_t PrevSearchLengthForConditionalBranch = SearchLengthForConditionalBranch; SearchLengthForConditionalBranch = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0}); EXPECT_THAT(Result.OrphanedNodes, SizeIs(1)); EXPECT_THAT(Result.OrphanedNodes, Each(HasPath(Result, ElementsAre(0xDEADBEEF + 4, 0xDEADBEEF + 5, @@ -416,11 +426,12 @@ 0x90, // 7: nop 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + {0xDEADBEEF, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT( Result.ConditionalBranchNodes, @@ -450,8 +461,9 @@ 0x75, 0xfb, // 5: jne 2 [-5] 0x0f, 0x0b, // 7: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + {0xDEADBEEF, 0x0}); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); EXPECT_THAT( @@ -529,11 +541,12 @@ 0x90, // 21: nop 0x0f, 0x0b, // 22: ud2 }, - 0x1000); + {0x1000, 0x0}); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 5; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x1000 + 9); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, {0x1000 + 9, 0x0}); EXPECT_THAT(Result.OrphanedNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(3));